/// Domain Entity: Design Request
///
/// Represents a request for design consultation service.
library;

import 'package:worker/features/projects/domain/entities/project_type.dart';

/// Design status enum
enum DesignStatus {
  /// Request submitted, pending assignment
  pending,

  /// Assigned to designer
  assigned,

  /// Design in progress
  inProgress,

  /// Design completed
  completed,

  /// Request cancelled
  cancelled;

  /// Get display name for status
  String get displayName {
    switch (this) {
      case DesignStatus.pending:
        return 'Pending';
      case DesignStatus.assigned:
        return 'Assigned';
      case DesignStatus.inProgress:
        return 'In Progress';
      case DesignStatus.completed:
        return 'Completed';
      case DesignStatus.cancelled:
        return 'Cancelled';
    }
  }
}

/// Design Request Entity
///
/// Contains information about a design consultation request:
/// - Project requirements
/// - Design preferences
/// - Budget constraints
/// - Assignment and tracking
class DesignRequest {
  /// Unique request identifier
  final String requestId;

  /// User ID who requested
  final String userId;

  /// Project name
  final String projectName;

  /// Project type
  final ProjectType projectType;

  /// Project area (square meters)
  final double area;

  /// Design style preference
  final String? style;

  /// Budget for design/construction
  final double? budget;

  /// Current situation description
  final String? currentSituation;

  /// Requirements and wishes
  final String? requirements;

  /// Additional notes
  final String? notes;

  /// Attachment URLs (photos, references)
  final List<String> attachments;

  /// Request status
  final DesignStatus status;

  /// Assigned designer name
  final String? assignedDesigner;

  /// Final design link/URL
  final String? finalDesignLink;

  /// User feedback
  final String? feedback;

  /// User rating (1-5)
  final int? rating;

  /// Estimated completion date
  final DateTime? estimatedCompletion;

  /// Request creation timestamp
  final DateTime createdAt;

  /// Completion timestamp
  final DateTime? completedAt;

  /// Last update timestamp
  final DateTime updatedAt;

  const DesignRequest({
    required this.requestId,
    required this.userId,
    required this.projectName,
    required this.projectType,
    required this.area,
    this.style,
    this.budget,
    this.currentSituation,
    this.requirements,
    this.notes,
    required this.attachments,
    required this.status,
    this.assignedDesigner,
    this.finalDesignLink,
    this.feedback,
    this.rating,
    this.estimatedCompletion,
    required this.createdAt,
    this.completedAt,
    required this.updatedAt,
  });

  /// Check if request is pending
  bool get isPending => status == DesignStatus.pending;

  /// Check if request is assigned
  bool get isAssigned =>
      status == DesignStatus.assigned || status == DesignStatus.inProgress;

  /// Check if request is in progress
  bool get isInProgress => status == DesignStatus.inProgress;

  /// Check if request is completed
  bool get isCompleted => status == DesignStatus.completed;

  /// Check if request is cancelled
  bool get isCancelled => status == DesignStatus.cancelled;

  /// Check if request has attachments
  bool get hasAttachments => attachments.isNotEmpty;

  /// Check if design is ready
  bool get hasDesign => finalDesignLink != null && finalDesignLink!.isNotEmpty;

  /// Check if user has provided feedback
  bool get hasFeedback => feedback != null || rating != null;

  /// Get completion duration
  Duration? get completionDuration {
    if (completedAt == null) return null;
    return completedAt!.difference(createdAt);
  }

  /// Check if overdue
  bool get isOverdue {
    if (estimatedCompletion == null || isCompleted || isCancelled) {
      return false;
    }
    return DateTime.now().isAfter(estimatedCompletion!);
  }

  /// Copy with method for immutability
  DesignRequest copyWith({
    String? requestId,
    String? userId,
    String? projectName,
    ProjectType? projectType,
    double? area,
    String? style,
    double? budget,
    String? currentSituation,
    String? requirements,
    String? notes,
    List<String>? attachments,
    DesignStatus? status,
    String? assignedDesigner,
    String? finalDesignLink,
    String? feedback,
    int? rating,
    DateTime? estimatedCompletion,
    DateTime? createdAt,
    DateTime? completedAt,
    DateTime? updatedAt,
  }) {
    return DesignRequest(
      requestId: requestId ?? this.requestId,
      userId: userId ?? this.userId,
      projectName: projectName ?? this.projectName,
      projectType: projectType ?? this.projectType,
      area: area ?? this.area,
      style: style ?? this.style,
      budget: budget ?? this.budget,
      currentSituation: currentSituation ?? this.currentSituation,
      requirements: requirements ?? this.requirements,
      notes: notes ?? this.notes,
      attachments: attachments ?? this.attachments,
      status: status ?? this.status,
      assignedDesigner: assignedDesigner ?? this.assignedDesigner,
      finalDesignLink: finalDesignLink ?? this.finalDesignLink,
      feedback: feedback ?? this.feedback,
      rating: rating ?? this.rating,
      estimatedCompletion: estimatedCompletion ?? this.estimatedCompletion,
      createdAt: createdAt ?? this.createdAt,
      completedAt: completedAt ?? this.completedAt,
      updatedAt: updatedAt ?? this.updatedAt,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is DesignRequest &&
        other.requestId == requestId &&
        other.userId == userId &&
        other.projectName == projectName &&
        other.area == area &&
        other.status == status;
  }

  @override
  int get hashCode {
    return Object.hash(requestId, userId, projectName, area, status);
  }

  @override
  String toString() {
    return 'DesignRequest(requestId: $requestId, projectName: $projectName, '
        'projectType: $projectType, area: $area, status: $status, '
        'assignedDesigner: $assignedDesigner)';
  }
}
