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 projectId;
  final String projectName;
  final String budgetSubjectId;
  final double loanWriteoffAmount;
  final String paymentMethod;
  final String accountId;
  final String accountName;
  final String remark;
  final String status;
  final String currentApproverId;
  final List<String> approvalChain;
  final DateTime createTime;
  final DateTime updateTime;
  final List<String> invoiceImages;
  final String paymentStatus;
  final String voucherNo;
  final List<ExpenseDetailModel> details;
  final List<ApprovalRecord> approvalRecords;

  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.projectId = '',
    this.projectName = '',
    this.budgetSubjectId = '',
    this.loanWriteoffAmount = 0.0,
    this.invoiceImages = const [],
    this.paymentStatus = 'unpaid',
    this.voucherNo = '',
    this.paymentMethod = '',
    this.accountId = '',
    this.accountName = '',
    this.remark = '',
    this.status = 'draft',
    this.currentApproverId = '',
    this.approvalChain = const [],
    required this.createTime,
    required this.updateTime,
    this.details = const [],
    this.approvalRecords = 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? ?? '',
      projectId: json['projectId'] as String? ?? '',
      projectName: json['projectName'] as String? ?? '',
      budgetSubjectId: json['budgetSubjectId'] as String? ?? '',
      loanWriteoffAmount:
          (json['loanWriteoffAmount'] as num?)?.toDouble() ?? 0.0,
      invoiceImages:
          (json['invoiceImages'] 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? ?? '',
      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),
      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() ??
          [],
    );
  }

  Map<String, dynamic> toJson() => {
    'id': id,
    'reportNo': reportNo,
    'applicantId': applicantId,
    'applicantName': applicantName,
    'deptId': deptId,
    'deptName': deptName,
    'expenseType': expenseType,
    'totalAmount': totalAmount,
    'invoiceCount': invoiceCount,
    'costCenterId': costCenterId,
    'projectId': projectId,
    'projectName': projectName,
    'budgetSubjectId': budgetSubjectId,
    'loanWriteoffAmount': loanWriteoffAmount,
    'invoiceImages': invoiceImages,
    'paymentStatus': paymentStatus,
    'voucherNo': voucherNo,
    'paymentMethod': paymentMethod,
    'accountId': accountId,
    'accountName': accountName,
    'remark': remark,
    '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(),
  };

  ExpenseModel copyWith({
    String? id,
    String? reportNo,
    String? applicantId,
    String? applicantName,
    String? deptId,
    String? deptName,
    String? expenseType,
    double? totalAmount,
    int? invoiceCount,
    String? costCenterId,
    String? projectId,
    String? projectName,
    String? budgetSubjectId,
    double? loanWriteoffAmount,
    List<String>? invoiceImages,
    String? paymentStatus,
    String? voucherNo,
    String? paymentMethod,
    String? accountId,
    String? accountName,
    String? remark,
    String? status,
    String? currentApproverId,
    List<String>? approvalChain,
    DateTime? createTime,
    DateTime? updateTime,
    List<ExpenseDetailModel>? details,
    List<ApprovalRecord>? approvalRecords,
  }) {
    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,
      projectId: projectId ?? this.projectId,
      projectName: projectName ?? this.projectName,
      budgetSubjectId: budgetSubjectId ?? this.budgetSubjectId,
      loanWriteoffAmount: loanWriteoffAmount ?? this.loanWriteoffAmount,
      invoiceImages: invoiceImages ?? this.invoiceImages,
      paymentStatus: paymentStatus ?? this.paymentStatus,
      voucherNo: voucherNo ?? this.voucherNo,
      paymentMethod: paymentMethod ?? this.paymentMethod,
      accountId: accountId ?? this.accountId,
      accountName: accountName ?? this.accountName,
      remark: remark ?? this.remark,
      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,
    );
  }
}

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 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.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,
      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,
    'invoiceNo': invoiceNo,
    'invoiceCode': invoiceCode,
    'invoiceType': invoiceType,
    'isDeductible': isDeductible,
    'taxRate': taxRate,
    'remark': remark,
    'attachments': attachments,
    'sortOrder': sortOrder,
  };
}
