import 'dart:convert';

/// Parse the entire response
ExpenseResponse expenseResponseFromJson(String str) =>
    ExpenseResponse.fromJson(json.decode(str));

String expenseResponseToJson(ExpenseResponse data) =>
    json.encode(data.toJson());

class ExpenseResponse {
  final bool success;
  final String message;
  final ExpenseData data;
  final dynamic errors;
  final int statusCode;
  final DateTime timestamp;

  ExpenseResponse({
    required this.success,
    required this.message,
    required this.data,
    required this.errors,
    required this.statusCode,
    required this.timestamp,
  });

  factory ExpenseResponse.fromJson(Map<String, dynamic> json) {
    final dataField = json["data"];
    return ExpenseResponse(
      success: json["success"] ?? false,
      message: json["message"] ?? '',
      data: (dataField is Map<String, dynamic>)
          ? ExpenseData.fromJson(dataField)
          : ExpenseData.empty(),
      errors: json["errors"],
      statusCode: json["statusCode"] ?? 0,
      timestamp: DateTime.tryParse(json["timestamp"] ?? '') ?? DateTime.now(),
    );
  }

  Map<String, dynamic> toJson() => {
        "success": success,
        "message": message,
        "data": data.toJson(),
        "errors": errors,
        "statusCode": statusCode,
        "timestamp": timestamp.toIso8601String(),
      };
}

class ExpenseData {
  final Filter? filter;
  final int currentPage;
  final int totalPages;
  final int totalEntites;
  final List<ExpenseModel> data;

  ExpenseData({
    required this.filter,
    required this.currentPage,
    required this.totalPages,
    required this.totalEntites,
    required this.data,
  });

  factory ExpenseData.fromJson(Map<String, dynamic> json) => ExpenseData(
        filter: json["filter"] != null ? Filter.fromJson(json["filter"]) : null,
        currentPage: json["currentPage"] ?? 0,
        totalPages: json["totalPages"] ?? 0,
        totalEntites: json["totalEntites"] ?? 0,
        data: (json["data"] as List<dynamic>? ?? [])
            .map((x) => ExpenseModel.fromJson(x))
            .toList(),
      );

  factory ExpenseData.empty() => ExpenseData(
        filter: null,
        currentPage: 0,
        totalPages: 0,
        totalEntites: 0,
        data: [],
      );

  Map<String, dynamic> toJson() => {
        "filter": filter?.toJson(),
        "currentPage": currentPage,
        "totalPages": totalPages,
        "totalEntites": totalEntites,
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
      };
}

class Filter {
  final List<String> projectIds;
  final List<String> statusIds;
  final List<String> createdByIds;
  final List<String> paidById;
  final DateTime? startDate;
  final DateTime? endDate;

  Filter({
    required this.projectIds,
    required this.statusIds,
    required this.createdByIds,
    required this.paidById,
    required this.startDate,
    required this.endDate,
  });

  factory Filter.fromJson(Map<String, dynamic> json) => Filter(
        projectIds: List<String>.from(json["projectIds"] ?? []),
        statusIds: List<String>.from(json["statusIds"] ?? []),
        createdByIds: List<String>.from(json["createdByIds"] ?? []),
        paidById: List<String>.from(json["paidById"] ?? []),
        startDate:
            json["startDate"] != null ? DateTime.tryParse(json["startDate"]) : null,
        endDate:
            json["endDate"] != null ? DateTime.tryParse(json["endDate"]) : null,
      );

  Map<String, dynamic> toJson() => {
        "projectIds": projectIds,
        "statusIds": statusIds,
        "createdByIds": createdByIds,
        "paidById": paidById,
        "startDate": startDate?.toIso8601String(),
        "endDate": endDate?.toIso8601String(),
      };
}

// --- ExpenseModel and other classes remain same as you wrote ---
// I will include them here for completeness.

class ExpenseModel {
  final String id;
  final Project project;
  final ExpenseType expensesType;
  final PaymentMode paymentMode;
  final PaidBy paidBy;
  final CreatedBy createdBy;
  final DateTime transactionDate;
  final DateTime createdAt;
  final String supplerName;
  final double amount;
  final Status status;
  final List<Status> nextStatus;
  final bool preApproved;

  ExpenseModel({
    required this.id,
    required this.project,
    required this.expensesType,
    required this.paymentMode,
    required this.paidBy,
    required this.createdBy,
    required this.transactionDate,
    required this.createdAt,
    required this.supplerName,
    required this.amount,
    required this.status,
    required this.nextStatus,
    required this.preApproved,
  });

  factory ExpenseModel.fromJson(Map<String, dynamic> json) => ExpenseModel(
        id: json["id"] ?? '',
        project: Project.fromJson(json["project"] ?? {}),
        expensesType: ExpenseType.fromJson(json["expensesType"] ?? {}),
        paymentMode: PaymentMode.fromJson(json["paymentMode"] ?? {}),
        paidBy: PaidBy.fromJson(json["paidBy"] ?? {}),
        createdBy: CreatedBy.fromJson(json["createdBy"] ?? {}),
        transactionDate:
            DateTime.tryParse(json["transactionDate"] ?? '') ?? DateTime.now(),
        createdAt:
            DateTime.tryParse(json["createdAt"] ?? '') ?? DateTime.now(),
        supplerName: json["supplerName"] ?? '',
        amount: (json["amount"] ?? 0).toDouble(),
        status: Status.fromJson(json["status"] ?? {}),
        nextStatus: (json["nextStatus"] as List<dynamic>? ?? [])
            .map((x) => Status.fromJson(x))
            .toList(),
        preApproved: json["preApproved"] ?? false,
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "project": project.toJson(),
        "expensesType": expensesType.toJson(),
        "paymentMode": paymentMode.toJson(),
        "paidBy": paidBy.toJson(),
        "createdBy": createdBy.toJson(),
        "transactionDate": transactionDate.toIso8601String(),
        "createdAt": createdAt.toIso8601String(),
        "supplerName": supplerName,
        "amount": amount,
        "status": status.toJson(),
        "nextStatus": List<dynamic>.from(nextStatus.map((x) => x.toJson())),
        "preApproved": preApproved,
      };
}

class Project {
  final String id;
  final String name;
  final String shortName;
  final String projectAddress;
  final String contactPerson;
  final DateTime startDate;
  final DateTime endDate;
  final String projectStatusId;

  Project({
    required this.id,
    required this.name,
    required this.shortName,
    required this.projectAddress,
    required this.contactPerson,
    required this.startDate,
    required this.endDate,
    required this.projectStatusId,
  });

  factory Project.fromJson(Map<String, dynamic> json) => Project(
        id: json["id"] ?? '',
        name: json["name"] ?? '',
        shortName: json["shortName"] ?? '',
        projectAddress: json["projectAddress"] ?? '',
        contactPerson: json["contactPerson"] ?? '',
        startDate:
            DateTime.tryParse(json["startDate"] ?? '') ?? DateTime.now(),
        endDate: DateTime.tryParse(json["endDate"] ?? '') ?? DateTime.now(),
        projectStatusId: json["projectStatusId"] ?? '',
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "shortName": shortName,
        "projectAddress": projectAddress,
        "contactPerson": contactPerson,
        "startDate": startDate.toIso8601String(),
        "endDate": endDate.toIso8601String(),
        "projectStatusId": projectStatusId,
      };
}

class ExpenseType {
  final String id;
  final String name;
  final bool noOfPersonsRequired;
  final String description;

  ExpenseType({
    required this.id,
    required this.name,
    required this.noOfPersonsRequired,
    required this.description,
  });

  factory ExpenseType.fromJson(Map<String, dynamic> json) => ExpenseType(
        id: json["id"] ?? '',
        name: json["name"] ?? '',
        noOfPersonsRequired: json["noOfPersonsRequired"] ?? false,
        description: json["description"] ?? '',
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "noOfPersonsRequired": noOfPersonsRequired,
        "description": description,
      };
}

class PaymentMode {
  final String id;
  final String name;
  final String description;

  PaymentMode({
    required this.id,
    required this.name,
    required this.description,
  });

  factory PaymentMode.fromJson(Map<String, dynamic> json) => PaymentMode(
        id: json["id"] ?? '',
        name: json["name"] ?? '',
        description: json["description"] ?? '',
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "description": description,
      };
}

class PaidBy {
  final String id;
  final String firstName;
  final String lastName;
  final String photo;
  final String jobRoleId;
  final String? jobRoleName;

  PaidBy({
    required this.id,
    required this.firstName,
    required this.lastName,
    required this.photo,
    required this.jobRoleId,
    this.jobRoleName,
  });

  factory PaidBy.fromJson(Map<String, dynamic> json) => PaidBy(
        id: json["id"] ?? '',
        firstName: json["firstName"] ?? '',
        lastName: json["lastName"] ?? '',
        photo: json["photo"] ?? '',
        jobRoleId: json["jobRoleId"] ?? '',
        jobRoleName: json["jobRoleName"],
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "firstName": firstName,
        "lastName": lastName,
        "photo": photo,
        "jobRoleId": jobRoleId,
        "jobRoleName": jobRoleName,
      };
}

class CreatedBy {
  final String id;
  final String firstName;
  final String lastName;
  final String photo;
  final String jobRoleId;
  final String? jobRoleName;

  CreatedBy({
    required this.id,
    required this.firstName,
    required this.lastName,
    required this.photo,
    required this.jobRoleId,
    this.jobRoleName,
  });

  factory CreatedBy.fromJson(Map<String, dynamic> json) => CreatedBy(
        id: json["id"] ?? '',
        firstName: json["firstName"] ?? '',
        lastName: json["lastName"] ?? '',
        photo: json["photo"] ?? '',
        jobRoleId: json["jobRoleId"] ?? '',
        jobRoleName: json["jobRoleName"],
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "firstName": firstName,
        "lastName": lastName,
        "photo": photo,
        "jobRoleId": jobRoleId,
        "jobRoleName": jobRoleName,
      };
}

class Status {
  final String id;
  final String name;
  final String displayName;
  final String description;
  final String color;
  final bool isSystem;

  Status({
    required this.id,
    required this.name,
    required this.displayName,
    required this.description,
    required this.color,
    required this.isSystem,
  });

  factory Status.fromJson(Map<String, dynamic> json) => Status(
        id: json["id"] ?? '',
        name: json["name"] ?? '',
        displayName: json["displayName"] ?? '',
        description: json["description"] ?? '',
        color: (json["color"] ?? '').replaceAll("'", ''), 
        isSystem: json["isSystem"] ?? false,
      );

  Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "displayName": displayName,
        "description": description,
        "color": color,
        "isSystem": isSystem,
      };
}
