"use client"

import React from "react"
import { DataTable, type ActionsColumnOptions, type DataViewProps } from "@/shared/data-view/table-view"
import { useResourcePage, type UseResourcePageOptions, type ResourceItem, type ResourcePageClient } from "./use-resource-page"
import type { ColumnDef } from "@tanstack/react-table"

export type CrudResourceColumnHelpers<TClient extends ResourcePageClient> = {
    actionsColumn: (options?: Partial<ActionsColumnOptions<ResourceItem<TClient>>>) => ColumnDef<ResourceItem<TClient>, unknown>
    openEdit: (row: ResourceItem<TClient>) => void
    deleteItem: (id: string) => Promise<unknown>
}

export type CrudResourceContext<TClient extends ResourcePageClient> = {
    selectedItem: ResourceItem<TClient> | null
    isDialogOpen: boolean
    dialogResourceId: string | null
    isLoading: boolean
    data: ResourceItem<TClient>[]
    openCreate: () => void
    openEdit: (row: ResourceItem<TClient>) => void
    closeDialog: () => void
    deleteItem: (id: string) => Promise<unknown>
    invalidateQuery: () => void
}

type ReactNodeOrRender<TClient extends ResourcePageClient> =
    | React.ReactNode
    | ((context: CrudResourceContext<TClient>) => React.ReactNode)

type ManagedTableProps = "columns" | "data" | "pagination" | "sorting" | "onChange" | "isLoading"

export type CrudResourceProps<TClient extends ResourcePageClient> = UseResourcePageOptions<TClient> & {
    columns: ColumnDef<ResourceItem<TClient>>[] | ((helpers: CrudResourceColumnHelpers<TClient>) => ColumnDef<ResourceItem<TClient>>[])
    onRowClick?: (row: ResourceItem<TClient>) => void
    tableHeader?: ReactNodeOrRender<TClient>
    tableProps?: Omit<Partial<DataViewProps<ResourceItem<TClient>>>, ManagedTableProps>
    render?: (table: React.ReactElement, context: CrudResourceContext<TClient>) => React.ReactElement
}

export function CrudResource<TClient extends ResourcePageClient>({
    columns: columnsProp,
    routeKey,
    getClient,
    queryOptions,
    paramKey,
    extraParams,
    onRowClick,
    tableHeader,
    tableProps,
    render,
}: CrudResourceProps<TClient>) {
    type TItem = ResourceItem<TClient>

    const page = useResourcePage<TClient>({ routeKey, getClient, queryOptions, paramKey, extraParams })

    const columns = typeof columnsProp === "function"
        ? columnsProp({
            actionsColumn: page.actionsColumn,
            openEdit: page.openEdit,
            deleteItem: page.deleteItem,
        })
        : columnsProp

    type ListResponse = { data?: TItem[] }
    const responseData = page.data as ListResponse | undefined
    const items = (responseData?.data ?? []) as TItem[]

    const context: CrudResourceContext<TClient> = {
        selectedItem: page.selectedItem,
        isDialogOpen: page.isDialogOpen,
        dialogResourceId: page.dialogResourceId,
        isLoading: page.isLoading,
        data: items,
        openCreate: page.openCreate,
        openEdit: page.openEdit,
        closeDialog: page.closeDialog,
        deleteItem: page.deleteItem,
        invalidateQuery: () => page.invalidateQuery(),
    }

    const table = (
        <>
            {tableHeader && (typeof tableHeader === "function" ? tableHeader(context) : tableHeader)}
            <DataTable
                {...tableProps}
                columns={columns}
                data={items}
                pagination={page.pagination}
                sorting={page.sorting}
                onChange={page.handleChange}
                isLoading={page.isLoading}
                onRowClick={onRowClick ?? tableProps?.onRowClick}
            />
        </>
    )

    if (render) return render(table, context)
    return table
}
