enum WorkOrderStatus {
  open,
  completed;

  String get databaseValue => name;

  static WorkOrderStatus fromDatabase(String value) {
    return WorkOrderStatus.values.firstWhere(
      (status) => status.name == value,
      orElse: () => WorkOrderStatus.open,
    );
  }
}

enum PhotoKind {
  before,
  after;

  String get databaseValue => name;

  static PhotoKind fromDatabase(String value) {
    return value == PhotoKind.after.name ? PhotoKind.after : PhotoKind.before;
  }
}

class TaskPhoto {
  const TaskPhoto({required this.id, required this.path, required this.kind});

  final String id;
  final String path;
  final PhotoKind kind;
}

class TaskPart {
  const TaskPart({required this.id, required this.name, required this.price});

  final String id;
  final String name;
  final int price;
}

class WorkTask {
  const WorkTask({
    required this.id,
    required this.title,
    required this.observation,
    required this.position,
    this.photos = const [],
    this.parts = const [],
  });

  final String id;
  final String title;
  final String observation;
  final int position;
  final List<TaskPhoto> photos;
  final List<TaskPart> parts;

  List<TaskPhoto> get beforePhotos =>
      photos.where((photo) => photo.kind == PhotoKind.before).toList();

  List<TaskPhoto> get afterPhotos =>
      photos.where((photo) => photo.kind == PhotoKind.after).toList();

  int get partsTotal => parts.fold(0, (total, part) => total + part.price);
}

class WorkOrderDetails {
  const WorkOrderDetails({
    this.client = '',
    this.phone = '',
    this.address = '',
  });

  final String client;
  final String phone;
  final String address;

  bool get isComplete =>
      client.trim().isNotEmpty &&
      phone.trim().isNotEmpty &&
      address.trim().isNotEmpty;

  WorkOrderDetails copyWith({String? client, String? phone, String? address}) {
    return WorkOrderDetails(
      client: client ?? this.client,
      phone: phone ?? this.phone,
      address: address ?? this.address,
    );
  }
}

class WorkOrder {
  const WorkOrder({
    required this.id,
    required this.title,
    required this.createdAt,
    required this.updatedAt,
    required this.status,
    this.details = const WorkOrderDetails(),
    this.laborCost = 0,
    this.completedAt,
    this.recipientEmail,
    this.pdfPath,
    this.tasks = const [],
  });

  final String id;
  final String title;
  final DateTime createdAt;
  final DateTime updatedAt;
  final DateTime? completedAt;
  final WorkOrderStatus status;
  final WorkOrderDetails details;
  final int laborCost;
  final String? recipientEmail;
  final String? pdfPath;
  final List<WorkTask> tasks;

  bool get isCompleted => status == WorkOrderStatus.completed;

  int get totalPhotos =>
      tasks.fold(0, (total, task) => total + task.photos.length);

  int get totalPartsCost =>
      tasks.fold(0, (total, task) => total + task.partsTotal);

  int get totalCost => laborCost + totalPartsCost;

  WorkOrder copyWith({
    String? title,
    DateTime? updatedAt,
    DateTime? completedAt,
    WorkOrderStatus? status,
    WorkOrderDetails? details,
    int? laborCost,
    String? recipientEmail,
    String? pdfPath,
    List<WorkTask>? tasks,
  }) {
    return WorkOrder(
      id: id,
      title: title ?? this.title,
      createdAt: createdAt,
      updatedAt: updatedAt ?? this.updatedAt,
      completedAt: completedAt ?? this.completedAt,
      status: status ?? this.status,
      details: details ?? this.details,
      laborCost: laborCost ?? this.laborCost,
      recipientEmail: recipientEmail ?? this.recipientEmail,
      pdfPath: pdfPath ?? this.pdfPath,
      tasks: tasks ?? this.tasks,
    );
  }
}
