import type { CSSProperties, ReactNode } from 'react';
import { memo } from 'react';
import { storagePreviewUrl, DOCUMENT_DEFAULT_ACCENT, DOCUMENT_DEFAULT_SECONDARY, type DocumentBlock, type DocumentField, type DocumentLayoutConfig } from '@admin/types/document';

export type DocumentPreviewDocument = {
    reference: string;
    issued_at: string | null;
    values: Record<string, string>;
    fields: DocumentField[];
    layout: DocumentLayoutConfig & {
        logo_url?: string;
        signature_image_url?: string;
        thank_you_url?: string;
        header_contact_lines?: string[];
    };
    qr_url: string;
};

function fieldMap(fields: DocumentField[]): Record<string, DocumentField> {
    return Object.fromEntries(fields.map((field) => [field.key, field]));
}

function linesFrom(value?: string | string[]): string[] {
    if (Array.isArray(value)) {
        return value.filter(Boolean);
    }

    return (value || '')
        .split(/\r?\n/)
        .map((line) => line.trim())
        .filter(Boolean);
}

function looksLikeHtml(value?: string): boolean {
    return Boolean(value && /<[a-z][\s\S]*>/i.test(value));
}

function RichOrPlain({ value, className }: { value?: string; className?: string }): ReactNode {
    if (looksLikeHtml(value)) {
        return (
            <div
                className={`${className ?? ''} document-rich-text`.trim()}
                dangerouslySetInnerHTML={{ __html: value || '' }}
            />
        );
    }

    const lines = (value || '').split(/\r?\n/);

    return (
        <div className={className}>
            {lines.map((line, index) => (
                <span key={`${line}-${index}`}>
                    {line}
                    {index < lines.length - 1 ? <br /> : null}
                </span>
            ))}
        </div>
    );
}

function resolveValue(values: Record<string, string>, fieldKey: string | undefined, fallback = ''): string {
    if (!fieldKey) {
        return fallback;
    }

    return values[fieldKey] ?? fallback;
}

function FieldValue({
    label,
    value,
    type,
    showLabel = true,
}: {
    label: string;
    value?: string;
    type?: string;
    showLabel?: boolean;
}): ReactNode {
    const html = type === 'wysiwyg' || looksLikeHtml(value);

    return (
        <div className="document-builder-field">
            {showLabel ? <div className="document-builder-label">{label}</div> : null}
            {html ? (
                <div
                    className="document-builder-value document-rich-text"
                    dangerouslySetInnerHTML={{ __html: value || '—' }}
                />
            ) : (
                <div className="document-builder-value">{value || '—'}</div>
            )}
        </div>
    );
}

function renderBlock(
    block: DocumentBlock,
    document: DocumentPreviewDocument,
    byKey: Record<string, DocumentField>,
): ReactNode {
    const layout = document.layout;
    const values = document.values;
    const contactLines = linesFrom(layout.header_contact_lines ?? layout.header_contact);

    switch (block.type) {
        case 'header':
            return (
                <header key={block.id} className="document-builder-header">
                    {block.show_logo !== false ? (
                        <div className="document-builder-brand">
                            {layout.logo_url ? (
                                <img
                                    src={layout.logo_url}
                                    alt={layout.company_name || 'Logo'}
                                    className="document-invoice-logo"
                                />
                            ) : (
                                <span className="document-invoice-brand-name">{layout.company_name || 'Document'}</span>
                            )}
                        </div>
                    ) : null}
                    {block.show_title !== false ? (
                        <div className="document-invoice-title-badge">
                            <span>{layout.title || 'Document'}</span>
                        </div>
                    ) : null}
                    {block.show_contact !== false ? (
                        <div className="document-invoice-contact">
                            {contactLines.map((line) => (
                                <p key={line}>{line}</p>
                            ))}
                        </div>
                    ) : null}
                </header>
            );

        case 'heading': {
            const text = resolveValue(values, block.field, block.text || '');

            return (
                <h2 key={block.id} className="document-builder-heading">
                    {text || '—'}
                </h2>
            );
        }

        case 'paragraph': {
            const content = resolveValue(values, block.field, block.html || '');

            return <RichOrPlain key={block.id} value={content} className="document-builder-paragraph" />;
        }

        case 'field': {
            const key = block.field || '';
            const meta = byKey[key];

            return (
                <FieldValue
                    key={block.id}
                    label={meta?.label ?? key}
                    value={values[key]}
                    type={meta?.type}
                    showLabel={block.show_label !== false}
                />
            );
        }

        case 'fields': {
            const keys = (block.fields ?? []).filter(Boolean);

            return (
                <div key={block.id} className="document-builder-fields">
                    {keys.map((key) => {
                        const meta = byKey[key];

                        return (
                            <FieldValue
                                key={`${block.id}-${key}`}
                                label={meta?.label ?? key}
                                value={values[key]}
                                type={meta?.type}
                                showLabel={block.show_labels !== false}
                            />
                        );
                    })}
                </div>
            );
        }

        case 'table': {
            const columns = block.columns ?? [];

            return (
                <div key={block.id} className="document-builder-table">
                    <div
                        className="document-builder-table-head"
                        style={{ gridTemplateColumns: `repeat(${Math.max(columns.length, 1)}, 1fr)` }}
                    >
                        {columns.map((column) => (
                            <div key={`${block.id}-h-${column.field || column.label}`} className="document-builder-col-head">
                                {column.label || column.field}
                            </div>
                        ))}
                    </div>
                    <div
                        className="document-builder-table-body"
                        style={{ gridTemplateColumns: `repeat(${Math.max(columns.length, 1)}, 1fr)` }}
                    >
                        {columns.map((column) => {
                            const meta = byKey[column.field];
                            const value = values[column.field] ?? '';
                            const html = meta?.type === 'wysiwyg' || looksLikeHtml(value);

                            return html ? (
                                <div
                                    key={`${block.id}-c-${column.field}`}
                                    className="document-builder-cell document-rich-text"
                                    dangerouslySetInnerHTML={{ __html: value || '—' }}
                                />
                            ) : (
                                <div key={`${block.id}-c-${column.field}`} className="document-builder-cell">
                                    {value || '—'}
                                </div>
                            );
                        })}
                    </div>
                </div>
            );
        }

        case 'divider':
            return <hr key={block.id} className="document-builder-divider" />;

        case 'signature':
            if (!layout.show_signature) {
                return null;
            }

            return (
                <div key={block.id} className="document-invoice-signature">
                    <span className="document-invoice-signature-label">SIGNATURE :</span>
                    <div className="document-invoice-signature-line">
                        {layout.signature_image_url ? (
                            <img
                                src={layout.signature_image_url}
                                alt="Authorized signature"
                                className="document-invoice-signature-image"
                            />
                        ) : null}
                        {!layout.signature_image_url && values.signature ? (
                            <span className="document-invoice-signature-text">{values.signature}</span>
                        ) : null}
                    </div>
                </div>
            );

        case 'footer':
            return (
                <div key={block.id} className="document-invoice-footer">
                    <div className="document-invoice-footer-center">
                        {block.show_thank_you !== false ? (
                            layout.thank_you_url ? (
                                <img
                                    src={layout.thank_you_url}
                                    alt="Thank You!"
                                    className="document-invoice-thanks-image"
                                />
                            ) : (
                                <p className="document-invoice-thanks">Thank You!</p>
                            )
                        ) : null}
                        {block.show_qr !== false ? (
                            <img src={document.qr_url} alt="Verification QR code" className="document-invoice-qr" />
                        ) : null}
                    </div>
                </div>
            );

        default:
            return null;
    }
}

export function buildLivePreviewDocument(
    base: DocumentPreviewDocument,
    layout: DocumentLayoutConfig,
): DocumentPreviewDocument {
    const customLogo = storagePreviewUrl(layout.logo_path);
    const customSignature = storagePreviewUrl(layout.signature_image);
    const customThankYou = storagePreviewUrl(layout.thank_you_path);

    return {
        ...base,
        layout: {
            ...base.layout,
            ...layout,
            logo_url: customLogo || base.layout.logo_url,
            signature_image_url: customSignature || (layout.show_signature ? base.layout.signature_image_url : ''),
            thank_you_url: customThankYou || base.layout.thank_you_url,
            header_contact_lines: linesFrom(layout.header_contact),
            blocks: layout.blocks ?? [],
        },
    };
}

export const DocumentBuilderPreview = memo(function DocumentBuilderPreview({
    document,
}: {
    document: DocumentPreviewDocument;
}): ReactNode {
    const layout = document.layout;
    const blocks = layout.blocks ?? [];
    const byKey = fieldMap(document.fields);
    const accent = layout.accent_color || DOCUMENT_DEFAULT_ACCENT;
    const secondary = layout.secondary_color || DOCUMENT_DEFAULT_SECONDARY;

    return (
        <article
            className="document-sheet document-sheet--builder document-sheet--preview"
            style={
                {
                    '--invoice-accent': accent,
                    '--invoice-secondary': secondary,
                } as CSSProperties
            }
        >
            {blocks.length === 0 ? (
                <p className="document-preview-empty">Add blocks on the left to build this page.</p>
            ) : (
                blocks.map((block) => renderBlock(block, document, byKey))
            )}
        </article>
    );
});
