import { FormGroup } from '@admin/components/ui/forms/form-group';
import { FormNumberInput } from '@admin/components/ui/forms/form-number-input';
import { FormSelect } from '@admin/components/ui/forms/form-select';
import { FormSwitch } from '@admin/components/ui/forms/form-switch';
import { formHelpClassName, formLabelClassName } from '@admin/components/ui/field-styles';
import { DocumentFieldSchemaEditor } from '@admin/pages/qr-codes/documentations/templates/document-field-schema-editor';
import { DocumentLayoutFields } from '@admin/pages/qr-codes/documentations/templates/document-layout-fields';
import {
    emptyDocumentLayout,
    type DocumentField,
    type DocumentLayoutConfig,
    type DocumentPresetOption,
    type DocumentPresetSchema,
    type DocumentSelectOption,
    type DocumentTemplateOption,
} from '@admin/types/document';
import type { AdministrativeUnitOption } from '@admin/types/administrative-unit';

export type DocumentTemplateFormData = {
    parent_id: string;
    administrative_unit_id: string;
    name: string;
    slug: string;
    kind: string;
    description: string;
    preset: string;
    field_schema: DocumentField[];
    layout: DocumentLayoutConfig;
    child_editable_keys: string[];
    sort_order: number;
    status: boolean;
};

export type DocumentTemplateFormSection = 'details' | 'fields' | 'design' | 'children' | 'all';

type DocumentTemplateFormFieldsProps = {
    data: DocumentTemplateFormData;
    errors: Record<string, string>;
    parents: DocumentTemplateOption[];
    units?: AdministrativeUnitOption[];
    presets: DocumentPresetOption[];
    presetSchemas: Record<string, DocumentPresetSchema>;
    fieldTypes: DocumentSelectOption[];
    styleOptions: DocumentSelectOption[];
    qrPositionOptions: DocumentSelectOption[];
    editableKeyOptions: DocumentSelectOption[];
    templateId?: number | null;
    lockParent?: boolean;
    /** Which section to render. Use `all` on create. */
    section?: DocumentTemplateFormSection;
    setData: (key: string, value: unknown) => void;
};

export function DocumentTemplateFormFields({
    data,
    errors,
    parents,
    units = [],
    presets,
    presetSchemas,
    fieldTypes,
    styleOptions,
    qrPositionOptions,
    editableKeyOptions,
    templateId = null,
    lockParent = false,
    section = 'all',
    setData,
}: DocumentTemplateFormFieldsProps) {
    const selectedParent = parents.find((parent) => String(parent.id) === data.parent_id) ?? null;
    const isChild = selectedParent !== null || (lockParent && Boolean(data.parent_id));
    const inheritedFields = selectedParent?.fields ?? data.field_schema;
    const editableKeys = isChild
        ? (selectedParent?.child_editable_keys ?? data.child_editable_keys ?? [])
        : null;

    const show = (name: Exclude<DocumentTemplateFormSection, 'all'>): boolean =>
        section === 'all' || section === name;

    const applyPreset = (preset: string) => {
        const schema = presetSchemas[preset];
        setData('preset', preset);

        if (!schema || isChild) {
            return;
        }

        setData('kind', schema.kind);
        setData('field_schema', schema.field_schema);
        setData('layout', { ...emptyDocumentLayout(), ...schema.layout });
    };

    const selectParent = (parentId: string) => {
        setData('parent_id', parentId);
        const parent = parents.find((item) => String(item.id) === parentId);

        if (!parent) {
            return;
        }

        setData('kind', parent.kind);
        setData('field_schema', parent.fields);
        setData('layout', { ...emptyDocumentLayout(), ...parent.layout });
        setData('child_editable_keys', parent.child_editable_keys ?? []);

        if (parent.administrative_unit_id) {
            setData('administrative_unit_id', String(parent.administrative_unit_id));
        }
    };

    return (
        <>
            {show('details') && (
                <div className="space-y-1">
                    {!lockParent && (
                        <FormSelect
                            label="Parent template"
                            value={data.parent_id}
                            placeholder="None — this is a parent template"
                            options={parents.map((parent) => ({
                                value: String(parent.id),
                                label: parent.name,
                            }))}
                            helpText="Child templates inherit columns. Only allowed design options can change."
                            error={errors.parent_id}
                            onChange={selectParent}
                        />
                    )}

                    <FormSelect
                        label="Administrative unit"
                        value={data.administrative_unit_id}
                        options={units.map((unit) => ({
                            value: String(unit.id),
                            label: unit.name,
                        }))}
                        placeholder="Select a unit"
                        helpText={
                            isChild
                                ? 'Child templates stay in the same unit as the parent.'
                                : 'Each unit can have many templates. Documents created from this template belong to this unit.'
                        }
                        error={errors.administrative_unit_id}
                        onChange={(value) => setData('administrative_unit_id', value)}
                        selectProps={{ required: !isChild, disabled: isChild }}
                    />

                    {!isChild && !lockParent && (
                        <FormSelect
                            label="Start from"
                            value={data.preset}
                            options={presets.map((preset) => ({
                                value: preset.value,
                                label: preset.label,
                            }))}
                            helpText={presets.find((preset) => preset.value === data.preset)?.description}
                            sortAlphabetically={false}
                            onChange={applyPreset}
                        />
                    )}

                    <FormGroup
                        label="Name"
                        error={errors.name}
                        inputProps={{
                            value: data.name,
                            required: true,
                            onChange: (event) => setData('name', event.target.value),
                        }}
                    />

                    <FormGroup
                        label="Slug"
                        helpText="Unique code for this template. Generated from the name if left blank."
                        error={errors.slug}
                        inputProps={{
                            value: data.slug,
                            placeholder: 'invoice',
                            onChange: (event) => setData('slug', event.target.value),
                        }}
                    />

                    {!isChild && (
                        <FormGroup
                            label="Kind"
                            helpText="Generic type such as invoice, receipt, or certificate."
                            error={errors.kind}
                            inputProps={{
                                value: data.kind,
                                onChange: (event) => setData('kind', event.target.value),
                            }}
                        />
                    )}

                    <FormGroup
                        label="Description"
                        as="textarea"
                        error={errors.description}
                        inputProps={{
                            value: data.description,
                            rows: 3,
                            onChange: (event) => setData('description', event.target.value),
                        }}
                    />

                    <FormNumberInput
                        label="Display order"
                        helpText="Lower numbers appear first."
                        min={0}
                        value={data.sort_order}
                        error={errors.sort_order}
                        required
                        onChange={(value) => setData('sort_order', value)}
                    />

                    <FormSwitch
                        id="document-template-status"
                        label="Active"
                        checked={data.status}
                        onChange={(event) => setData('status', event.target.checked)}
                    />
                </div>
            )}

            {show('fields') && (
                <DocumentFieldSchemaEditor
                    fields={isChild ? inheritedFields : data.field_schema}
                    fieldTypes={fieldTypes}
                    disabled={isChild}
                    error={errors.field_schema}
                    onChange={(fields) => setData('field_schema', fields)}
                />
            )}

            {show('design') && (
                <DocumentLayoutFields
                    layout={data.layout}
                    fields={isChild ? inheritedFields : data.field_schema}
                    styleOptions={styleOptions}
                    qrPositionOptions={qrPositionOptions}
                    editableKeys={editableKeys}
                    templateId={templateId}
                    errors={errors}
                    onChange={(layout) => setData('layout', { ...data.layout, ...layout })}
                />
            )}

            {show('children') && !isChild && (
                <div>
                    <p className={formLabelClassName}>Child templates may change</p>
                    <p className={formHelpClassName}>
                        Choose which design options a child template can override. Columns always come from the parent.
                    </p>
                    <div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
                        {editableKeyOptions.map((option) => {
                            const checked = data.child_editable_keys.includes(option.value);

                            return (
                                <label
                                    key={option.value}
                                    className="inline-flex items-center gap-2 rounded-sm border border-defaultborder px-3 py-2 text-sm dark:border-white/10"
                                >
                                    <input
                                        type="checkbox"
                                        className="ti-form-checkbox"
                                        checked={checked}
                                        onChange={(event) => {
                                            const next = event.target.checked
                                                ? [...data.child_editable_keys, option.value]
                                                : data.child_editable_keys.filter((key) => key !== option.value);

                                            setData('child_editable_keys', next);
                                        }}
                                    />
                                    {option.label}
                                </label>
                            );
                        })}
                    </div>
                </div>
            )}
        </>
    );
}
