import '../../shared/models/approval_status.dart';

class ExpenseApplicationModel {
  final String id;
  final String applicationNo;
  final String applicantId;
  final String applicantName;
  final String deptId;
  final String deptName;
  final String expenseType;
  final List<String> expenseTypes;
  final double estimatedAmount;
  final String purpose;
  final String remark;
  final String status;
  final String currentApproverId;
  final List<String> approvalChain;
  final DateTime createTime;
  final DateTime updateTime;
  final DateTime? estimatedStartDate;
  final DateTime? estimatedEndDate;
  final String urgency;
  final String projectId;
  final String projectName;
  final String budgetSubjectId;
  final String budgetSubjectName;
  final double availableBalance;
  final bool isTaxIncluded;
  final DateTime? validUntil;
  final String referenceNo;
  final String usageStatus;
  // 差旅费专用
  final bool isOvernight;
  final String transportMode;
  // 招待费专用
  final String entertainTarget;
  final String entertainLevel;
  final int guestCount;
  final int hostCount;
  final String entertainLocation;
  // 会议费专用
  final DateTime? meetingDate;
  final String meetingLocation;
  final List<ExpenseAppDetailModel> details;
  final List<String> attachments;
  final List<ApprovalRecord> approvalRecords;

  const ExpenseApplicationModel({
    required this.id,
    required this.applicationNo,
    this.applicantId = '',
    this.applicantName = '',
    this.deptId = '',
    this.deptName = '',
    this.expenseType = '',
    this.expenseTypes = const [],
    this.estimatedAmount = 0.0,
    this.purpose = '',
    this.remark = '',
    this.status = 'draft',
    this.currentApproverId = '',
    this.approvalChain = const [],
    required this.createTime,
    required this.updateTime,
    this.estimatedStartDate,
    this.estimatedEndDate,
    this.urgency = 'normal',
    this.projectId = '',
    this.projectName = '',
    this.budgetSubjectId = '',
    this.budgetSubjectName = '',
    this.availableBalance = 0.0,
    this.isTaxIncluded = false,
    this.validUntil,
    this.referenceNo = '',
    this.usageStatus = 'unused',
    this.isOvernight = false,
    this.transportMode = '',
    this.entertainTarget = '',
    this.entertainLevel = '',
    this.guestCount = 0,
    this.hostCount = 0,
    this.entertainLocation = '',
    this.meetingDate,
    this.meetingLocation = '',
    this.details = const [],
    this.attachments = const [],
    this.approvalRecords = const [],
  });

  factory ExpenseApplicationModel.fromJson(Map<String, dynamic> json) {
    return ExpenseApplicationModel(
      id: json['id'] as String,
      applicationNo: json['applicationNo'] as String? ?? '',
      applicantId: json['applicantId'] as String? ?? '',
      applicantName: json['applicantName'] as String? ?? '',
      deptId: json['deptId'] as String? ?? '',
      deptName: json['deptName'] as String? ?? '',
      expenseType: json['expenseType'] as String? ?? '',
      expenseTypes: (json['expenseTypes'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
      estimatedAmount: (json['estimatedAmount'] as num?)?.toDouble() ?? 0.0,
      purpose: json['purpose'] as String? ?? '',
      remark: json['remark'] as String? ?? '',
      status: json['status'] as String? ?? 'draft',
      currentApproverId: json['currentApproverId'] as String? ?? '',
      approvalChain:
          (json['approvalChain'] as List<dynamic>?)
              ?.map((e) => e as String)
              .toList() ??
          [],
      createTime: DateTime.parse(json['createTime'] as String),
      updateTime: DateTime.parse(json['updateTime'] as String),
      estimatedStartDate: json['estimatedStartDate'] != null
          ? DateTime.parse(json['estimatedStartDate'] as String)
          : null,
      estimatedEndDate: json['estimatedEndDate'] != null
          ? DateTime.parse(json['estimatedEndDate'] as String)
          : null,
      urgency: json['urgency'] as String? ?? 'normal',
      projectId: json['projectId'] as String? ?? '',
      projectName: json['projectName'] as String? ?? '',
      budgetSubjectId: json['budgetSubjectId'] as String? ?? '',
      budgetSubjectName: json['budgetSubjectName'] as String? ?? '',
      availableBalance: (json['availableBalance'] as num?)?.toDouble() ?? 0.0,
      isTaxIncluded: json['isTaxIncluded'] as bool? ?? false,
      validUntil: json['validUntil'] != null ? DateTime.parse(json['validUntil'] as String) : null,
      referenceNo: json['referenceNo'] as String? ?? '',
      usageStatus: json['usageStatus'] as String? ?? 'unused',
      isOvernight: json['isOvernight'] as bool? ?? false,
      transportMode: json['transportMode'] as String? ?? '',
      entertainTarget: json['entertainTarget'] as String? ?? '',
      entertainLevel: json['entertainLevel'] as String? ?? '',
      guestCount: json['guestCount'] as int? ?? 0,
      hostCount: json['hostCount'] as int? ?? 0,
      entertainLocation: json['entertainLocation'] as String? ?? '',
      meetingDate: json['meetingDate'] != null ? DateTime.parse(json['meetingDate'] as String) : null,
      meetingLocation: json['meetingLocation'] as String? ?? '',
      details:
          (json['details'] as List<dynamic>?)
              ?.map(
                (e) =>
                    ExpenseAppDetailModel.fromJson(e as Map<String, dynamic>),
              )
              .toList() ??
          [],
      attachments:
          (json['attachments'] as List<dynamic>?)?.map((e) => e as String).toList() ?? [],
      approvalRecords:
          (json['approvalRecords'] as List<dynamic>?)
              ?.map((e) => ApprovalRecord.fromJson(e as Map<String, dynamic>))
              .toList() ??
          [],
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'applicationNo': applicationNo,
    'applicantId': applicantId,
    'applicantName': applicantName,
    'deptId': deptId,
    'deptName': deptName,
    'expenseType': expenseType,
    'expenseTypes': expenseTypes,
    'estimatedAmount': estimatedAmount,
    'purpose': purpose,
    'remark': remark,
    'status': status,
    'currentApproverId': currentApproverId,
    'approvalChain': approvalChain,
    'createTime': createTime.toIso8601String(),
    'updateTime': updateTime.toIso8601String(),
    'estimatedStartDate': estimatedStartDate?.toIso8601String(),
    'estimatedEndDate': estimatedEndDate?.toIso8601String(),
    'urgency': urgency,
    'projectId': projectId,
    'projectName': projectName,
    'budgetSubjectId': budgetSubjectId,
    'budgetSubjectName': budgetSubjectName,
    'availableBalance': availableBalance,
    'isTaxIncluded': isTaxIncluded,
    'validUntil': validUntil?.toIso8601String(),
    'referenceNo': referenceNo,
    'usageStatus': usageStatus,
    'isOvernight': isOvernight,
    'transportMode': transportMode,
    'entertainTarget': entertainTarget,
    'entertainLevel': entertainLevel,
    'guestCount': guestCount,
    'hostCount': hostCount,
    'entertainLocation': entertainLocation,
    'meetingDate': meetingDate?.toIso8601String(),
    'meetingLocation': meetingLocation,
    'details': details.map((d) => d.toJson()).toList(),
    'attachments': attachments,
    'approvalRecords': approvalRecords.map((r) => r.toJson()).toList(),
  };

  ExpenseApplicationModel copyWith({
    String? id,
    String? applicationNo,
    String? applicantId,
    String? applicantName,
    String? deptId,
    String? deptName,
    String? expenseType,
    List<String>? expenseTypes,
    double? estimatedAmount,
    String? purpose,
    String? remark,
    String? status,
    String? currentApproverId,
    List<String>? approvalChain,
    DateTime? createTime,
    DateTime? updateTime,
    DateTime? estimatedStartDate,
    DateTime? estimatedEndDate,
    String? urgency,
    String? projectId,
    String? projectName,
    String? budgetSubjectId,
    String? budgetSubjectName,
    double? availableBalance,
    bool? isTaxIncluded,
    DateTime? validUntil,
    String? referenceNo,
    String? usageStatus,
    bool? isOvernight,
    String? transportMode,
    String? entertainTarget,
    String? entertainLevel,
    int? guestCount,
    int? hostCount,
    String? entertainLocation,
    DateTime? meetingDate,
    String? meetingLocation,
    List<ExpenseAppDetailModel>? details,
    List<String>? attachments,
    List<ApprovalRecord>? approvalRecords,
  }) {
    return ExpenseApplicationModel(
      id: id ?? this.id,
      applicationNo: applicationNo ?? this.applicationNo,
      applicantId: applicantId ?? this.applicantId,
      applicantName: applicantName ?? this.applicantName,
      deptId: deptId ?? this.deptId,
      deptName: deptName ?? this.deptName,
      expenseType: expenseType ?? this.expenseType,
      expenseTypes: expenseTypes ?? this.expenseTypes,
      estimatedAmount: estimatedAmount ?? this.estimatedAmount,
      purpose: purpose ?? this.purpose,
      remark: remark ?? this.remark,
      status: status ?? this.status,
      currentApproverId: currentApproverId ?? this.currentApproverId,
      approvalChain: approvalChain ?? this.approvalChain,
      createTime: createTime ?? this.createTime,
      updateTime: updateTime ?? this.updateTime,
      estimatedStartDate: estimatedStartDate ?? this.estimatedStartDate,
      estimatedEndDate: estimatedEndDate ?? this.estimatedEndDate,
      urgency: urgency ?? this.urgency,
      projectId: projectId ?? this.projectId,
      projectName: projectName ?? this.projectName,
      budgetSubjectId: budgetSubjectId ?? this.budgetSubjectId,
      budgetSubjectName: budgetSubjectName ?? this.budgetSubjectName,
      availableBalance: availableBalance ?? this.availableBalance,
      isTaxIncluded: isTaxIncluded ?? this.isTaxIncluded,
      validUntil: validUntil ?? this.validUntil,
      referenceNo: referenceNo ?? this.referenceNo,
      usageStatus: usageStatus ?? this.usageStatus,
      isOvernight: isOvernight ?? this.isOvernight,
      transportMode: transportMode ?? this.transportMode,
      entertainTarget: entertainTarget ?? this.entertainTarget,
      entertainLevel: entertainLevel ?? this.entertainLevel,
      guestCount: guestCount ?? this.guestCount,
      hostCount: hostCount ?? this.hostCount,
      entertainLocation: entertainLocation ?? this.entertainLocation,
      meetingDate: meetingDate ?? this.meetingDate,
      meetingLocation: meetingLocation ?? this.meetingLocation,
      details: details ?? this.details,
      attachments: attachments ?? this.attachments,
      approvalRecords: approvalRecords ?? this.approvalRecords,
    );
  }
}

class ExpenseAppDetailModel {
  final String id;
  final String applicationId;
  final String itemName;
  final double estimatedAmount;
  final String remark;
  final int sortOrder;
  final double quantity;
  final String unit;
  final double unitPrice;
  final double lineAmount;
  final String category;
  final String description;

  const ExpenseAppDetailModel({
    required this.id,
    this.applicationId = '',
    this.itemName = '',
    this.estimatedAmount = 0.0,
    this.remark = '',
    this.sortOrder = 1,
    this.quantity = 1,
    this.unit = '张',
    this.unitPrice = 0.0,
    this.lineAmount = 0.0,
    this.category = '',
    this.description = '',
  });

  factory ExpenseAppDetailModel.fromJson(Map<String, dynamic> json) {
    return ExpenseAppDetailModel(
      id: json['id'] as String,
      applicationId: json['applicationId'] as String? ?? '',
      itemName: json['itemName'] as String? ?? '',
      estimatedAmount: (json['estimatedAmount'] as num?)?.toDouble() ?? 0.0,
      remark: json['remark'] as String? ?? '',
      sortOrder: json['sortOrder'] as int? ?? 1,
      quantity: (json['quantity'] as num?)?.toDouble() ?? 1,
      unit: json['unit'] as String? ?? '张',
      unitPrice: (json['unitPrice'] as num?)?.toDouble() ?? 0.0,
      lineAmount: (json['lineAmount'] as num?)?.toDouble() ?? 0.0,
      category: json['category'] as String? ?? '',
      description: json['description'] as String? ?? '',
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'applicationId': applicationId,
    'itemName': itemName,
    'estimatedAmount': estimatedAmount,
    'remark': remark,
    'sortOrder': sortOrder,
    'quantity': quantity,
    'unit': unit,
    'unitPrice': unitPrice,
    'lineAmount': lineAmount,
    'category': category,
    'description': description,
  };
}
