import 'bootstrap';
import { Modal } from 'bootstrap';
import './styles/sign.scss';

declare global {
    interface Window {
        pdfjsLib?: {
            getDocument: (src: { url: string; withCredentials?: boolean }) => {
                promise: Promise<{
                    numPages: number;
                    getPage: (pageNumber: number) => Promise<{
                        getViewport: (params: { scale: number }) => { width: number; height: number };
                        render: (params: { canvasContext: CanvasRenderingContext2D; viewport: { width: number; height: number } }) => { promise: Promise<void> };
                    }>;
                }>;
            };
            GlobalWorkerOptions: { workerSrc: string };
        };
    }
}

type GuestField = {
    id: number;
    type: string;
    page: number;
    posX: number;
    posY: number;
    width: number;
    height: number;
    required: boolean;
    value: string | null;
    completed: boolean;
};

document.addEventListener('DOMContentLoaded', () => {
    const app = document.getElementById('signGuestApp');
    const pagesEl = document.getElementById('signGuestPages');
    const loadingEl = document.getElementById('signGuestLoading');
    const finishBtn = document.getElementById('signGuestFinishBtn');
    const submitForm = document.getElementById('signGuestSubmitForm') as HTMLFormElement | null;
    const payloadInput = document.getElementById('signGuestPayload') as HTMLInputElement | null;
    const modalEl = document.getElementById('signatureModal');
    const sigTyped = document.getElementById('sigTyped') as HTMLInputElement | null;
    const sigTypedPreview = document.getElementById('sigTypedPreview');
    const sigTypedWrap = document.getElementById('sigTypedWrap');
    const sigDrawWrap = document.getElementById('sigDrawWrap');
    const sigCanvas = document.getElementById('sigCanvas') as HTMLCanvasElement | null;
    const sigClearBtn = document.getElementById('sigClearBtn');
    const sigApplyBtn = document.getElementById('sigApplyBtn');

    if (!app || !pagesEl) {
        return;
    }

    const modal = modalEl ? new Modal(modalEl) : null;
    if (modalEl && modalEl.parentElement !== document.body) {
        document.body.appendChild(modalEl);
    }

    let fields: GuestField[] = [];
    const fieldsNode = document.getElementById('signGuestFields');
    if (fieldsNode?.textContent) {
        try {
            fields = JSON.parse(fieldsNode.textContent) as GuestField[];
        } catch (error) {
            fields = [];
        }
    }

    const values = new Map<number, string>();
    fields.forEach((field) => {
        if (field.value) {
            values.set(field.id, field.value);
        } else if (field.type === 'date') {
            values.set(field.id, new Date().toLocaleDateString('de-DE'));
        }
    });

    let activeFieldId: number | null = null;
    let signatureData: string | null = null;
    let signatureType = 'typed';
    let drawing = false;

    const labelFor = (type: string): string => {
        if (type === 'signature') return app.dataset.labelSignature || 'Unterschrift';
        if (type === 'date') return app.dataset.labelDate || 'Datum';
        return app.dataset.labelText || 'Text';
    };

    const syncFieldDom = (fieldId: number) => {
        const el = pagesEl.querySelector<HTMLElement>(`[data-field-id="${fieldId}"]`);
        if (!el) {
            return;
        }
        const field = fields.find((item) => item.id === fieldId);
        const value = values.get(fieldId) || '';
        el.classList.toggle('is-filled', Boolean(value));
        const content = el.querySelector('.sign-guest-field__content');
        if (!content || !field) {
            return;
        }
        if (field.type === 'signature' && value.startsWith('data:image')) {
            content.innerHTML = `<img src="${value}" alt="signature">`;
        } else {
            content.textContent = value || labelFor(field.type);
        }
    };

    const openSignatureModal = (fieldId: number) => {
        activeFieldId = fieldId;
        modal?.show();
    };

    const createFieldBox = (field: GuestField): HTMLElement => {
        const box = document.createElement('button');
        box.type = 'button';
        box.className = 'sign-guest-field';
        box.dataset.fieldId = String(field.id);
        box.dataset.fieldType = field.type;
        box.style.left = `${field.posX}%`;
        box.style.top = `${field.posY}%`;
        box.style.width = `${field.width}%`;
        box.style.height = `${field.height}%`;
        box.innerHTML = `<span class="sign-guest-field__content">${values.get(field.id) || labelFor(field.type)}</span>`;
        if (values.get(field.id)) {
            box.classList.add('is-filled');
        }

        box.addEventListener('click', () => {
            if (field.type === 'signature') {
                openSignatureModal(field.id);
                return;
            }
            if (field.type === 'date') {
                const next = window.prompt(labelFor('date'), values.get(field.id) || new Date().toLocaleDateString('de-DE'));
                if (next !== null) {
                    values.set(field.id, next.trim());
                    syncFieldDom(field.id);
                }
                return;
            }
            const next = window.prompt(labelFor('text'), values.get(field.id) || '');
            if (next !== null) {
                values.set(field.id, next.trim());
                syncFieldDom(field.id);
            }
        });

        return box;
    };

    const renderPdf = async () => {
        if (!window.pdfjsLib) {
            if (loadingEl) loadingEl.textContent = 'PDF-Viewer konnte nicht geladen werden.';
            return;
        }
        const pdfUrl = app.dataset.pdfUrl;
        if (!pdfUrl) {
            return;
        }

        try {
            const pdf = await window.pdfjsLib.getDocument({ url: pdfUrl, withCredentials: true }).promise;
            pagesEl.innerHTML = '';
            const baseWidth = Math.min(860, app.clientWidth || 860);

            for (let pageNumber = 1; pageNumber <= pdf.numPages; pageNumber += 1) {
                const page = await pdf.getPage(pageNumber);
                const unscaled = page.getViewport({ scale: 1 });
                const scale = baseWidth / unscaled.width;
                const viewport = page.getViewport({ scale });

                const pageEl = document.createElement('div');
                pageEl.className = 'sign-pdf-page';
                pageEl.dataset.page = String(pageNumber);

                const canvas = document.createElement('canvas');
                canvas.width = viewport.width;
                canvas.height = viewport.height;
                canvas.className = 'sign-pdf-page__canvas';
                pageEl.appendChild(canvas);

                const layer = document.createElement('div');
                layer.className = 'sign-pdf-page__layer';
                pageEl.appendChild(layer);
                pagesEl.appendChild(pageEl);

                const context = canvas.getContext('2d');
                if (context) {
                    await page.render({ canvasContext: context, viewport }).promise;
                }

                fields
                    .filter((field) => field.page === pageNumber)
                    .forEach((field) => {
                        layer.appendChild(createFieldBox(field));
                        syncFieldDom(field.id);
                    });
            }

            pagesEl.hidden = false;
            if (loadingEl) loadingEl.hidden = true;
        } catch (error) {
            console.error(error);
            if (loadingEl) loadingEl.textContent = 'PDF konnte nicht geladen werden.';
        }
    };

    const canvasCtx = sigCanvas?.getContext('2d');
    if (sigCanvas && canvasCtx) {
        canvasCtx.strokeStyle = '#003FA5';
        canvasCtx.lineWidth = 2;
        canvasCtx.lineCap = 'round';

        const pos = (event: PointerEvent) => {
            const rect = sigCanvas.getBoundingClientRect();
            return {
                x: ((event.clientX - rect.left) / rect.width) * sigCanvas.width,
                y: ((event.clientY - rect.top) / rect.height) * sigCanvas.height,
            };
        };

        sigCanvas.addEventListener('pointerdown', (event) => {
            drawing = true;
            const point = pos(event);
            canvasCtx.beginPath();
            canvasCtx.moveTo(point.x, point.y);
            sigCanvas.setPointerCapture(event.pointerId);
        });
        sigCanvas.addEventListener('pointermove', (event) => {
            if (!drawing) return;
            const point = pos(event);
            canvasCtx.lineTo(point.x, point.y);
            canvasCtx.stroke();
        });
        sigCanvas.addEventListener('pointerup', () => {
            drawing = false;
        });
    }

    sigClearBtn?.addEventListener('click', () => {
        if (!sigCanvas || !canvasCtx) return;
        canvasCtx.clearRect(0, 0, sigCanvas.width, sigCanvas.height);
    });

    sigTyped?.addEventListener('input', () => {
        if (sigTypedPreview) {
            sigTypedPreview.textContent = sigTyped.value || ' ';
        }
    });

    document.querySelectorAll<HTMLInputElement>('input[name="sig_mode"]').forEach((radio) => {
        radio.addEventListener('change', () => {
            const mode = document.querySelector<HTMLInputElement>('input[name="sig_mode"]:checked')?.value || 'typed';
            if (sigTypedWrap) sigTypedWrap.hidden = mode !== 'typed';
            if (sigDrawWrap) sigDrawWrap.hidden = mode !== 'draw';
        });
    });

    sigApplyBtn?.addEventListener('click', () => {
        if (activeFieldId === null) {
            return;
        }
        const mode = document.querySelector<HTMLInputElement>('input[name="sig_mode"]:checked')?.value || 'typed';
        if (mode === 'typed') {
            const name = (sigTyped?.value || '').trim();
            if (!name) {
                return;
            }
            const canvas = document.createElement('canvas');
            canvas.width = 500;
            canvas.height = 140;
            const ctx = canvas.getContext('2d');
            if (!ctx) return;
            ctx.fillStyle = '#ffffff';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = '#003FA5';
            ctx.font = '48px "Brush Script MT", "Segoe Script", cursive';
            ctx.fillText(name, 24, 88);
            signatureData = canvas.toDataURL('image/png');
            signatureType = 'typed';
            values.set(activeFieldId, signatureData);
        } else if (sigCanvas && canvasCtx) {
            // Flatten onto white so transparent strokes remain visible in stamped PDFs.
            canvasCtx.save();
            canvasCtx.globalCompositeOperation = 'destination-over';
            canvasCtx.fillStyle = '#ffffff';
            canvasCtx.fillRect(0, 0, sigCanvas.width, sigCanvas.height);
            canvasCtx.restore();
            signatureData = sigCanvas.toDataURL('image/png');
            signatureType = 'draw';
            values.set(activeFieldId, signatureData);
        }
        syncFieldDom(activeFieldId);
        modal?.hide();
    });

    finishBtn?.addEventListener('click', () => {
        const missing = fields.filter((field) => field.required && !(values.get(field.id) || '').trim());
        if (missing.length > 0) {
            alert(app.dataset.incomplete || 'Bitte alle Pflichtfelder ausfüllen.');
            return;
        }
        if (!submitForm || !payloadInput) {
            return;
        }
        payloadInput.value = JSON.stringify({
            signatureData,
            signatureType,
            fields: fields.map((field) => ({
                id: field.id,
                value: values.get(field.id) || '',
            })),
        });
        submitForm.submit();
    });

    void renderPdf();
});
