import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
import 'package:krow/core/data/models/event/addon_model.dart';
import 'package:krow/core/data/models/event/business_member_model.dart';
import 'package:krow/core/data/models/event/event_model.dart';
import 'package:krow/core/data/models/event/hub_model.dart';
import 'package:krow/core/data/models/event/tag_model.dart';
import 'package:krow/core/entity/position_entity.dart';
import 'package:krow/core/entity/shift_entity.dart';

enum EventStatus {
  pending,
  assigned,
  confirmed,
  active,
  finished,
  completed,
  closed,
  canceled,
  draft
}

class EventEntity {
  final String id;
  final EventStatus? status;
  final String name;
  DateTime? startDate;
  DateTime? endDate;
  final String? cursor;
  final ValueNotifier<double> totalCost = ValueNotifier(0.0);
  final HubModel? hub;
  final List<AddonModel>? addons;
  final BusinessMemberModel? completedBy;
  final String? completedNode;
  final String? additionalInfo;

  // final EventContractType contractType;
  final List<ShiftEntity>? shifts;
  final String? poNumber;

  // final String? contractNumber;
  final EventModel? dto;
  final List<TagModel>? tags;

  EventEntity(
      {required this.id,
      this.status,
      required this.name,
      required this.startDate,
      required this.endDate,
      this.completedBy,
      this.completedNode,
      this.hub,
      this.addons,
      this.additionalInfo,
      // this.contractType = EventContractType.direct,
      this.shifts,
      this.cursor,
      this.poNumber,
      // this.contractNumber,
      this.dto,
      this.tags});

  static EventEntity fromEventDto(EventModel event, {String? cursor}) {

    var date = DateFormat('yyyy-MM-dd').parse(event.date);

    var entity = EventEntity(
        id: event.id,
        status: event.status,
        name: event.name,
        startDate: date,
        endDate: date,
        completedBy: null,
        completedNode: null,
        hub: event.hub,
        shifts: event.shifts
            .map<ShiftEntity>((shift) => ShiftEntity.fromDto(shift, date))
            .toList(),
        addons: event.addons,
        additionalInfo: event.additionalInfo,
        // contractType: event.contractType,
        poNumber: event.purchaseOrder,
        cursor: cursor,
        dto: event,
        tags: event.tags);

    entity.totalCost.value =
        EventEntity.getTotalCost(entity); // Calculate total cost

    try {
      entity.shifts?.forEach((element) {
        element.parentEvent = entity;
      });
    } catch (e) {
      print(e);
    }

    return entity;
  }

  EventEntity copyWith(
      {String? id,
      EventStatus? status,
      String? name,
      DateTime? startDate,
      DateTime? endDate,
      BusinessMemberModel? completedBy,
      String? completedNode,
      HubModel? hub,
      List<AddonModel>? addons,
      String? additionalInfo,
      EventContractType? contractType,
      List<ShiftEntity>? shifts,
      String? poNumber,
      String? contractNumber,
      String? cursor,
      List<TagModel>? tags}) {
    var entity = EventEntity(
        id: id ?? this.id,
        status: status ?? this.status,
        name: name ?? this.name,
        startDate: startDate ?? this.startDate,
        endDate: endDate ?? this.endDate,
        hub: hub ?? this.hub,
        completedBy: completedBy ?? this.completedBy,
        completedNode: completedNode ?? this.completedNode,
        addons: addons ?? this.addons,
        additionalInfo: additionalInfo ?? this.additionalInfo,
        // contractType: contractType ?? this.contractType,
        shifts: shifts ?? this.shifts,
        poNumber: poNumber ?? this.poNumber,
        // contractNumber: contractNumber ?? this.contractNumber,
        cursor: cursor ?? this.cursor,
        tags: tags ?? this.tags);

    entity.totalCost.value =
        EventEntity.getTotalCost(entity); // Calculate total cost

    entity.shifts?.forEach((element) {
      element.parentEvent = entity;
    });
    return entity;
  }

  static empty() {
    var entity = EventEntity(
        id: '',
        name: '',
        startDate: null,
        endDate: null,
        hub: null,
        completedBy: null,
        completedNode: null,
        addons: [],
        additionalInfo: '',
        // contractType: EventContractType.direct,
        shifts: [ShiftEntity.empty()],
        poNumber: '',
        // contractNumber: '',
        cursor: null,
        tags: []);
    entity.shifts?.forEach((element) {
      element.parentEvent = entity;
    });
    return entity;
  }

  static double getTotalCost(EventEntity event) {
    foldPosition(previousValue, PositionEntity position) {
      return (previousValue ?? 0) +
          ((((position.businessSkill?.price ?? 0) * (position.count ?? 0)) /
                  60) *
              (position.endTime.difference(position.startTime).inMinutes));
    }

    foldRoles(previousValue, ShiftEntity shift) {
      return previousValue + (shift.positions.fold(0.0, foldPosition));
    }

    var eventCost = event.shifts?.fold(0.0, foldRoles) ?? 0;

    double totalCost = eventCost +
        (event.addons?.fold(0.0,
                (previousValue, addon) => previousValue + (addon.price ?? 0)) ??
            0);

    return totalCost;
  }

  @override
  int get hashCode =>
      id.hashCode ^
      status.hashCode ^
      name.hashCode ^
      startDate.hashCode ^
      endDate.hashCode ^
      cursor.hashCode ^
      totalCost.hashCode ^
      hub.hashCode ^
      addons.hashCode ^
      completedBy.hashCode ^
      completedNode.hashCode ^
      additionalInfo.hashCode ^
      shifts.hashCode ^
      poNumber.hashCode ^
      dto.hashCode ^
      tags.hashCode;

  @override
  bool operator ==(Object other) {
    return super == (other) &&
        other is EventEntity &&
        id == other.id &&
        status == other.status &&
        name == other.name &&
        startDate == other.startDate &&
        endDate == other.endDate &&
        cursor == other.cursor &&
        totalCost.value == other.totalCost.value &&
        hub == other.hub &&
        addons == other.addons &&
        completedBy == other.completedBy &&
        completedNode == other.completedNode &&
        additionalInfo == other.additionalInfo &&
        shifts == other.shifts &&
        poNumber == other.poNumber &&
        dto == other.dto &&
        tags == other.tags;
  }
}
