/// 加班申请主表，对应 OA_OT_APPLY 表。
class OvertimeModel {
  final int applyId;
  final String billNo;
  final DateTime? applyDate;
  final String origBillNo;
  final String salesman;
  final String dept;
  final String customer;
  final String billType;
  final bool isClosed;
  final String feedback;
  final String remark;
  final int status;
  final String createUser;
  final DateTime createTime;
  final DateTime updateTime;

  // ── 瞬态字段（API 实时查询，非存储） ──
  final bool isAuditApproved;

  // ── 子表 ──
  final List<OvertimeDetailModel> details;

  const OvertimeModel({
    required this.applyId,
    this.billNo = '',
    this.applyDate,
    this.origBillNo = '',
    this.salesman = '',
    this.dept = '',
    this.customer = '',
    this.billType = '',
    this.isClosed = false,
    this.feedback = '',
    this.remark = '',
    this.status = 0,
    this.createUser = '',
    required this.createTime,
    required this.updateTime,
    this.isAuditApproved = false,
    this.details = const [],
  });

  factory OvertimeModel.fromJson(Map<String, dynamic> json) {
    return OvertimeModel(
      applyId: json['applyId'] as int? ?? 0,
      billNo: json['billNo'] as String? ?? '',
      applyDate: json['applyDate'] != null
          ? DateTime.tryParse(json['applyDate'] as String)
          : null,
      origBillNo: json['origBillNo'] as String? ?? '',
      salesman: json['salesman'] as String? ?? '',
      dept: json['dept'] as String? ?? '',
      customer: json['customer'] as String? ?? '',
      billType: json['billType'] as String? ?? '',
      isClosed: (json['isClosed'] as int?) == 1,
      feedback: json['feedback'] as String? ?? '',
      remark: json['remark'] as String? ?? '',
      status: json['status'] as int? ?? 0,
      createUser: json['createUser'] as String? ?? '',
      createTime: json['createTime'] != null
          ? DateTime.parse(json['createTime'] as String)
          : DateTime.now(),
      updateTime: json['updateTime'] != null
          ? DateTime.parse(json['updateTime'] as String)
          : DateTime.now(),
      isAuditApproved: (json['isAuditApproved'] as int?) == 1,
      details:
          (json['details'] as List<dynamic>?)
              ?.map(
                (e) => OvertimeDetailModel.fromJson(e as Map<String, dynamic>),
              )
              .toList() ??
          [],
    );
  }

  Map<String, dynamic> toJson() => {
    'applyId': applyId,
    'billNo': billNo,
    'applyDate': applyDate?.toIso8601String(),
    'origBillNo': origBillNo,
    'salesman': salesman,
    'dept': dept,
    'customer': customer,
    'billType': billType,
    'isClosed': isClosed ? 1 : 0,
    'feedback': feedback,
    'remark': remark,
    'status': status,
    'createUser': createUser,
    'createTime': createTime.toIso8601String(),
    'updateTime': updateTime.toIso8601String(),
    'isAuditApproved': isAuditApproved ? 1 : 0,
    'details': details.map((d) => d.toJson()).toList(),
  };

  OvertimeModel copyWith({
    int? applyId,
    String? billNo,
    DateTime? applyDate,
    String? origBillNo,
    String? salesman,
    String? dept,
    String? customer,
    String? billType,
    bool? isClosed,
    String? feedback,
    String? remark,
    int? status,
    String? createUser,
    DateTime? createTime,
    DateTime? updateTime,
    bool? isAuditApproved,
    List<OvertimeDetailModel>? details,
  }) {
    return OvertimeModel(
      applyId: applyId ?? this.applyId,
      billNo: billNo ?? this.billNo,
      applyDate: applyDate ?? this.applyDate,
      origBillNo: origBillNo ?? this.origBillNo,
      salesman: salesman ?? this.salesman,
      dept: dept ?? this.dept,
      customer: customer ?? this.customer,
      billType: billType ?? this.billType,
      isClosed: isClosed ?? this.isClosed,
      feedback: feedback ?? this.feedback,
      remark: remark ?? this.remark,
      status: status ?? this.status,
      createUser: createUser ?? this.createUser,
      createTime: createTime ?? this.createTime,
      updateTime: updateTime ?? this.updateTime,
      isAuditApproved: isAuditApproved ?? this.isAuditApproved,
      details: details ?? this.details,
    );
  }
}

/// 加班明细，对应 OA_OT_DETAIL 表。
class OvertimeDetailModel {
  final int detailId;
  final int applyId;
  final int seqNo;
  final String empCode;
  final String shiftType;
  final DateTime? startDate;
  final DateTime? endDate;
  final double approvedHours;
  final String isApproved;
  final String directOt;
  final double otQuantity;
  final String reason;
  final String handleMethod;
  final String chargeMethod;
  final String remark;
  final String isClosed;
  final String outBillNo;

  const OvertimeDetailModel({
    required this.detailId,
    this.applyId = 0,
    this.seqNo = 0,
    this.empCode = '',
    this.shiftType = '',
    this.startDate,
    this.endDate,
    this.approvedHours = 0.0,
    this.isApproved = 'N',
    this.directOt = 'N',
    this.otQuantity = 0.0,
    this.reason = '',
    this.handleMethod = '',
    this.chargeMethod = '',
    this.remark = '',
    this.isClosed = 'N',
    this.outBillNo = '',
  });

  factory OvertimeDetailModel.fromJson(Map<String, dynamic> json) {
    return OvertimeDetailModel(
      detailId: json['detailId'] as int? ?? 0,
      applyId: json['applyId'] as int? ?? 0,
      seqNo: json['seqNo'] as int? ?? 0,
      empCode: json['empCode'] as String? ?? '',
      shiftType: json['shiftType'] as String? ?? '',
      startDate: json['startDate'] != null
          ? DateTime.tryParse(json['startDate'] as String)
          : null,
      endDate: json['endDate'] != null
          ? DateTime.tryParse(json['endDate'] as String)
          : null,
      approvedHours: (json['approvedHours'] as num?)?.toDouble() ?? 0.0,
      isApproved: json['isApproved'] as String? ?? 'N',
      directOt: json['directOt'] as String? ?? 'N',
      otQuantity: (json['otQuantity'] as num?)?.toDouble() ?? 0.0,
      reason: json['reason'] as String? ?? '',
      handleMethod: json['handleMethod'] as String? ?? '',
      chargeMethod: json['chargeMethod'] as String? ?? '',
      remark: json['remark'] as String? ?? '',
      isClosed: json['isClosed'] as String? ?? 'N',
      outBillNo: json['outBillNo'] as String? ?? '',
    );
  }

  Map<String, dynamic> toJson() => {
    'detailId': detailId,
    'applyId': applyId,
    'seqNo': seqNo,
    'empCode': empCode,
    'shiftType': shiftType,
    'startDate': startDate?.toIso8601String(),
    'endDate': endDate?.toIso8601String(),
    'approvedHours': approvedHours,
    'isApproved': isApproved,
    'directOt': directOt,
    'otQuantity': otQuantity,
    'reason': reason,
    'handleMethod': handleMethod,
    'chargeMethod': chargeMethod,
    'remark': remark,
    'isClosed': isClosed,
    'outBillNo': outBillNo,
  };
}
