import {
    dangerSoftButtonClassName,
    formControlClassName,
    formErrorClassName,
    formHelpClassName,
    formLabelClassName,
    primarySoftButtonClassName,
} from '@admin/components/ui/field-styles';
import { cn } from '@admin/lib/utils';
import { emptyDocumentField, type DocumentField, type DocumentSelectOption } from '@admin/types/document';

type DocumentFieldSchemaEditorProps = {
    fields: DocumentField[];
    fieldTypes: DocumentSelectOption[];
    disabled?: boolean;
    error?: string;
    onChange: (fields: DocumentField[]) => void;
};

function slugifyKey(value: string): string {
    return value
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, '_')
        .replace(/^_+|_+$/g, '')
        .replace(/^([0-9])/, 'f_$1');
}

export function DocumentFieldSchemaEditor({
    fields,
    fieldTypes,
    disabled = false,
    error,
    onChange,
}: DocumentFieldSchemaEditorProps) {
    const updateField = (index: number, patch: Partial<DocumentField>) => {
        onChange(fields.map((field, fieldIndex) => (fieldIndex === index ? { ...field, ...patch } : field)));
    };

    const moveField = (index: number, direction: -1 | 1) => {
        const nextIndex = index + direction;

        if (nextIndex < 0 || nextIndex >= fields.length) {
            return;
        }

        const next = [...fields];
        const [moved] = next.splice(index, 1);
        next.splice(nextIndex, 0, moved);
        onChange(next);
    };

    return (
        <div>
            <div className="mb-3 flex flex-wrap items-center justify-between gap-3">
                <div>
                    <p className={formLabelClassName}>Columns</p>
                    <p className={formHelpClassName}>
                        These columns are filled when a document record is created. Mark unique keys to block duplicates.
                    </p>
                </div>
                {!disabled && (
                    <button
                        type="button"
                        className={primarySoftButtonClassName}
                        onClick={() => onChange([...fields, emptyDocumentField()])}
                    >
                        <i className="ri-add-line me-1" />
                        Add column
                    </button>
                )}
            </div>

            <div className="table-responsive">
                <table className="ti-custom-table ti-custom-table-head ti-custom-table-hover w-full min-w-[720px]">
                    <thead>
                        <tr>
                            <th className="w-10">#</th>
                            <th>Label</th>
                            <th>Key</th>
                            <th className="w-36">Type</th>
                            <th className="w-20 text-center">Req</th>
                            <th className="w-20 text-center">Unique</th>
                            <th>Help</th>
                            {!disabled && <th className="w-28 text-end">Actions</th>}
                        </tr>
                    </thead>
                    <tbody>
                        {fields.length === 0 ? (
                            <tr>
                                <td colSpan={disabled ? 7 : 8} className="text-center text-sm text-textmuted">
                                    No columns yet. Add a column to define what each document stores.
                                </td>
                            </tr>
                        ) : (
                            fields.map((field, index) => (
                                <tr key={`${field.key || 'new'}-${index}`}>
                                    <td className="align-middle text-sm text-textmuted">{index + 1}</td>
                                    <td className="align-middle">
                                        <input
                                            className={formControlClassName}
                                            value={field.label}
                                            disabled={disabled}
                                            placeholder="Label"
                                            onChange={(event) => {
                                                const label = event.target.value;
                                                const shouldSyncKey =
                                                    field.key === '' || field.key === slugifyKey(field.label);

                                                updateField(index, {
                                                    label,
                                                    key: shouldSyncKey ? slugifyKey(label) : field.key,
                                                });
                                            }}
                                        />
                                    </td>
                                    <td className="align-middle">
                                        <input
                                            className={formControlClassName}
                                            value={field.key}
                                            disabled={disabled}
                                            placeholder="key"
                                            onChange={(event) =>
                                                updateField(index, { key: slugifyKey(event.target.value) })
                                            }
                                        />
                                    </td>
                                    <td className="align-middle">
                                        <select
                                            className={cn('ti-form-select', formControlClassName)}
                                            value={field.type}
                                            disabled={disabled}
                                            onChange={(event) =>
                                                updateField(index, {
                                                    type: event.target.value as DocumentField['type'],
                                                })
                                            }
                                        >
                                            {fieldTypes.map((type) => (
                                                <option key={type.value} value={type.value}>
                                                    {type.label}
                                                </option>
                                            ))}
                                        </select>
                                    </td>
                                    <td className="align-middle text-center">
                                        <input
                                            type="checkbox"
                                            className="ti-form-checkbox"
                                            checked={field.required}
                                            disabled={disabled}
                                            title="Required"
                                            onChange={(event) =>
                                                updateField(index, { required: event.target.checked })
                                            }
                                        />
                                    </td>
                                    <td className="align-middle text-center">
                                        <input
                                            type="checkbox"
                                            className="ti-form-checkbox"
                                            checked={Boolean(field.unique)}
                                            disabled={disabled}
                                            title="Unique key"
                                            onChange={(event) =>
                                                updateField(index, { unique: event.target.checked })
                                            }
                                        />
                                    </td>
                                    <td className="align-middle">
                                        <input
                                            className={formControlClassName}
                                            value={field.help ?? ''}
                                            disabled={disabled}
                                            placeholder="Optional help"
                                            onChange={(event) =>
                                                updateField(index, { help: event.target.value || null })
                                            }
                                        />
                                        {field.type === 'select' && (
                                            <input
                                                className={cn(formControlClassName, 'mt-2')}
                                                value={field.options.join(', ')}
                                                disabled={disabled}
                                                placeholder="Options, comma separated"
                                                onChange={(event) =>
                                                    updateField(index, {
                                                        options: event.target.value
                                                            .split(',')
                                                            .map((option) => option.trim())
                                                            .filter(Boolean),
                                                    })
                                                }
                                            />
                                        )}
                                    </td>
                                    {!disabled && (
                                        <td className="align-middle text-end">
                                            <div className="inline-flex gap-1">
                                                <button
                                                    type="button"
                                                    className={primarySoftButtonClassName}
                                                    aria-label="Move up"
                                                    disabled={index === 0}
                                                    onClick={() => moveField(index, -1)}
                                                >
                                                    <i className="ri-arrow-up-line" />
                                                </button>
                                                <button
                                                    type="button"
                                                    className={primarySoftButtonClassName}
                                                    aria-label="Move down"
                                                    disabled={index === fields.length - 1}
                                                    onClick={() => moveField(index, 1)}
                                                >
                                                    <i className="ri-arrow-down-line" />
                                                </button>
                                                <button
                                                    type="button"
                                                    className={dangerSoftButtonClassName}
                                                    aria-label="Remove"
                                                    onClick={() =>
                                                        onChange(fields.filter((_, fieldIndex) => fieldIndex !== index))
                                                    }
                                                >
                                                    <i className="ri-delete-bin-line" />
                                                </button>
                                            </div>
                                        </td>
                                    )}
                                </tr>
                            ))
                        )}
                    </tbody>
                </table>
            </div>

            {error ? <span className={formErrorClassName}>{error}</span> : null}
        </div>
    );
}
