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

/// 费用报销主表，对应 [Expense] 表。
class ExpenseModel {
  final String id;
  final String expenseNo;
  final DateTime? expenseDate;
  final String applicantId;
  final String applicantName;
  final String deptId;
  final String deptName;
  final String currencyCode;
  final bool isGenerateVoucher;
  final String voucherNo;
  final double approvedAmount;
  final double totalAmount;
  final String purpose;
  final String remark;
  final String paymentMethod;
  final bool isInvoiceVerified;
  final bool isTaxIdMatched;
  final bool isCategoryCompliant;
  final String bankTransferNo;
  final String paymentStatus;
  final String status;
  final String approvalInstanceId;
  final String previousInstanceIds;
  final DateTime? effectiveDate;
  final String auditorId;
  final int version;
  final DateTime createTime;
  final DateTime updateTime;
  final bool isDeleted;

  // ── 瞬态字段（API 从 ERP 实时查询，非存储） ──
  final String currentApproverId;
  final List<String> approvalChain;
  final List<ApprovalRecord> approvalRecords;

  // ── 子表 ──
  final List<ExpenseDetailModel> details;
  final List<String> attachments;

  const ExpenseModel({
    required this.id,
    required this.expenseNo,
    this.expenseDate,
    this.applicantId = '',
    this.applicantName = '',
    this.deptId = '',
    this.deptName = '',
    this.currencyCode = '',
    this.isGenerateVoucher = true,
    this.voucherNo = '',
    this.approvedAmount = 0.0,
    this.totalAmount = 0.0,
    this.purpose = '',
    this.remark = '',
    this.paymentMethod = '',
    this.isInvoiceVerified = false,
    this.isTaxIdMatched = false,
    this.isCategoryCompliant = false,
    this.bankTransferNo = '',
    this.paymentStatus = 'unpaid',
    this.status = 'draft',
    this.approvalInstanceId = '',
    this.previousInstanceIds = '',
    this.effectiveDate,
    this.auditorId = '',
    this.version = 1,
    required this.createTime,
    required this.updateTime,
    this.isDeleted = false,
    this.currentApproverId = '',
    this.approvalChain = const [],
    this.approvalRecords = const [],
    this.details = const [],
    this.attachments = const [],
  });

  factory ExpenseModel.fromJson(Map<String, dynamic> json) {
    return ExpenseModel(
      id: json['id'] as String? ?? '',
      expenseNo: json['expenseNo'] as String? ?? '',
      expenseDate: json['expenseDate'] != null
          ? DateTime.parse(json['expenseDate'] as String)
          : null,
      applicantId: json['usrNo'] as String? ?? '',
      applicantName: json['applicantName'] as String? ?? json['usrNo'] as String? ?? '',
      deptId: json['dept'] as String? ?? '',
      deptName: json['deptName'] as String? ?? json['dept'] as String? ?? '',
      currencyCode: json['curId'] as String? ?? '',
      isGenerateVoucher: json['isGenerateVoucher'] as bool? ?? false,
      voucherNo: json['vohNo'] as String? ?? '',
      approvedAmount: (json['approvedAmount'] as num?)?.toDouble() ?? 0.0,
      totalAmount: (json['totalAmount'] as num?)?.toDouble() ?? 0.0,
      purpose: json['reason'] as String? ?? '',
      remark: json['rem'] as String? ?? '',
      paymentMethod: json['payId'] as String? ?? '',
      isInvoiceVerified: json['isInvoiceVerified'] as bool? ?? false,
      isTaxIdMatched: json['isTaxIdMatched'] as bool? ?? false,
      isCategoryCompliant: json['isCategoryCompliant'] as bool? ?? false,
      bankTransferNo: json['bankTransferNo'] as String? ?? '',
      paymentStatus: json['paymentStatus'] as String? ?? 'unpaid',
      status: json['clsDate'] != null ? 'closed' : (json['status'] as String? ?? 'draft'),
      approvalInstanceId: json['approvalInstanceId'] as String? ?? '',
      previousInstanceIds: json['previousInstanceIds'] as String? ?? '',
      effectiveDate: json['effDd'] != null
          ? DateTime.parse(json['effDd'] as String)
          : null,
      auditorId: json['chkMan'] as String? ?? '',
      version: json['version'] as int? ?? 1,
      createTime: json['createTime'] != null
          ? DateTime.parse(json['createTime'] as String)
          : DateTime.now(),
      updateTime: json['updateTime'] != null
          ? DateTime.parse(json['updateTime'] as String)
          : DateTime.now(),
      isDeleted: json['isDeleted'] as bool? ?? false,
      currentApproverId: json['currentApproverId'] as String? ?? '',
      approvalChain:
          (json['approvalChain'] 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() ??
          [],
      details:
          (json['details'] as List<dynamic>?)
              ?.map(
                (e) => ExpenseDetailModel.fromJson(e as Map<String, dynamic>),
              )
              .toList() ??
          [],
      attachments:
          (json['attachments'] as List<dynamic>?)
              ?.map((e) => e as String)
              .toList() ??
          [],
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'expenseNo': expenseNo,
    'expenseDate': expenseDate?.toIso8601String(),
    'applicantId': applicantId,
    'applicantName': applicantName,
    'deptId': deptId,
    'deptName': deptName,
    'currencyCode': currencyCode,
    'isGenerateVoucher': isGenerateVoucher,
    'voucherNo': voucherNo,
    'approvedAmount': approvedAmount,
    'totalAmount': totalAmount,
    'purpose': purpose,
    'remark': remark,
    'paymentMethod': paymentMethod,
    'isInvoiceVerified': isInvoiceVerified,
    'isTaxIdMatched': isTaxIdMatched,
    'isCategoryCompliant': isCategoryCompliant,
    'bankTransferNo': bankTransferNo,
    'paymentStatus': paymentStatus,
    'status': status,
    'approvalInstanceId': approvalInstanceId,
    'previousInstanceIds': previousInstanceIds,
    'effectiveDate': effectiveDate?.toIso8601String(),
    'auditorId': auditorId,
    'version': version,
    'createTime': createTime.toIso8601String(),
    'updateTime': updateTime.toIso8601String(),
    'isDeleted': isDeleted,
    'currentApproverId': currentApproverId,
    'approvalChain': approvalChain,
    'approvalRecords': approvalRecords.map((r) => r.toJson()).toList(),
    'details': details.map((d) => d.toJson()).toList(),
    'attachments': attachments,
  };

  ExpenseModel copyWith({
    String? id,
    String? expenseNo,
    DateTime? expenseDate,
    String? applicantId,
    String? applicantName,
    String? deptId,
    String? deptName,
    String? currencyCode,
    bool? isGenerateVoucher,
    String? voucherNo,
    double? approvedAmount,
    double? totalAmount,
    String? purpose,
    String? remark,
    String? paymentMethod,
    bool? isInvoiceVerified,
    bool? isTaxIdMatched,
    bool? isCategoryCompliant,
    String? bankTransferNo,
    String? paymentStatus,
    String? status,
    String? approvalInstanceId,
    String? previousInstanceIds,
    DateTime? effectiveDate,
    String? auditorId,
    int? version,
    DateTime? createTime,
    DateTime? updateTime,
    bool? isDeleted,
    String? currentApproverId,
    List<String>? approvalChain,
    List<ApprovalRecord>? approvalRecords,
    List<ExpenseDetailModel>? details,
    List<String>? attachments,
  }) {
    return ExpenseModel(
      id: id ?? this.id,
      expenseNo: expenseNo ?? this.expenseNo,
      expenseDate: expenseDate ?? this.expenseDate,
      applicantId: applicantId ?? this.applicantId,
      applicantName: applicantName ?? this.applicantName,
      deptId: deptId ?? this.deptId,
      deptName: deptName ?? this.deptName,
      currencyCode: currencyCode ?? this.currencyCode,
      isGenerateVoucher: isGenerateVoucher ?? this.isGenerateVoucher,
      voucherNo: voucherNo ?? this.voucherNo,
      approvedAmount: approvedAmount ?? this.approvedAmount,
      totalAmount: totalAmount ?? this.totalAmount,
      purpose: purpose ?? this.purpose,
      paymentMethod: paymentMethod ?? this.paymentMethod,
      isInvoiceVerified: isInvoiceVerified ?? this.isInvoiceVerified,
      isTaxIdMatched: isTaxIdMatched ?? this.isTaxIdMatched,
      isCategoryCompliant: isCategoryCompliant ?? this.isCategoryCompliant,
      bankTransferNo: bankTransferNo ?? this.bankTransferNo,
      paymentStatus: paymentStatus ?? this.paymentStatus,
      status: status ?? this.status,
      approvalInstanceId: approvalInstanceId ?? this.approvalInstanceId,
      previousInstanceIds: previousInstanceIds ?? this.previousInstanceIds,
      effectiveDate: effectiveDate ?? this.effectiveDate,
      auditorId: auditorId ?? this.auditorId,
      version: version ?? this.version,
      createTime: createTime ?? this.createTime,
      updateTime: updateTime ?? this.updateTime,
      isDeleted: isDeleted ?? this.isDeleted,
      currentApproverId: currentApproverId ?? this.currentApproverId,
      approvalChain: approvalChain ?? this.approvalChain,
      approvalRecords: approvalRecords ?? this.approvalRecords,
      details: details ?? this.details,
      attachments: attachments ?? this.attachments,
    );
  }
}

/// 费用报销明细，对应 [ExpenseDetail] 表。
class ExpenseDetailModel {
  final String id;
  final String expenseId;
  final String expenseApplyId;
  final String expenseApplyNo;
  final DateTime? expenseApplyDate;
  final String expenseCategory;
  final String categoryName;
  final String priority;
  final String purpose;
  final String projectId;
  final String projectName;
  final String costDeptId;
  final String costDeptName;
  final String acctSubjectId;
  final String acctSubjectName;
  final double amount;
  final double taxRate;
  final double taxAmount;
  final double totalAmount;
  final String currencyCode;
  final double exchangeRate;
  final double baseAmount;
  final double approvedAmount;
  final String customerVendorId;
  final String customerVendorName;
  final double offsetAmount;
  final String bankName;
  final String bankAccountName;
  final String bankAccount;
  final String sqMan;
  final String sqManName;
  final String aeNo;
  final String aeDd;
  final String remark;
  final int sortOrder;
  final List<String> attachments;
  final DateTime createTime;
  final DateTime updateTime;
  final bool isDeleted;

  const ExpenseDetailModel({
    required this.id,
    required this.expenseId,
    this.expenseApplyId = '',
    this.expenseApplyNo = '',
    this.expenseApplyDate,
    this.expenseCategory = '',
    this.categoryName = '',
    this.priority = '1',
    this.purpose = '',
    this.projectId = '',
    this.projectName = '',
    this.costDeptId = '',
    this.costDeptName = '',
    this.acctSubjectId = '',
    this.acctSubjectName = '',
    required this.amount,
    this.taxRate = 0.0,
    this.taxAmount = 0.0,
    required this.totalAmount,
    this.currencyCode = '',
    this.exchangeRate = 1.0,
    this.baseAmount = 0.0,
    this.approvedAmount = 0.0,
    this.customerVendorId = '',
    this.customerVendorName = '',
    this.offsetAmount = 0.0,
    this.bankName = '',
    this.bankAccountName = '',
    this.bankAccount = '',
    this.sqMan = '',
    this.sqManName = '',
    this.aeNo = '',
    this.aeDd = '',
    this.remark = '',
    this.sortOrder = 1,
    this.attachments = const [],
    required this.createTime,
    required this.updateTime,
    this.isDeleted = false,
  });

  factory ExpenseDetailModel.fromJson(Map<String, dynamic> json) {
    return ExpenseDetailModel(
      id: json['id'] as String? ?? '',
      expenseId: json['expenseId'] as String? ?? '',
      expenseApplyId: json['aeNo'] as String? ?? '',
      expenseApplyNo: json['aeNo'] as String? ?? '',
      expenseApplyDate: json['aeDd'] != null
          ? DateTime.parse(json['aeDd'] as String)
          : null,
      expenseCategory: json['idxNo'] as String? ?? json['expenseCategory'] as String? ?? '',
      categoryName: json['idxName'] as String? ?? json['categoryName'] as String? ?? '',
      priority: json['priority'] as String? ?? '1',
      purpose: json['purpose'] as String? ?? '',
      projectId: json['objNo'] as String? ?? '',
      projectName: json['objName'] as String? ?? json['projectName'] as String? ?? '',
      costDeptId: json['dep'] as String? ?? '',
      costDeptName: json['depName'] as String? ?? json['dep'] as String? ?? '',
      acctSubjectId: json['accNo'] as String? ?? '',
      acctSubjectName: json['accName'] as String? ?? '',
      amount: (json['amt'] as num?)?.toDouble() ?? 0.0,
      taxRate: (json['taxRto'] as num?)?.toDouble() ?? 0.0,
      taxAmount: (json['tax'] as num?)?.toDouble() ?? 0.0,
      totalAmount: (json['amtn'] as num?)?.toDouble() ?? 0.0,
      currencyCode: json['currencyCode'] as String? ?? '',
      exchangeRate: (json['exchangeRate'] as num?)?.toDouble() ?? 1.0,
      baseAmount: (json['baseAmount'] as num?)?.toDouble() ?? 0.0,
      approvedAmount: (json['approvedAmount'] as num?)?.toDouble() ?? 0.0,
      customerVendorId: json['customerVendorId'] as String? ?? '',
      customerVendorName: json['cust'] as String? ?? '',
      offsetAmount: (json['offsetAmount'] as num?)?.toDouble() ?? 0.0,
      bankName: json['bankName'] as String? ?? '',
      bankAccountName: json['bankAccountName'] as String? ?? '',
      bankAccount: json['bankAccount'] as String? ?? '',
      sqMan: json['sqMan'] as String? ?? '',
      sqManName: json['sqName'] as String? ?? json['sqManName'] as String? ?? json['sqMan'] as String? ?? '',
      aeNo: json['aeNo'] as String? ?? '',
      aeDd: json['aeDd'] as String? ?? '',
      remark: json['rem'] as String? ?? '',
      sortOrder: json['itm'] as int? ?? 1,
      attachments:
          (json['attachments'] as List<dynamic>?)
              ?.map((e) => e as String)
              .toList() ??
          [],
      createTime: json['createTime'] != null
          ? DateTime.parse(json['createTime'] as String)
          : DateTime.now(),
      updateTime: json['updateTime'] != null
          ? DateTime.parse(json['updateTime'] as String)
          : DateTime.now(),
      isDeleted: json['isDeleted'] as bool? ?? false,
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'expenseId': expenseId,
    'expenseApplyId': expenseApplyId,
    'expenseApplyNo': expenseApplyNo,
    'expenseApplyDate': expenseApplyDate?.toIso8601String(),
    'expenseCategory': expenseCategory,
    'categoryName': categoryName,
    'priority': priority,
    'purpose': purpose,
    'projectId': projectId,
    'projectName': projectName,
    'costDeptId': costDeptId,
    'costDeptName': costDeptName,
    'acctSubjectId': acctSubjectId,
    'acctSubjectName': acctSubjectName,
    'amount': amount,
    'taxRate': taxRate,
    'taxAmount': taxAmount,
    'totalAmount': totalAmount,
    'currencyCode': currencyCode,
    'exchangeRate': exchangeRate,
    'baseAmount': baseAmount,
    'approvedAmount': approvedAmount,
    'customerVendorId': customerVendorId,
    'customerVendorName': customerVendorName,
    'offsetAmount': offsetAmount,
    'bankName': bankName,
    'bankAccountName': bankAccountName,
    'bankAccount': bankAccount,
    'sqMan': sqMan,
    'sqManName': sqManName,
    'aeNo': aeNo,
    'aeDd': aeDd,
    'remark': remark,
    'sortOrder': sortOrder,
    'attachments': attachments,
    'createTime': createTime.toIso8601String(),
    'updateTime': updateTime.toIso8601String(),
    'isDeleted': isDeleted,
  };

  ExpenseDetailModel copyWith({
    String? id,
    String? expenseId,
    String? expenseApplyId,
    String? expenseApplyNo,
    DateTime? expenseApplyDate,
    String? expenseCategory,
    String? categoryName,
    String? priority,
    String? purpose,
    String? projectId,
    String? projectName,
    String? costDeptId,
    String? costDeptName,
    String? acctSubjectId,
    String? acctSubjectName,
    double? amount,
    double? taxRate,
    double? taxAmount,
    double? totalAmount,
    String? currencyCode,
    double? exchangeRate,
    double? baseAmount,
    double? approvedAmount,
    String? customerVendorId,
    String? customerVendorName,
    double? offsetAmount,
    String? bankName,
    String? bankAccountName,
    String? bankAccount,
    String? sqMan,
    String? sqManName,
    String? aeNo,
    String? aeDd,
    String? remark,
    int? sortOrder,
    List<String>? attachments,
    DateTime? createTime,
    DateTime? updateTime,
    bool? isDeleted,
  }) {
    return ExpenseDetailModel(
      id: id ?? this.id,
      expenseId: expenseId ?? this.expenseId,
      expenseApplyId: expenseApplyId ?? this.expenseApplyId,
      expenseApplyNo: expenseApplyNo ?? this.expenseApplyNo,
      expenseApplyDate: expenseApplyDate ?? this.expenseApplyDate,
      expenseCategory: expenseCategory ?? this.expenseCategory,
      categoryName: categoryName ?? this.categoryName,
      priority: priority ?? this.priority,
      purpose: purpose ?? this.purpose,
      projectId: projectId ?? this.projectId,
      projectName: projectName ?? this.projectName,
      costDeptId: costDeptId ?? this.costDeptId,
      costDeptName: costDeptName ?? this.costDeptName,
      acctSubjectId: acctSubjectId ?? this.acctSubjectId,
      acctSubjectName: acctSubjectName ?? this.acctSubjectName,
      amount: amount ?? this.amount,
      taxRate: taxRate ?? this.taxRate,
      taxAmount: taxAmount ?? this.taxAmount,
      totalAmount: totalAmount ?? this.totalAmount,
      currencyCode: currencyCode ?? this.currencyCode,
      exchangeRate: exchangeRate ?? this.exchangeRate,
      baseAmount: baseAmount ?? this.baseAmount,
      approvedAmount: approvedAmount ?? this.approvedAmount,
      customerVendorId: customerVendorId ?? this.customerVendorId,
      customerVendorName: customerVendorName ?? this.customerVendorName,
      offsetAmount: offsetAmount ?? this.offsetAmount,
      bankName: bankName ?? this.bankName,
      bankAccountName: bankAccountName ?? this.bankAccountName,
      bankAccount: bankAccount ?? this.bankAccount,
      sqMan: sqMan ?? this.sqMan,
      sqManName: sqManName ?? this.sqManName,
      aeNo: aeNo ?? this.aeNo,
      aeDd: aeDd ?? this.aeDd,
      remark: remark ?? this.remark,
      sortOrder: sortOrder ?? this.sortOrder,
      attachments: attachments ?? this.attachments,
      createTime: createTime ?? this.createTime,
      updateTime: updateTime ?? this.updateTime,
      isDeleted: isDeleted ?? this.isDeleted,
    );
  }
}
