import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { endpoint } from "@/utils/endpoint";
import type {
  CreateFileUploadFieldDto,
  CreateFileUploadSettingDto,
  FileUploadField,
  FileUploadSetting,
  UpdateFileUploadFieldDto,
  UpdateFileUploadSettingDto,
} from "@/types/fileUploadSettings";
import {
  CreateDropdownOptionDto,
  CreateDropdownSettingDto,
  DropdownOption,
  DropdownSetting,
  UpdateDropdownOptionDto,
  UpdateDropdownSettingDto,
} from "@/types/dropdownSettings";
import {
  RuleEngineListResult,
  RuleEngineRecord,
  RuleEngineResourceSlug,
} from "@/types/rule-engine";
import { fileUploadSettingsService } from "./fileUploadSettings.service";
import { dropdownSettingsService } from "./dropdownSettings.service";
import {
  ruleEngineService,
  RuleEngineListParams,
} from "./ruleEngine/ruleEngine.service";
import {
  bookingsService,
  BookingListFilter,
  type ApproveStepPayload,
  type PaginatedBookings,
  type RejectStepPayload,
} from "./bookings.service";
import type { BookingDetail } from "@/types/booking";

export const api = {
  fileUploadSettings: {
    list: endpoint<void, FileUploadSetting[]>(
      "file-upload-settings",
      "list",
      fileUploadSettingsService.list,
    ),

    getById: endpoint<{ id: string }, FileUploadSetting>(
      "file-upload-settings",
      "getById",
      ({ id }) => fileUploadSettingsService.getById(id),
    ),

    getByCode: endpoint<{ code: string }, FileUploadSetting>(
      "file-upload-settings",
      "getByCode",
      ({ code }) => fileUploadSettingsService.getByCode(code),
    ),

    create: endpoint<CreateFileUploadSettingDto, FileUploadSetting>(
      "file-upload-settings",
      "create",
      (payload) => fileUploadSettingsService.create(payload),
    ),

    update: endpoint<
      { id: string; dto: UpdateFileUploadSettingDto },
      FileUploadSetting
    >("file-upload-settings", "update", ({ id, dto }) =>
      fileUploadSettingsService.update(id, dto),
    ),

    remove: endpoint<{ id: string }, void>(
      "file-upload-settings",
      "remove",
      ({ id }) => fileUploadSettingsService.remove(id),
    ),

    replaceFields: endpoint<
      { id: string; fields: CreateFileUploadFieldDto[] },
      FileUploadField[]
    >("file-upload-settings", "replaceFields", ({ id, fields }) =>
      fileUploadSettingsService.replaceFields(id, fields),
    ),

    addField: endpoint<
      { settingId: string; dto: CreateFileUploadFieldDto },
      FileUploadField
    >("file-upload-settings", "addField", ({ settingId, dto }) =>
      fileUploadSettingsService.addField(settingId, dto),
    ),

    updateField: endpoint<
      { fieldId: string; dto: UpdateFileUploadFieldDto },
      FileUploadField
    >("file-upload-settings", "updateField", ({ fieldId, dto }) =>
      fileUploadSettingsService.updateField(fieldId, dto),
    ),

    removeField: endpoint<{ fieldId: string }, void>(
      "file-upload-settings",
      "removeField",
      ({ fieldId }) => fileUploadSettingsService.removeField(fieldId),
    ),
  },

  dropdownSettings: {
    list: endpoint<void, DropdownSetting[]>(
      "dropdown-settings",
      "list",
      dropdownSettingsService.list,
    ),

    getById: endpoint<{ id: string }, DropdownSetting>(
      "dropdown-settings",
      "getById",
      ({ id }) => dropdownSettingsService.getById(id),
    ),

    getByCode: endpoint<{ code: string }, DropdownSetting>(
      "dropdown-settings",
      "getByCode",
      ({ code }) => dropdownSettingsService.getByCode(code),
    ),

    create: endpoint<CreateDropdownSettingDto, DropdownSetting>(
      "dropdown-settings",
      "create",
      (payload) => dropdownSettingsService.create(payload),
    ),

    update: endpoint<
      { id: string; dto: UpdateDropdownSettingDto },
      DropdownSetting
    >("dropdown-settings", "update", ({ id, dto }) =>
      dropdownSettingsService.update(id, dto),
    ),

    remove: endpoint<{ id: string }, void>(
      "dropdown-settings",
      "remove",
      ({ id }) => dropdownSettingsService.remove(id),
    ),

    replaceOptions: endpoint<
      { id: string; options: CreateDropdownOptionDto[] },
      DropdownOption[]
    >("dropdown-settings", "replaceOptions", ({ id, options }) =>
      dropdownSettingsService.replaceOptions(id, options),
    ),

    addOption: endpoint<
      { id: string; dto: CreateDropdownOptionDto },
      DropdownOption
    >("dropdown-settings", "addOption", ({ id, dto }) =>
      dropdownSettingsService.addOption(id, dto),
    ),

    updateOption: endpoint<
      { optionId: string; dto: UpdateDropdownOptionDto },
      DropdownOption
    >("dropdown-settings", "updateOption", ({ optionId, dto }) =>
      dropdownSettingsService.updateOption(optionId, dto),
    ),

    removeOption: endpoint<{ optionId: string }, void>(
      "dropdown-settings",
      "removeOption",
      ({ optionId }) => dropdownSettingsService.removeOption(optionId),
    ),
  },

  ruleEngine: {
    list: endpoint<
      { resource: RuleEngineResourceSlug; params?: RuleEngineListParams },
      RuleEngineListResult<RuleEngineRecord>
    >(
      "rule-engine",
      "list",
      ({ resource, params }) => ruleEngineService.list(resource, params),
      ({ resource, params }) => QUERY_KEYS.RULE_ENGINE.list(resource, params),
    ),

    getById: endpoint<
      { resource: RuleEngineResourceSlug; id: string },
      RuleEngineRecord
    >(
      "rule-engine",
      "getById",
      ({ resource, id }) => ruleEngineService.getById(resource, id),
      ({ resource, id }) => QUERY_KEYS.RULE_ENGINE.detail(resource, id),
    ),

    create: endpoint<
      { resource: RuleEngineResourceSlug; payload: Record<string, unknown> },
      RuleEngineRecord
    >("rule-engine", "create", ({ resource, payload }) =>
      ruleEngineService.create(resource, payload),
    ),

    update: endpoint<
      {
        resource: RuleEngineResourceSlug;
        id: string;
        payload: Record<string, unknown>;
      },
      RuleEngineRecord
    >("rule-engine", "update", ({ resource, id, payload }) =>
      ruleEngineService.update(resource, id, payload),
    ),

    remove: endpoint<
      { resource: RuleEngineResourceSlug; id: string },
      void
    >("rule-engine", "remove", ({ resource, id }) =>
      ruleEngineService.remove(resource, id),
    ),

    submitRate: endpoint<{ id: string }, RuleEngineRecord>(
      "rule-engine",
      "submitRate",
      ({ id }) => ruleEngineService.submitRate(id),
    ),

    approveRate: endpoint<{ id: string }, RuleEngineRecord>(
      "rule-engine",
      "approveRate",
      ({ id }) => ruleEngineService.approveRate(id),
    ),

    getApprovalChain: endpoint<void, RuleEngineRecord[]>(
      "rule-engine",
      "getApprovalChain",
      () => ruleEngineService.getApprovalChain(),
      () => QUERY_KEYS.RULE_ENGINE.chain,
    ),
  },

  bookings: {
    list: endpoint<{ filter?: BookingListFilter }, PaginatedBookings>(
      "bookings",
      "list",
      ({ filter }) => bookingsService.list(filter),
      ({ filter }) => QUERY_KEYS.BOOKINGS.list(filter),
    ),

    getById: endpoint<{ id: string }, BookingDetail>(
      "bookings",
      "getById",
      ({ id }) => bookingsService.getById(id),
      ({ id }) => QUERY_KEYS.BOOKINGS.byId(id),
    ),

    remove: endpoint<{ id: string }, void>(
      "bookings",
      "remove",
      ({ id }) => bookingsService.remove(id),
    ),

    staffAccept: endpoint<{ id: string }, BookingDetail>(
      "bookings",
      "staffAccept",
      ({ id }) => bookingsService.staffAccept(id),
    ),

    requestChanges: endpoint<{ id: string; note: string }, BookingDetail>(
      "bookings",
      "requestChanges",
      ({ id, note }) => bookingsService.requestChanges(id, note),
    ),

    staffReject: endpoint<{ id: string; reason: string }, BookingDetail>(
      "bookings",
      "staffReject",
      ({ id, reason }) => bookingsService.staffReject(id, reason),
    ),

    approveStep: endpoint<ApproveStepPayload, BookingDetail>(
      "bookings",
      "approveStep",
      (payload) => bookingsService.approveStep(payload),
    ),

    rejectStep: endpoint<RejectStepPayload, BookingDetail>(
      "bookings",
      "rejectStep",
      (payload) => bookingsService.rejectStep(payload),
    ),

    generateContract: endpoint<{ id: string }, BookingDetail>(
      "bookings",
      "generateContract",
      ({ id }) => bookingsService.generateContract(id),
    ),

    getContractView: endpoint<{ id: string }, import("./bookings.service").ContractView>(
      "bookings",
      "getContractView",
      ({ id }) => bookingsService.getContractView(id),
    ),

    signContract: endpoint<
      { id: string } & import("./bookings.service").SignContractPayload,
      BookingDetail
    >("bookings", "signContract", ({ id, ...payload }) =>
      bookingsService.signContract(id, payload),
    ),

    payBooking: endpoint<{ id: string }, BookingDetail>(
      "bookings",
      "payBooking",
      ({ id }) => bookingsService.payBooking(id),
    ),

    startTransit: endpoint<{ id: string }, BookingDetail>(
      "bookings",
      "startTransit",
      ({ id }) => bookingsService.startTransit(id),
    ),

    complete: endpoint<{ id: string }, BookingDetail>(
      "bookings",
      "complete",
      ({ id }) => bookingsService.complete(id),
    ),

    cancel: endpoint<{ id: string; reason: string }, BookingDetail>(
      "bookings",
      "cancel",
      ({ id, reason }) => bookingsService.cancel(id, reason),
    ),
  },
};
