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

class ExpenseModel {
  final String id;
  final String reportNo;
  final String applicantId;
  final String applicantName;
  final String deptId;
  final String deptName;
  final String expenseType;
  final double totalAmount;
  final int invoiceCount;
  final String costCenterId;
  final String costCenterName;
  final String projectId;
  final String projectName;
  final String budgetSubjectId;
  final String budgetSubjectName;
  final double loanWriteoffAmount;
  final String paymentMethod;
  final String accountBankName;
  final String accountHolderName;
  final String accountId;
  final String accountName;
  final String remark;
  final String purpose;
  final String status;
  final String currentApproverId;
  final List<String> approvalChain;
  final DateTime createTime;
  final DateTime updateTime;
  final List<String> attachments;
  final String paymentStatus;
  final String voucherNo;
  final List<ExpenseDetailModel> details;
  final List<ApprovalRecord> approvalRecords;
  // 财务查验
  final bool isInvoiceVerified;
  final bool isTaxIdMatched;
  final bool isCategoryCompliant;
  // 申请来源
  final String sourceApplicationId;
  final double sourceImportAmount;
  // 发票附件图片
  final List<String> invoiceImages;
  // 数据库字段
  final String bankName;
  final String bankAccount;
  final String bankTransferNo;
  final String approvalInstanceId;
  final DateTime? applicationDate;

  const ExpenseModel({
    required this.id,
    required this.reportNo,
    required this.applicantId,
    required this.applicantName,
    required this.deptId,
    required this.deptName,
    required this.expenseType,
    required this.totalAmount,
    this.invoiceCount = 0,
    this.costCenterId = '',
    this.costCenterName = '',
    this.projectId = '',
    this.projectName = '',
    this.budgetSubjectId = '',
    this.budgetSubjectName = '',
    this.loanWriteoffAmount = 0.0,
    this.attachments = const [],
    this.paymentStatus = 'unpaid',
    this.voucherNo = '',
    this.paymentMethod = '',
    this.accountId = '',
    this.accountName = '',
    this.accountBankName = '',
    this.accountHolderName = '',
    this.remark = '',
    this.purpose = '',
    this.status = 'draft',
    this.currentApproverId = '',
    this.approvalChain = const [],
    required this.createTime,
    required this.updateTime,
    this.details = const [],
    this.approvalRecords = const [],
    this.isInvoiceVerified = false,
    this.isTaxIdMatched = false,
    this.isCategoryCompliant = false,
    this.sourceApplicationId = '',
    this.sourceImportAmount = 0.0,
    this.bankName = '',
    this.bankAccount = '',
    this.bankTransferNo = '',
    this.approvalInstanceId = '',
    this.applicationDate,
    this.invoiceImages = const [],
  });

  factory ExpenseModel.fromJson(Map<String, dynamic> json) {
    return ExpenseModel(
      id: json['id'] as String,
      reportNo: json['reportNo'] 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? ?? '',
      totalAmount: (json['totalAmount'] as num?)?.toDouble() ?? 0.0,
      invoiceCount: json['invoiceCount'] as int? ?? 0,
      costCenterId: json['costCenterId'] as String? ?? '',
      costCenterName: json['costCenterName'] as String? ?? '',
      projectId: json['projectId'] as String? ?? '',
      projectName: json['projectName'] as String? ?? '',
      budgetSubjectId: json['budgetSubjectId'] as String? ?? '',
      budgetSubjectName: json['budgetSubjectName'] as String? ?? '',
      loanWriteoffAmount:
          (json['loanWriteoffAmount'] as num?)?.toDouble() ?? 0.0,
      attachments:
          (json['attachments'] as List<dynamic>?)
              ?.map((e) => e as String)
              .toList() ??
          [],
      paymentStatus: json['paymentStatus'] as String? ?? 'unpaid',
      voucherNo: json['voucherNo'] as String? ?? '',
      paymentMethod: json['paymentMethod'] as String? ?? '',
      accountId: json['accountId'] as String? ?? '',
      accountName: json['accountName'] as String? ?? '',
      accountBankName: json['accountBankName'] as String? ?? '',
      accountHolderName: json['accountHolderName'] as String? ?? '',
      remark: json['remark'] as String? ?? '',
      purpose: json['purpose'] 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),
      details:
          (json['details'] as List<dynamic>?)
              ?.map(
                (e) => ExpenseDetailModel.fromJson(e as Map<String, dynamic>),
              )
              .toList() ??
          [],
      approvalRecords:
          (json['approvalRecords'] as List<dynamic>?)
              ?.map((e) => ApprovalRecord.fromJson(e as Map<String, dynamic>))
              .toList() ??
          [],
      isInvoiceVerified: json['isInvoiceVerified'] as bool? ?? false,
      isTaxIdMatched: json['isTaxIdMatched'] as bool? ?? false,
      isCategoryCompliant: json['isCategoryCompliant'] as bool? ?? false,
      sourceApplicationId: json['sourceApplicationId'] as String? ?? '',
      sourceImportAmount:
          (json['sourceImportAmount'] as num?)?.toDouble() ?? 0.0,
      bankName: json['bankName'] as String? ?? '',
      bankAccount: json['bankAccount'] as String? ?? '',
      bankTransferNo: json['bankTransferNo'] as String? ?? '',
      approvalInstanceId: json['approvalInstanceId'] as String? ?? '',
      applicationDate: json['applicationDate'] != null
          ? DateTime.parse(json['applicationDate'] as String)
          : null,
      invoiceImages:
          (json['invoiceImages'] as List<dynamic>?)
              ?.map((e) => e as String)
              .toList() ??
          [],
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'reportNo': reportNo,
    'applicantId': applicantId,
    'applicantName': applicantName,
    'deptId': deptId,
    'deptName': deptName,
    'expenseType': expenseType,
    'totalAmount': totalAmount,
    'invoiceCount': invoiceCount,
    'costCenterId': costCenterId,
    'costCenterName': costCenterName,
    'projectId': projectId,
    'projectName': projectName,
    'budgetSubjectId': budgetSubjectId,
    'budgetSubjectName': budgetSubjectName,
    'loanWriteoffAmount': loanWriteoffAmount,
    'attachments': attachments,
    'paymentStatus': paymentStatus,
    'voucherNo': voucherNo,
    'paymentMethod': paymentMethod,
    'accountId': accountId,
    'accountName': accountName,
    'accountBankName': accountBankName,
    'accountHolderName': accountHolderName,
    'remark': remark,
    'purpose': purpose,
    'status': status,
    'currentApproverId': currentApproverId,
    'approvalChain': approvalChain,
    'createTime': createTime.toIso8601String(),
    'updateTime': updateTime.toIso8601String(),
    'details': details.map((d) => d.toJson()).toList(),
    'approvalRecords': approvalRecords.map((r) => r.toJson()).toList(),
    'isInvoiceVerified': isInvoiceVerified,
    'isTaxIdMatched': isTaxIdMatched,
    'isCategoryCompliant': isCategoryCompliant,
    'sourceApplicationId': sourceApplicationId,
    'sourceImportAmount': sourceImportAmount,
    'bankName': bankName,
    'bankAccount': bankAccount,
    'bankTransferNo': bankTransferNo,
    'approvalInstanceId': approvalInstanceId,
    'applicationDate': applicationDate?.toIso8601String(),
    'invoiceImages': invoiceImages,
  };

  ExpenseModel copyWith({
    String? id,
    String? reportNo,
    String? applicantId,
    String? applicantName,
    String? deptId,
    String? deptName,
    String? expenseType,
    double? totalAmount,
    int? invoiceCount,
    String? costCenterId,
    String? costCenterName,
    String? projectId,
    String? projectName,
    String? budgetSubjectId,
    String? budgetSubjectName,
    double? loanWriteoffAmount,
    List<String>? attachments,
    String? paymentStatus,
    String? voucherNo,
    String? paymentMethod,
    String? accountId,
    String? accountName,
    String? accountBankName,
    String? accountHolderName,
    String? remark,
    String? purpose,
    String? status,
    String? currentApproverId,
    List<String>? approvalChain,
    DateTime? createTime,
    DateTime? updateTime,
    List<ExpenseDetailModel>? details,
    List<ApprovalRecord>? approvalRecords,
    bool? isInvoiceVerified,
    bool? isTaxIdMatched,
    bool? isCategoryCompliant,
    String? sourceApplicationId,
    double? sourceImportAmount,
    String? bankName,
    String? bankAccount,
    String? bankTransferNo,
    String? approvalInstanceId,
    DateTime? applicationDate,
    List<String>? invoiceImages,
  }) {
    return ExpenseModel(
      id: id ?? this.id,
      reportNo: reportNo ?? this.reportNo,
      applicantId: applicantId ?? this.applicantId,
      applicantName: applicantName ?? this.applicantName,
      deptId: deptId ?? this.deptId,
      deptName: deptName ?? this.deptName,
      expenseType: expenseType ?? this.expenseType,
      totalAmount: totalAmount ?? this.totalAmount,
      invoiceCount: invoiceCount ?? this.invoiceCount,
      costCenterId: costCenterId ?? this.costCenterId,
      costCenterName: costCenterName ?? this.costCenterName,
      projectId: projectId ?? this.projectId,
      projectName: projectName ?? this.projectName,
      budgetSubjectId: budgetSubjectId ?? this.budgetSubjectId,
      budgetSubjectName: budgetSubjectName ?? this.budgetSubjectName,
      loanWriteoffAmount: loanWriteoffAmount ?? this.loanWriteoffAmount,
      attachments: attachments ?? this.attachments,
      paymentStatus: paymentStatus ?? this.paymentStatus,
      voucherNo: voucherNo ?? this.voucherNo,
      paymentMethod: paymentMethod ?? this.paymentMethod,
      accountId: accountId ?? this.accountId,
      accountName: accountName ?? this.accountName,
      accountBankName: accountBankName ?? this.accountBankName,
      accountHolderName: accountHolderName ?? this.accountHolderName,
      remark: remark ?? this.remark,
      purpose: purpose ?? this.purpose,
      status: status ?? this.status,
      currentApproverId: currentApproverId ?? this.currentApproverId,
      approvalChain: approvalChain ?? this.approvalChain,
      createTime: createTime ?? this.createTime,
      updateTime: updateTime ?? this.updateTime,
      details: details ?? this.details,
      approvalRecords: approvalRecords ?? this.approvalRecords,
      isInvoiceVerified: isInvoiceVerified ?? this.isInvoiceVerified,
      isTaxIdMatched: isTaxIdMatched ?? this.isTaxIdMatched,
      isCategoryCompliant: isCategoryCompliant ?? this.isCategoryCompliant,
      sourceApplicationId: sourceApplicationId ?? this.sourceApplicationId,
      sourceImportAmount: sourceImportAmount ?? this.sourceImportAmount,
      bankName: bankName ?? this.bankName,
      bankAccount: bankAccount ?? this.bankAccount,
      bankTransferNo: bankTransferNo ?? this.bankTransferNo,
      approvalInstanceId: approvalInstanceId ?? this.approvalInstanceId,
      applicationDate: applicationDate ?? this.applicationDate,
      invoiceImages: invoiceImages ?? this.invoiceImages,
    );
  }
}

class ExpenseDetailModel {
  final String id;
  final String expenseId;
  final DateTime expenseDate;
  final String expenseType;
  final String expenseDesc;
  final double amount;
  final double taxAmount;
  final double totalAmount;
  final double baseAmount;
  final String currency;
  final double exchangeRate;
  final String invoiceNo;
  final String invoiceCode;
  final String invoiceType;
  final bool isDeductible;
  final double taxRate;
  final String remark;
  final List<String> attachments;
  final int sortOrder;

  const ExpenseDetailModel({
    required this.id,
    required this.expenseId,
    required this.expenseDate,
    required this.expenseType,
    required this.expenseDesc,
    required this.amount,
    this.taxAmount = 0.0,
    required this.totalAmount,
    this.baseAmount = 0.0,
    this.currency = 'CNY',
    this.exchangeRate = 1.0,
    this.invoiceNo = '',
    this.invoiceCode = '',
    this.invoiceType = '',
    this.isDeductible = false,
    this.taxRate = 0.0,
    this.remark = '',
    this.attachments = const [],
    this.sortOrder = 1,
  });

  factory ExpenseDetailModel.fromJson(Map<String, dynamic> json) {
    return ExpenseDetailModel(
      id: json['id'] as String,
      expenseId: json['expenseId'] as String? ?? '',
      expenseDate: DateTime.parse(json['expenseDate'] as String),
      expenseType: json['expenseType'] as String? ?? '',
      expenseDesc: json['expenseDesc'] as String? ?? '',
      amount: (json['amount'] as num?)?.toDouble() ?? 0.0,
      taxAmount: (json['taxAmount'] as num?)?.toDouble() ?? 0.0,
      totalAmount: (json['totalAmount'] as num?)?.toDouble() ?? 0.0,
      baseAmount: (json['baseAmount'] as num?)?.toDouble() ?? 0.0,
      currency: json['currency'] as String? ?? 'CNY',
      exchangeRate: (json['exchangeRate'] as num?)?.toDouble() ?? 1.0,
      invoiceNo: json['invoiceNo'] as String? ?? '',
      invoiceCode: json['invoiceCode'] as String? ?? '',
      invoiceType: json['invoiceType'] as String? ?? '',
      isDeductible: json['isDeductible'] as bool? ?? false,
      taxRate: (json['taxRate'] as num?)?.toDouble() ?? 0.0,
      remark: json['remark'] as String? ?? '',
      attachments:
          (json['attachments'] as List<dynamic>?)
              ?.map((e) => e as String)
              .toList() ??
          [],
      sortOrder: json['sortOrder'] as int? ?? 1,
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'expenseId': expenseId,
    'expenseDate': expenseDate.toIso8601String(),
    'expenseType': expenseType,
    'expenseDesc': expenseDesc,
    'amount': amount,
    'taxAmount': taxAmount,
    'totalAmount': totalAmount,
    'baseAmount': baseAmount,
    'currency': currency,
    'exchangeRate': exchangeRate,
    'invoiceNo': invoiceNo,
    'invoiceCode': invoiceCode,
    'invoiceType': invoiceType,
    'isDeductible': isDeductible,
    'taxRate': taxRate,
    'remark': remark,
    'attachments': attachments,
    'sortOrder': sortOrder,
  };
}
