import { FormCheckbox } from '@admin/components/ui/forms/form-checkbox';
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 { FileUploadInput } from '@admin/components/ui/forms/file-upload-input';
import {
    formControlClassName,
    formHelpClassName,
    formLabelClassName,
    primarySoftButtonClassName,
} from '@admin/components/ui/field-styles';
import {
    DOCUMENT_DEFAULT_ACCENT,
    DOCUMENT_DEFAULT_FONT_SIZES,
    DOCUMENT_DEFAULT_SECONDARY,
    DOCUMENT_INVOICE_COLUMNS,
    DOCUMENT_RECOMMENDED_LOGO_HEIGHT,
    DOCUMENT_RECOMMENDED_LOGO_WIDTH,
    DOCUMENT_RECOMMENDED_THANK_YOU_HEIGHT,
    DOCUMENT_RECOMMENDED_THANK_YOU_WIDTH,
    brandingImagePreviewUrl,
    defaultBuilderBlocks,
    documentDefaultLogoUrl,
    documentDefaultThankYouUrl,
    type DocumentField,
    type DocumentInvoiceColumn,
    type DocumentLayoutConfig,
    type DocumentSelectOption,
} from '@admin/types/document';

type DocumentLayoutFieldsProps = {
    layout: DocumentLayoutConfig;
    fields: DocumentField[];
    styleOptions: DocumentSelectOption[];
    qrPositionOptions: DocumentSelectOption[];
    editableKeys?: string[] | null;
    templateId?: number | null;
    errors: Partial<Record<string, string>>;
    onChange: (layout: DocumentLayoutConfig) => void;
};

const ALL_KEYS: Array<keyof DocumentLayoutConfig> = [
    'style',
    'title',
    'company_name',
    'subtitle',
    'accent_color',
    'secondary_color',
    'header_contact',
    'nb_note',
    'bank_details',
    'currency',
    'logo_path',
    'thank_you_path',
    'signature_image',
    'footer_note',
    'show_signature',
    'qr_position',
    'blocks',
    'visible_columns',
    'description_font_size',
    'type_font_size',
    'amount_font_size',
    'bank_details_font_size',
    'amount_in_words_font_size',
];

export function DocumentLayoutFields({
    layout,
    fields: _fields,
    styleOptions,
    qrPositionOptions,
    editableKeys = null,
    templateId = null,
    errors,
    onChange,
}: DocumentLayoutFieldsProps) {
    const canEdit = (key: keyof DocumentLayoutConfig): boolean => {
        if (editableKeys === null) {
            return true;
        }

        return editableKeys.includes(key);
    };

    const setLayout = <K extends keyof DocumentLayoutConfig>(key: K, value: DocumentLayoutConfig[K]) => {
        onChange({ ...layout, [key]: value });
    };

    const setStyle = (style: DocumentLayoutConfig['style']) => {
        if (style === 'builder' && (layout.blocks?.length ?? 0) === 0) {
            onChange({ ...layout, style, blocks: defaultBuilderBlocks() });
            return;
        }

        setLayout('style', style);
    };

    const visibleColumns = layout.visible_columns ?? [...DOCUMENT_INVOICE_COLUMNS];
    const showsColumn = (column: DocumentInvoiceColumn): boolean => visibleColumns.includes(column);
    const toggleColumn = (column: DocumentInvoiceColumn, checked: boolean) => {
        setLayout(
            'visible_columns',
            DOCUMENT_INVOICE_COLUMNS.filter((item) => (item === column ? checked : showsColumn(item))),
        );
    };

    const openBuilder = () => {
        if (!templateId) {
            return;
        }

        window.open(
            route('admin.qr-codes.documentations.templates.builder', templateId),
            '_blank',
            'noopener,noreferrer',
        );
    };

    const visibleKeys = ALL_KEYS.filter((key) => canEdit(key));
    const isInvoice = layout.style === 'invoice';
    const isBuilder = layout.style === 'builder';

    return (
        <div>
            <p className={formLabelClassName}>Design</p>
            <p className={formHelpClassName}>
                {editableKeys === null
                    ? 'Parent templates control the full document look. Child templates can only change the keys you allow below.'
                    : 'Only the design options allowed by the parent template can be changed.'}
            </p>

            {visibleKeys.includes('style') && (
                <FormSelect
                    label="Style"
                    value={layout.style}
                    options={styleOptions}
                    error={errors['layout.style']}
                    sortAlphabetically={false}
                    onChange={(value) => setStyle(value as DocumentLayoutConfig['style'])}
                    selectProps={{ required: true }}
                />
            )}

            {isBuilder && (
                <div className="mb-4 rounded-sm border border-primary/20 bg-primary/5 p-4 dark:border-primary/30">
                    <p className="mb-1 text-sm font-medium">Visual builder</p>
                    <p className={formHelpClassName}>
                        {templateId
                            ? 'Open the builder in a new tab to arrange blocks with a live A4 preview.'
                            : 'Save this template first. You will be taken to the visual builder with a live preview.'}
                    </p>
                    {templateId ? (
                        <button type="button" className={`${primarySoftButtonClassName} mt-3`} onClick={openBuilder}>
                            <i className="ri-external-link-line me-1" />
                            Open visual builder
                        </button>
                    ) : null}
                </div>
            )}

            {visibleKeys.includes('title') && !isBuilder && (
                <FormGroup
                    label="Document title"
                    error={errors['layout.title']}
                    inputProps={{
                        value: layout.title,
                        required: true,
                        onChange: (event) => setLayout('title', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('company_name') && !isBuilder && (
                <FormGroup
                    label="Company name"
                    error={errors['layout.company_name']}
                    inputProps={{
                        value: layout.company_name,
                        onChange: (event) => setLayout('company_name', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('subtitle') && !isBuilder && (
                <FormGroup
                    label="Subtitle"
                    error={errors['layout.subtitle']}
                    inputProps={{
                        value: layout.subtitle,
                        onChange: (event) => setLayout('subtitle', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('accent_color') && !isBuilder && (
                <FormGroup label="Accent colour (orange)" error={errors['layout.accent_color']}>
                    <div className="flex items-center gap-3">
                        <input
                            type="color"
                            className="h-10 w-14 rounded-sm border border-defaultborder p-1"
                            value={layout.accent_color || DOCUMENT_DEFAULT_ACCENT}
                            onChange={(event) => setLayout('accent_color', event.target.value)}
                        />
                        <input
                            className={formControlClassName}
                            value={layout.accent_color}
                            maxLength={7}
                            onChange={(event) => setLayout('accent_color', event.target.value)}
                        />
                    </div>
                </FormGroup>
            )}

            {visibleKeys.includes('secondary_color') && isInvoice && (
                <FormGroup label="Secondary colour (grey)" error={errors['layout.secondary_color']}>
                    <div className="flex items-center gap-3">
                        <input
                            type="color"
                            className="h-10 w-14 rounded-sm border border-defaultborder p-1"
                            value={layout.secondary_color || DOCUMENT_DEFAULT_SECONDARY}
                            onChange={(event) => setLayout('secondary_color', event.target.value)}
                        />
                        <input
                            className={formControlClassName}
                            value={layout.secondary_color}
                            maxLength={7}
                            onChange={(event) => setLayout('secondary_color', event.target.value)}
                        />
                    </div>
                </FormGroup>
            )}

            {visibleKeys.includes('header_contact') && isInvoice && (
                <FormGroup
                    label="Header contact lines"
                    as="textarea"
                    helpText="One contact line per row. Used by the invoice header."
                    error={errors['layout.header_contact']}
                    inputProps={{
                        value: layout.header_contact,
                        rows: 3,
                        onChange: (event) => setLayout('header_contact', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('nb_note') && isInvoice && (
                <FormGroup
                    label="NB note"
                    as="textarea"
                    error={errors['layout.nb_note']}
                    inputProps={{
                        value: layout.nb_note,
                        rows: 2,
                        onChange: (event) => setLayout('nb_note', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('bank_details') && isInvoice && (
                <FormGroup
                    label="Bank details"
                    as="textarea"
                    helpText="One detail per row (bank, account name, number, SWIFT)."
                    error={errors['layout.bank_details']}
                    inputProps={{
                        value: layout.bank_details,
                        rows: 4,
                        onChange: (event) => setLayout('bank_details', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('currency') && isInvoice && (
                <FormGroup
                    label="Currency"
                    error={errors['layout.currency']}
                    inputProps={{
                        value: layout.currency,
                        onChange: (event) => setLayout('currency', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('visible_columns') && isInvoice && (
                <div className="mb-4">
                    <p className={formLabelClassName}>Invoice columns</p>
                    <p className={formHelpClassName}>
                        Choose which value columns appear beside number, date, and client. Existing invoices keep
                        all three until you change this.
                    </p>
                    <div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-3">
                        {DOCUMENT_INVOICE_COLUMNS.map((column) => (
                            <FormCheckbox
                                key={column}
                                id={`document-layout-column-${column}`}
                                label={column === 'amount' ? 'Amount' : column === 'type' ? 'Type' : 'Description'}
                                checked={showsColumn(column)}
                                onChange={(event) => toggleColumn(column, event.target.checked)}
                            />
                        ))}
                    </div>
                </div>
            )}

            {isInvoice &&
                [
                    'description_font_size',
                    'type_font_size',
                    'amount_font_size',
                    'bank_details_font_size',
                    'amount_in_words_font_size',
                ].some((key) => visibleKeys.includes(key as keyof DocumentLayoutConfig)) && (
                    <div className="mb-4">
                        <p className={formLabelClassName}>Value font sizes (pt)</p>
                        <p className={formHelpClassName}>
                            Controls invoice field values on the PDF and web preview. Range 8–24 pt.
                        </p>
                        <div className="mt-3 grid grid-cols-1 gap-x-4 sm:grid-cols-2">
                            {visibleKeys.includes('description_font_size') && showsColumn('description') && (
                                <FormNumberInput
                                    label="Description font size"
                                    value={layout.description_font_size ?? DOCUMENT_DEFAULT_FONT_SIZES.description_font_size}
                                    min={8}
                                    max={24}
                                    step={1}
                                    error={errors['layout.description_font_size']}
                                    onChange={(value) => setLayout('description_font_size', Number(value))}
                                />
                            )}
                            {visibleKeys.includes('type_font_size') && showsColumn('type') && (
                                <FormNumberInput
                                    label="Type font size"
                                    value={layout.type_font_size ?? DOCUMENT_DEFAULT_FONT_SIZES.type_font_size}
                                    min={8}
                                    max={24}
                                    step={1}
                                    error={errors['layout.type_font_size']}
                                    onChange={(value) => setLayout('type_font_size', Number(value))}
                                />
                            )}
                            {visibleKeys.includes('amount_font_size') && showsColumn('amount') && (
                                <FormNumberInput
                                    label="Amount font size"
                                    value={layout.amount_font_size ?? DOCUMENT_DEFAULT_FONT_SIZES.amount_font_size}
                                    min={8}
                                    max={24}
                                    step={1}
                                    error={errors['layout.amount_font_size']}
                                    onChange={(value) => setLayout('amount_font_size', Number(value))}
                                />
                            )}
                            {visibleKeys.includes('bank_details_font_size') && (
                                <FormNumberInput
                                    label="Bank details font size"
                                    value={layout.bank_details_font_size ?? DOCUMENT_DEFAULT_FONT_SIZES.bank_details_font_size}
                                    min={8}
                                    max={24}
                                    step={1}
                                    error={errors['layout.bank_details_font_size']}
                                    onChange={(value) => setLayout('bank_details_font_size', Number(value))}
                                />
                            )}
                            {visibleKeys.includes('amount_in_words_font_size') && showsColumn('amount') && (
                                <FormNumberInput
                                    label="Amount in words font size"
                                    value={
                                        layout.amount_in_words_font_size ??
                                        DOCUMENT_DEFAULT_FONT_SIZES.amount_in_words_font_size
                                    }
                                    min={8}
                                    max={24}
                                    step={1}
                                    error={errors['layout.amount_in_words_font_size']}
                                    onChange={(value) => setLayout('amount_in_words_font_size', Number(value))}
                                />
                            )}
                        </div>
                    </div>
                )}

            {visibleKeys.includes('logo_path') && !isBuilder && (
                <FileUploadInput
                    label={`Logo (optional, ${DOCUMENT_RECOMMENDED_LOGO_WIDTH}×${DOCUMENT_RECOMMENDED_LOGO_HEIGHT} px recommended)`}
                    inputId="document-layout-logo"
                    buttonText="Upload logo"
                    uploadUrl="/admin/api/document_template/upload_logo"
                    accept="image/png,image/jpeg,image/jpg,image/webp"
                    previewUrl={brandingImagePreviewUrl(
                        layout.logo_path,
                        layout.logo_url || documentDefaultLogoUrl(),
                    )}
                    error={errors['layout.logo_path']}
                    helpText="Transparent PNG recommended. Leave empty to use the Chato Beach Resort logo."
                    onSuccess={(filename) => setLayout('logo_path', filename)}
                />
            )}

            {visibleKeys.includes('thank_you_path') && !isBuilder && (
                <FileUploadInput
                    label={`Thank-you image (optional, ${DOCUMENT_RECOMMENDED_THANK_YOU_WIDTH}×${DOCUMENT_RECOMMENDED_THANK_YOU_HEIGHT} px recommended)`}
                    inputId="document-layout-thank-you"
                    buttonText="Upload thank-you image"
                    uploadUrl="/admin/api/document_template/upload_thank_you"
                    accept="image/png,image/jpeg,image/jpg,image/webp"
                    previewUrl={brandingImagePreviewUrl(
                        layout.thank_you_path,
                        layout.thank_you_url || documentDefaultThankYouUrl(),
                    )}
                    error={errors['layout.thank_you_path']}
                    helpText="Transparent PNG recommended. Leave empty to use the default thank-you image."
                    onSuccess={(filename) => setLayout('thank_you_path', filename)}
                />
            )}

            {visibleKeys.includes('signature_image') && !isBuilder && (
                <div className="space-y-1">
                    <FileUploadInput
                        label="Signature image (optional)"
                        inputId="document-layout-signature-image"
                        buttonText="Upload signature"
                        uploadUrl="/admin/api/document_template/upload_signature"
                        accept="image/png,image/jpeg,image/jpg,image/webp"
                        previewUrl={brandingImagePreviewUrl(layout.signature_image, layout.signature_image_url)}
                        error={errors['layout.signature_image']}
                        onSuccess={(filename) => setLayout('signature_image', filename)}
                    />
                    <p className={formHelpClassName}>
                        Transparent PNG, about 400×200px (max 800×400). Leave empty to use the default signature.
                    </p>
                </div>
            )}

            {visibleKeys.includes('footer_note') && !isBuilder && (
                <FormGroup
                    label="Footer note"
                    as="textarea"
                    error={errors['layout.footer_note']}
                    inputProps={{
                        value: layout.footer_note,
                        rows: 2,
                        onChange: (event) => setLayout('footer_note', event.target.value),
                    }}
                />
            )}

            {visibleKeys.includes('qr_position') && !isBuilder && (
                <FormSelect
                    label="QR position"
                    value={layout.qr_position}
                    options={qrPositionOptions}
                    error={errors['layout.qr_position']}
                    sortAlphabetically={false}
                    onChange={(value) => setLayout('qr_position', value as DocumentLayoutConfig['qr_position'])}
                />
            )}

            {visibleKeys.includes('show_signature') && !isBuilder && (
                <FormSwitch
                    id="document-layout-signature"
                    label="Show signature line"
                    checked={layout.show_signature}
                    onChange={(event) => setLayout('show_signature', event.target.checked)}
                />
            )}
        </div>
    );
}
