/// Domain Entity: Project Submission
///
/// Represents a completed project submitted for loyalty points.
library;

/// Project type enum
enum ProjectType {
  /// Residential project
  residential,

  /// Commercial project
  commercial,

  /// Industrial project
  industrial,

  /// Public infrastructure
  infrastructure,

  /// Other type
  other;

  /// Get display name for project type
  String get displayName {
    switch (this) {
      case ProjectType.residential:
        return 'Residential';
      case ProjectType.commercial:
        return 'Commercial';
      case ProjectType.industrial:
        return 'Industrial';
      case ProjectType.infrastructure:
        return 'Infrastructure';
      case ProjectType.other:
        return 'Other';
    }
  }
}

/// Submission status enum
enum SubmissionStatus {
  /// Submitted, pending review
  pending,

  /// Under review
  reviewing,

  /// Approved, points awarded
  approved,

  /// Rejected
  rejected;

  /// Get display name for status
  String get displayName {
    switch (this) {
      case SubmissionStatus.pending:
        return 'Pending';
      case SubmissionStatus.reviewing:
        return 'Reviewing';
      case SubmissionStatus.approved:
        return 'Approved';
      case SubmissionStatus.rejected:
        return 'Rejected';
    }
  }
}

/// Project Submission Entity
///
/// Contains information about a completed project:
/// - Project details
/// - Before/after photos
/// - Invoice documentation
/// - Review status
/// - Points earned
class ProjectSubmission {
  /// Unique submission identifier
  final String submissionId;

  /// User ID who submitted
  final String userId;

  /// Project name
  final String projectName;

  /// Project address/location
  final String? projectAddress;

  /// Project value/cost
  final double projectValue;

  /// Project type
  final ProjectType projectType;

  /// Before photos URLs
  final List<String> beforePhotos;

  /// After photos URLs
  final List<String> afterPhotos;

  /// Invoice/receipt URLs
  final List<String> invoices;

  /// Submission status
  final SubmissionStatus status;

  /// Review notes from admin
  final String? reviewNotes;

  /// Rejection reason (if rejected)
  final String? rejectionReason;

  /// Points earned (if approved)
  final int? pointsEarned;

  /// Submission timestamp
  final DateTime submittedAt;

  /// Review timestamp
  final DateTime? reviewedAt;

  /// ID of admin who reviewed
  final String? reviewedBy;

  const ProjectSubmission({
    required this.submissionId,
    required this.userId,
    required this.projectName,
    this.projectAddress,
    required this.projectValue,
    required this.projectType,
    required this.beforePhotos,
    required this.afterPhotos,
    required this.invoices,
    required this.status,
    this.reviewNotes,
    this.rejectionReason,
    this.pointsEarned,
    required this.submittedAt,
    this.reviewedAt,
    this.reviewedBy,
  });

  /// Check if submission is pending
  bool get isPending => status == SubmissionStatus.pending;

  /// Check if submission is under review
  bool get isReviewing => status == SubmissionStatus.reviewing;

  /// Check if submission is approved
  bool get isApproved => status == SubmissionStatus.approved;

  /// Check if submission is rejected
  bool get isRejected => status == SubmissionStatus.rejected;

  /// Check if submission has been reviewed
  bool get isReviewed =>
      status == SubmissionStatus.approved ||
      status == SubmissionStatus.rejected;

  /// Check if submission has before photos
  bool get hasBeforePhotos => beforePhotos.isNotEmpty;

  /// Check if submission has after photos
  bool get hasAfterPhotos => afterPhotos.isNotEmpty;

  /// Check if submission has invoices
  bool get hasInvoices => invoices.isNotEmpty;

  /// Get total number of photos
  int get totalPhotos => beforePhotos.length + afterPhotos.length;

  /// Get review duration
  Duration? get reviewDuration {
    if (reviewedAt == null) return null;
    return reviewedAt!.difference(submittedAt);
  }

  /// Copy with method for immutability
  ProjectSubmission copyWith({
    String? submissionId,
    String? userId,
    String? projectName,
    String? projectAddress,
    double? projectValue,
    ProjectType? projectType,
    List<String>? beforePhotos,
    List<String>? afterPhotos,
    List<String>? invoices,
    SubmissionStatus? status,
    String? reviewNotes,
    String? rejectionReason,
    int? pointsEarned,
    DateTime? submittedAt,
    DateTime? reviewedAt,
    String? reviewedBy,
  }) {
    return ProjectSubmission(
      submissionId: submissionId ?? this.submissionId,
      userId: userId ?? this.userId,
      projectName: projectName ?? this.projectName,
      projectAddress: projectAddress ?? this.projectAddress,
      projectValue: projectValue ?? this.projectValue,
      projectType: projectType ?? this.projectType,
      beforePhotos: beforePhotos ?? this.beforePhotos,
      afterPhotos: afterPhotos ?? this.afterPhotos,
      invoices: invoices ?? this.invoices,
      status: status ?? this.status,
      reviewNotes: reviewNotes ?? this.reviewNotes,
      rejectionReason: rejectionReason ?? this.rejectionReason,
      pointsEarned: pointsEarned ?? this.pointsEarned,
      submittedAt: submittedAt ?? this.submittedAt,
      reviewedAt: reviewedAt ?? this.reviewedAt,
      reviewedBy: reviewedBy ?? this.reviewedBy,
    );
  }

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

    return other is ProjectSubmission &&
        other.submissionId == submissionId &&
        other.userId == userId &&
        other.projectName == projectName &&
        other.projectValue == projectValue &&
        other.status == status;
  }

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

  @override
  String toString() {
    return 'ProjectSubmission(submissionId: $submissionId, projectName: $projectName, '
        'projectValue: $projectValue, projectType: $projectType, status: $status, '
        'pointsEarned: $pointsEarned)';
  }
}
