import { ReactNode, useState } from 'react';
import { Button } from '@heroui/react';
import { DataTable, Column } from '@/Components/ui/DataTable';
import { Field } from '@/Components/ui/Field';
import { SelectField } from '@/Components/ui/SelectField';
import { FileField } from '@/Components/ui/FileField';
import { FormModal, FullWidth } from '@/Components/ui/FormModal';
import { useCreate, useDelete, useList, useUpdate } from '@/hooks/useResource';
import { useAuth } from '@/hooks/useAuth';
import { useConfirm } from '@/hooks/useConfirm';
import { RowActions } from '@/Components/ui/RowActions';
import { SearchInput } from '@/Components/ui/SearchInput';
import { FilterSelect } from '@/Components/ui/FilterSelect';
import { PlusIcon } from '@heroicons/react/24/solid';

export interface FieldConfig {
    name: string;
    label: string;
    type?: 'text' | 'number' | 'email' | 'password' | 'textarea' | 'select' | 'file';
    options?: { id: string | number; label: string }[];
    required?: boolean;
    folder?: string;
}

interface MasterCrudPageProps<T extends { id: number }> {
    title: string;
    resourceKey: string;
    apiPath: string;
    columns: Column<T>[];
    fields: FieldConfig[];
    emptyForm: Record<string, any>;
    rowActionsExtra?: (row: T) => ReactNode;
    menuKey?: string;
}

export function MasterCrudPage<T extends { id: number }>({
    title, resourceKey, apiPath, columns, fields, emptyForm, rowActionsExtra, menuKey,
}: MasterCrudPageProps<T>) {
    const { canWrite, canDelete, canEdit } = useAuth();
    const allowEdit = menuKey ? canEdit(menuKey) : canWrite;
    const allowDelete = menuKey ? canDelete(menuKey) : canWrite;
    const [search, setSearch] = useState('');
    const [status, setStatus] = useState('');
    const [modalOpen, setModalOpen] = useState(false);
    const [editingId, setEditingId] = useState<number | null>(null);
    const [form, setForm] = useState<Record<string, any>>(emptyForm);

    const { data, isLoading } = useList<T>(resourceKey, apiPath, { search, status: status || undefined, per_page: 500 });
    const create = useCreate<T>(resourceKey, apiPath);
    const update = useUpdate<T>(resourceKey, apiPath);
    const remove = useDelete(resourceKey, apiPath);
    const confirm = useConfirm();

    function openCreate() {
        setEditingId(null);
        setForm(emptyForm);
        setModalOpen(true);
    }

    function openEdit(row: T) {
        setEditingId(row.id);
        setForm({ ...emptyForm, ...row });
        setModalOpen(true);
    }

    function submit() {
        const action = editingId
            ? update.mutateAsync({ id: editingId, data: form as any })
            : create.mutateAsync(form as any);

        action.then(() => setModalOpen(false));
    }

    const showActionCol = allowEdit || allowDelete || !!rowActionsExtra;

    const actionColumn: Column<T> = {
        header: 'Aksi',
        cell: (row) => (
            <div className="flex items-center gap-1">
                {rowActionsExtra?.(row)}
                <RowActions
                    onEdit={allowEdit ? () => openEdit(row) : undefined}
                    onDelete={allowDelete ? async () => { if (await confirm({ title: 'Hapus data ini?' })) remove.mutate(row.id); } : undefined}
                />
            </div>
        ),
    };

    return (
        <div className="flex flex-col gap-5">
            <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 bg-white border border-slate-200/80 px-4 sm:px-6 py-4 sm:py-4.5 rounded-2xl shadow-sm">
                <h1 className="text-lg sm:text-xl font-bold text-gray-900">{title}</h1>
                {allowEdit && (
                    <Button onPress={openCreate} className="rounded-full px-3 sm:px-5 shadow-md bg-sky-600 hover:bg-sky-700 text-white shrink-0 self-start sm:self-auto">
                        <PlusIcon className="w-4 h-4" /> <span>Tambah</span>
                    </Button>
                )}
            </div>

            <div className="flex flex-nowrap items-center gap-2">
                <div className="flex-1 min-w-0">
                    <SearchInput value={search} onChange={setSearch} placeholder="Cari..." />
                </div>
                <FilterSelect
                    value={status}
                    onChange={setStatus}
                    placeholder="Semua Status"
                    items={[
                        { id: 'Aktif', label: 'Aktif' },
                        { id: 'Tidak Aktif', label: 'Tidak Aktif' },
                    ]}
                />
            </div>

            <DataTable
                columns={showActionCol ? [...columns, actionColumn] : columns}
                rows={data?.data ?? []}
                rowKey={(row) => row.id}
                isLoading={isLoading}
            />

            <FormModal
                isOpen={modalOpen}
                onOpenChange={setModalOpen}
                title={editingId ? `Edit ${title}` : `Tambah ${title}`}
                onSubmit={submit}
                isSubmitting={create.isPending || update.isPending}
            >
                {fields.map((f) => {
                    if (f.type === 'file') {
                        return (
                            <FileField
                                key={f.name}
                                label={f.label}
                                max={1}
                                folder={f.folder ?? 'master'}
                                value={form[f.name] ? [form[f.name]] : []}
                                onChange={(urls) => setForm((s) => ({ ...s, [f.name]: urls[0] ?? null }))}
                            />
                        );
                    }

                    const field = f.type === 'select' ? (
                        <SelectField
                            key={f.name}
                            label={f.label}
                            items={f.options ?? []}
                            selectedKey={form[f.name] ?? null}
                            onSelectionChange={(v) => setForm((s) => ({ ...s, [f.name]: v }))}
                            clearable={!f.required}
                        />
                    ) : (
                        <Field
                            key={f.name}
                            label={f.label}
                            type={f.type}
                            multiline={f.type === 'textarea'}
                            required={f.required}
                            value={form[f.name] ?? ''}
                            onChange={(v) => setForm((s) => ({ ...s, [f.name]: v }))}
                        />
                    );

                    return f.type === 'textarea' ? <FullWidth key={f.name}>{field}</FullWidth> : field;
                })}
            </FormModal>
        </div>
    );
}
