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

export const INVOICE_ROUTES = {
    INDEX: "/api/invoices",
    BY_ID: "/api/invoices/{id}",
    ADD_ATTACHMENT: "/api/invoices/{id}/add-attachment",
    DELETE_ATTACHMENT: "/api/invoices/{id}/delete-attachment",
    DOCUMENTS: "/api/invoice-documents",
    DOCUMENT_BY_ID: "/api/invoice-documents/{id}",
    NOTES: "/api/invoice-notes",
    NOTE_BY_ID: "/api/invoice-notes/{id}",
    LABELS: "/api/invoice-labels",
    LABEL_BY_ID: "/api/invoice-labels/{id}",
} as const satisfies Record<string, ApiPath>

// Enhanced invoice type with additional fields
export interface InvoiceShowData {
    id?: string | number
    amount?: string | number
    received_payment?: string | number
    customer?: {
        id?: string | number
        first_name?: string
        last_name?: string
        company_name?: string
    }
    customer_id?: string | number
    customer_name?: string
    [key: string]: any // Allow additional properties
}

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

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

    async deleteAttachment(invoiceId: string, attachmentId: number) {
        return this.delete(INVOICE_ROUTES.DELETE_ATTACHMENT, {
            params: { id: invoiceId },
            body: { attachment_id: attachmentId },
        } as never)
    }

    // ── Documents ──
    async listDocuments(query?: ApiListQueryParams & { invoice_id?: string | number }) {
        return this.get(INVOICE_ROUTES.DOCUMENTS, query ? { query } as never : undefined)
    }

    async createDocument(payload: ApiRequestBody<typeof INVOICE_ROUTES.DOCUMENTS, "post">) {
        return this.post(INVOICE_ROUTES.DOCUMENTS, payload)
    }

    async updateDocument(id: string, payload: ApiRequestBody<typeof INVOICE_ROUTES.DOCUMENT_BY_ID, "put">) {
        return this.put(INVOICE_ROUTES.DOCUMENT_BY_ID, payload, { params: { id } })
    }

    async destroyDocument(id: string) {
        return this.delete(INVOICE_ROUTES.DOCUMENT_BY_ID, { params: { id } })
    }

    // ── Notes ──
    async listNotes(query?: ApiListQueryParams & { invoice_id?: string | number }) {
        return this.get(INVOICE_ROUTES.NOTES, query ? { query } as never : undefined)
    }

    async createNote(payload: ApiRequestBody<typeof INVOICE_ROUTES.NOTES, "post">) {
        return this.post(INVOICE_ROUTES.NOTES, payload)
    }

    async updateNote(id: string, payload: ApiRequestBody<typeof INVOICE_ROUTES.NOTE_BY_ID, "put">) {
        return this.put(INVOICE_ROUTES.NOTE_BY_ID, payload, { params: { id } })
    }

    async destroyNote(id: string) {
        return this.delete(INVOICE_ROUTES.NOTE_BY_ID, { params: { id } })
    }

    // ── Labels ──
    async listLabels(query?: ApiListQueryParams) {
        return this.get(INVOICE_ROUTES.LABELS, query ? { query } as never : undefined)
    }

    async createLabel(payload: ApiRequestBody<typeof INVOICE_ROUTES.LABELS, "post">) {
        return this.post(INVOICE_ROUTES.LABELS, payload)
    }

    async updateLabel(id: string, payload: ApiRequestBody<typeof INVOICE_ROUTES.LABEL_BY_ID, "put">) {
        return this.put(INVOICE_ROUTES.LABEL_BY_ID, payload, { params: { id } })
    }

    async destroyLabel(id: string) {
        return this.delete(INVOICE_ROUTES.LABEL_BY_ID, { params: { id } })
    }
}
