import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiOperationResponse, ApiPath, ApiRequestBody, ApiResponse } from "../infra/types"
import { ApiBaseResponse } from "../contracts/types"

export const JOB_CARD_ROUTES = {
    INDEX: "/api/job-cards",
    BY_ID: "/api/job-cards/{id}",
    CHANGE_DATE: "/api/job-cards/{id}/change-date",
    CHANGE_STATUS: "/api/job-cards/{id}/change-status",
    CHECK_IN: "/api/job-cards/{id}/check-in",
    DELIVERY: "/api/job-cards/{id}/delivery",
    ADD_CUSTOMER_REMARK: "/api/job-cards/{id}/add-customer-remark",
    EDIT_CUSTOMER_REMARK: "/api/job-cards/{id}/edit-customer-remark",
    DELETE_CUSTOMER_REMARK: "/api/job-cards/{id}/delete-customer-remark",
    ADD_SHOP_RECOMMENDATION: "/api/job-cards/{id}/add-shop-recommendation",
    EDIT_SHOP_RECOMMENDATION: "/api/job-cards/{id}/edit-shop-recommendation",
    DELETE_SHOP_RECOMMENDATION: "/api/job-cards/{id}/delete-shop-recommendation",
    ADD_ATTACHMENT: "/api/job-cards/{id}/add-attachment",
    DELETE_ATTACHMENT: "/api/job-cards/{id}/delete-attachment",
    CHANGE_SERVICE_WRITER: "/api/job-cards/{id}/change-service-writer-id",
    CHANGE_SALES_PERSON: "/api/job-cards/{id}/change-sales-person-id",
    CHANGE_TECHNICIAN: "/api/job-cards/{id}/change-technician-id",
    GET_PARTS: "/api/job-cards/{id}/get-parts",
    ADD_PART: "/api/job-cards/{id}/add-part",
    UPDATE_PART: "/api/job-cards/{id}/update-part",
    DELETE_PART: "/api/job-cards/{id}/delete-part",
    GET_SERVICES: "/api/job-cards/{id}/get-services",
    ADD_SERVICE: "/api/job-cards/{id}/add-service",
    UPDATE_SERVICE: "/api/job-cards/{id}/update-service",
    DELETE_SERVICE: "/api/job-cards/{id}/delete-service",
    ADD_SERVICE_ATTACHMENT: "/api/job-cards/{id}/add-service-attachment",
    DELETE_SERVICE_ATTACHMENT: "/api/job-cards/{id}/delete-service-attachment",
    GET_EXPENSE_ITEMS: "/api/job-cards/{id}/get-expense-items",
    ADD_EXPENSE_ITEM: "/api/job-cards/{id}/add-expense-item",
    UPDATE_EXPENSE_ITEM: "/api/job-cards/{id}/update-expense-item",
    DELETE_EXPENSE_ITEM: "/api/job-cards/{id}/delete-expense-item",
    CONVERT_TO_INVOICE: "/api/job-cards/{id}/convert-to-invoice",
} as const satisfies Record<string, ApiPath>


export type JobCardShowData = ApiResponse<typeof JOB_CARD_ROUTES.BY_ID, "get">['data'] & {
    purchase_orders_count: number
    bills_count: number
    expenses_count: number
    tasks_count: number
    appointments_count: number
    parts_count: number
}

export class JobCardsClient extends CrudClient<
    typeof JOB_CARD_ROUTES.INDEX,
    typeof JOB_CARD_ROUTES.BY_ID,
    {
        showResponse: ApiBaseResponse<JobCardShowData>
    }
> {
    constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
        super(baseUrl, defaultOptions, JOB_CARD_ROUTES.INDEX, JOB_CARD_ROUTES.BY_ID)
    }

    async changeDate(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHANGE_DATE, "post">) {
        return this.post(JOB_CARD_ROUTES.CHANGE_DATE, payload, { params: { id } })
    }

    async changeStatus(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHANGE_STATUS, "post">) {
        return this.post(JOB_CARD_ROUTES.CHANGE_STATUS, payload, { params: { id } })
    }

    async checkIn(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHECK_IN, "post">) {
        return this.post(JOB_CARD_ROUTES.CHECK_IN, payload, { params: { id } })
    }

    async delivery(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.DELIVERY, "post">) {
        return this.post(JOB_CARD_ROUTES.DELIVERY, payload, { params: { id } })
    }

    async addCustomerRemark(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_CUSTOMER_REMARK, "post">) {
        return this.post(JOB_CARD_ROUTES.ADD_CUSTOMER_REMARK, payload, { params: { id } })
    }

    async editCustomerRemark(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.EDIT_CUSTOMER_REMARK, "post">) {
        return this.post(JOB_CARD_ROUTES.EDIT_CUSTOMER_REMARK, payload, { params: { id } })
    }

    async deleteCustomerRemark(id: string, customerRemarkId: number) {
        return this.delete(JOB_CARD_ROUTES.DELETE_CUSTOMER_REMARK, { params: { id }, body: { customer_remark_id: customerRemarkId } } as never)
    }

    async addShopRecommendation(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_SHOP_RECOMMENDATION, "post">) {
        return this.post(JOB_CARD_ROUTES.ADD_SHOP_RECOMMENDATION, payload, { params: { id } })
    }

    async editShopRecommendation(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.EDIT_SHOP_RECOMMENDATION, "post">) {
        return this.post(JOB_CARD_ROUTES.EDIT_SHOP_RECOMMENDATION, payload, { params: { id } })
    }

    async deleteShopRecommendation(id: string, shopRecommendationId: number) {
        return this.delete(JOB_CARD_ROUTES.DELETE_SHOP_RECOMMENDATION, { params: { id }, body: { shop_recommendation_id: shopRecommendationId } } as never)
    }

    async addAttachment(id: string, files: File[]) {
        const fd = new FormData()
        for (const file of files) {
            fd.append("attachments[]", file)
        }
        return this.postFormData(`/api/job-cards/${id}/add-attachment`, fd)
    }

    async deleteAttachment(id: string, attachmentId: number) {
        return this.post(JOB_CARD_ROUTES.DELETE_ATTACHMENT, { attachment_id: attachmentId } as never, { params: { id } })
    }

    async changeServiceWriter(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHANGE_SERVICE_WRITER, "post">) {
        return this.post(JOB_CARD_ROUTES.CHANGE_SERVICE_WRITER, payload, { params: { id } })
    }

    async changeSalesPerson(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHANGE_SALES_PERSON, "post">) {
        return this.post(JOB_CARD_ROUTES.CHANGE_SALES_PERSON, payload, { params: { id } })
    }

    async changeTechnician(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHANGE_TECHNICIAN, "post">) {
        return this.post(JOB_CARD_ROUTES.CHANGE_TECHNICIAN, payload, { params: { id } })
    }

    async getParts(id: string, params?: Record<string, unknown>) {
        return this.get(JOB_CARD_ROUTES.GET_PARTS, { params: { id }, query: params as any })
    }

    async addPart(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_PART, "post">) {
        return this.post(JOB_CARD_ROUTES.ADD_PART, payload, { params: { id } })
    }

    async updatePart(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.UPDATE_PART, "put">) {
        return this.put(JOB_CARD_ROUTES.UPDATE_PART, payload, { params: { id } })
    }

    async deletePart(id: string, jobCardPartId: number) {
        return this.delete(JOB_CARD_ROUTES.DELETE_PART, { params: { id }, body: { job_card_part_id: jobCardPartId } } as never)
    }

    async getServices(id: string, params?: Record<string, unknown>) {
        return this.get(JOB_CARD_ROUTES.GET_SERVICES, { params: { id }, query: params as any })
    }

    async addService(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_SERVICE, "post">) {
        return this.post(JOB_CARD_ROUTES.ADD_SERVICE, payload, { params: { id } })
    }

    async updateService(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.UPDATE_SERVICE, "put">) {
        return this.put(JOB_CARD_ROUTES.UPDATE_SERVICE, payload, { params: { id } })
    }

    async deleteService(id: string, jobCardServiceId: number) {
        return this.delete(JOB_CARD_ROUTES.DELETE_SERVICE, { params: { id }, body: { job_card_service_id: jobCardServiceId } } as never)
    }

    async addServiceAttachment(id: string, jobCardServiceId: number, files: File[]) {
        const fd = new FormData()
        fd.append("job_card_service_id", String(jobCardServiceId))
        for (const file of files) {
            fd.append("attachments[]", file)
        }
        return this.postFormData(`/api/job-cards/${id}/add-service-attachment`, fd)
    }

    async deleteServiceAttachment(id: string, jobCardServiceId: number, attachmentId: number) {
        return this.delete(JOB_CARD_ROUTES.DELETE_SERVICE_ATTACHMENT, { params: { id }, body: { job_card_service_id: jobCardServiceId, attachment_id: attachmentId } } as never)
    }

    async getExpenseItems(id: string, params?: Record<string, unknown>) {
        return this.get(JOB_CARD_ROUTES.GET_EXPENSE_ITEMS, { params: { id }, query: params as any })
    }

    async addExpenseItem(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_EXPENSE_ITEM, "post">) {
        return this.post(JOB_CARD_ROUTES.ADD_EXPENSE_ITEM, payload, { params: { id } })
    }

    async updateExpenseItem(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.UPDATE_EXPENSE_ITEM, "put">) {
        return this.put(JOB_CARD_ROUTES.UPDATE_EXPENSE_ITEM, payload, { params: { id } })
    }

    async deleteExpenseItem(id: string, jobCardExpenseItemId: number) {
        return this.delete(JOB_CARD_ROUTES.DELETE_EXPENSE_ITEM, { params: { id }, body: { job_card_expense_item_id: jobCardExpenseItemId } } as never)
    }

    async convertToInvoice(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CONVERT_TO_INVOICE, "post">) {
        return this.post(JOB_CARD_ROUTES.CONVERT_TO_INVOICE, payload, { params: { id } })
    }
}
