import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
import { __ } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
import { klona } from 'klona';
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets';
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core';
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US';
import '@univerjs/preset-sheets-core/lib/index.css';

// api
import EvaluationFormsService from '../../../../service/evaluation-forms-service';
import FormsService from '../../../../service/forms-service';

// store
import { storeGet, storeSet } from '../../../../store';

// tools
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
import { xlsxToWorkbookData } from './xlsxToWorkbookData';

// components
import BandoEditFormActions from '../BandoEditFormActions';
import { Toast } from 'primereact/toast';

const BandoEditFormStep3Excel = forwardRef(function () {
    const navigate = useNavigate();
    const { id } = useParams();
    const [formName, setFormName] = useState('');
    const [bandoStatus, setBandoStatus] = useState('');
    const [tagTooltip, setTagTooltip] = useState(null); // { label } | null
    const toast = useRef(null);
    const univerRef = useRef(null);
    const containerRef = useRef(null);
    const univerAPIRef = useRef(null);
    const formFieldsRef = useRef([]);
    const fieldsLoadedRef = useRef(false);
    const pendingWorkbookRef = useRef(undefined); // undefined = eval form not yet returned, null = returned with no workbook
    const mousePos = useRef({ x: 0, y: 0 });
    const fileInputRef = useRef(null);

    const getBandoId = () => {
        const parsed = parseInt(id)
        return !isNaN(parsed) ? parsed : 0;
    }

    const onSaveDraft = () => {
        const workbookData = univerAPIRef.current?.getActiveWorkbook()?.save() ?? null;
        const formId = storeGet('formId');
        const formData = {
            label: formName,
            content: workbookData,
        }

        storeSet('setAsyncRequest');
        EvaluationFormsService.updateForm(formId, formData, updateFormCallback, errUpdateFormCallback)
    }

    const updateFormCallback = (resp) => {
        if (resp.status === 'SUCCESS') {
            setBandoStatus(resp.data.callStatus);
            if (toast.current) {
                toast.current.show({
                    severity: 'success',
                    summary: '',
                    detail: __('Il bando è stato aggiornato correttamente!', 'gepafin')
                });
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const errUpdateFormCallback = (resp) => {
        set404FromErrorResponse(resp);
        storeSet('unsetAsyncRequest');
    }

    const openPreview = () => {
        const bandoId = getBandoId();
        navigate(`/bandi/${bandoId}/preview`);
    }

    const openPreviewEvaluation = () => {
        const bandoId = getBandoId();
        navigate(`/bandi/${bandoId}/preview-evaluation`);
    }

    const getFormCallback = (resp) => {
        if (resp.status === 'SUCCESS') {
            storeSet('formId', resp.data.id);
            storeSet('formLabel', resp.data.label);
            setFormName(resp.data.label);
            setBandoStatus(resp.data.callStatus);
            const content = resp.data.content ? klona(resp.data.content) : null;
            storeSet('formElements', content);
            const workbook = content && content.sheets ? content : null;
            if (fieldsLoadedRef.current) {
                initializeUniver(workbook);
            } else {
                pendingWorkbookRef.current = workbook; // null or workbook; signals eval form returned
            }
        } else {
            if (!fieldsLoadedRef.current) {
                pendingWorkbookRef.current = null; // eval form done, no workbook
            }
        }
        storeSet('unsetAsyncRequest');
    }

    const getFormsCallback = (resp) => {
        if (resp.status === 'SUCCESS') {
            const EXCLUDED_TYPES = new Set(['fileupload', 'fileselect']);
            const raw = (resp.data ?? []).flatMap(form =>
                (form.content ?? [])
                    .filter(f => !EXCLUDED_TYPES.has(f.name))
                    .map(f => ({ id: f.id, label: f.label }))
            );
            // Group by label: same label across forms → one entry with multiple ids
            const byLabel = new Map();
            raw.forEach(f => {
                if (!byLabel.has(f.label)) byLabel.set(f.label, { label: f.label, ids: [] });
                byLabel.get(f.label).ids.push(f.id);
            });
            formFieldsRef.current = Array.from(byLabel.values());
        }
        fieldsLoadedRef.current = true;
        if (pendingWorkbookRef.current !== undefined) {
            // eval form already returned; initialize with its workbook (may be null)
            initializeUniver(pendingWorkbookRef.current);
            pendingWorkbookRef.current = undefined;
        }
        // else: eval form hasn't returned yet; getFormCallback will trigger initializeUniver
    }

    const errGetFormsCallback = () => {
        fieldsLoadedRef.current = true;
        if (pendingWorkbookRef.current !== undefined) {
            initializeUniver(pendingWorkbookRef.current);
            pendingWorkbookRef.current = undefined;
        }
    }

    const errGetFormCallback = (resp) => {
        set404FromErrorResponse(resp);
        if (!fieldsLoadedRef.current) {
            pendingWorkbookRef.current = null;
        }
        storeSet('unsetAsyncRequest');
    }

    useEffect(() => {
        storeSet('setAsyncRequest');
        EvaluationFormsService.getFormForCall(id, getFormCallback, errGetFormCallback)
    }, [id]);

    useEffect(() => {
        FormsService.getFormsForCall(id, getFormsCallback, errGetFormsCallback);
    }, [id]);

    const insertFieldTag = (ids, type) => {
        const api = univerAPIRef.current;
        if (!api) return;
        const range = api.getActiveWorkbook()?.getActiveSheet()?.getActiveRange();
        if (!range) return;
        range.setValue(`{{gepafin_field:${ids.join(',')}|${type}}}`);
        range.setBackground('#dbeafe');
    };

    const initializeUniver = useCallback((workbookData) => {
        if (univerRef.current) {
            univerRef.current.dispose();
            univerRef.current = null;
            univerAPIRef.current = null;
        }

        if (!containerRef.current) return;

        const { univer, univerAPI } = createUniver({
            locale: LocaleType.EN_US,
            locales: {
                [LocaleType.EN_US]: mergeLocales(UniverPresetSheetsCoreEnUS),
            },
            presets: [
                UniverSheetsCorePreset({
                    container: containerRef.current,
                }),
            ],
        });

        univerAPI.createWorkbook(workbookData || { name: 'Sheet' });
        univerRef.current = univer;
        univerAPIRef.current = univerAPI;

        // Disable adding new sheets
        univerAPI.addEvent(univerAPI.Event.BeforeCommandExecute, (event) => {
            if (event.id === 'sheet.command.insert-sheet') {
                event.cancel = true;
            }
        });

        // Context menu: "Inserisci variabile GEPAFIN" with per-field submenus
        const fields = formFieldsRef.current;
        const submenu = univerAPI.createSubmenu({
            id: 'gepafin-insert-variable',
            title: 'Inserisci variabile GEPAFIN',
        });

        fields.forEach((field, index) => {
            if (index > 0) submenu.addSeparator();

            const menuKey = field.ids[0];
            const countLabel = field.ids.length > 1 ? ` [${field.ids.length}]` : '';

            submenu.addSubmenu(univerAPI.createMenu({
                id: `gepafin-field-${menuKey}-label`,
                title: `${field.label}${countLabel} (etichetta)`,
                action: () => insertFieldTag(field.ids, 'label'),
            }));

            submenu.addSubmenu(univerAPI.createMenu({
                id: `gepafin-field-${menuKey}-value`,
                title: `${field.label}${countLabel} (valore)`,
                action: () => insertFieldTag(field.ids, 'value'),
            }));
        });

        submenu.appendTo(['contextMenu.mainArea', 'contextMenu.others']);

        // Tooltip on hover over tagged cells
        univerAPI.addEvent(univerAPI.Event.CellHover, (params) => {
            const { row, column, worksheet } = params;
            const cellValue = worksheet?.getRange(row, column)?.getValue?.();
            if (typeof cellValue === 'string' && cellValue.startsWith('{{gepafin_field:')) {
                const match = cellValue.match(/\{\{gepafin_field:([^|]+)\|([^}]+)\}\}/);
                if (match) {
                    const tagIds = match[1].split(',');
                    const field = formFieldsRef.current.find(f => f.ids.some(id => tagIds.includes(id)));
                    const countSuffix = tagIds.length > 1 ? ` — ${tagIds.length} moduli` : '';
                    setTagTooltip({ label: `${field ? field.label : match[1]} (${match[2]})${countSuffix}` });
                }
            } else {
                setTagTooltip(null);
            }
        });
    }, []); // containerRef, formFieldsRef, univerRef, univerAPIRef are stable refs

    useEffect(() => {
        return () => {
            if (univerRef.current) {
                univerRef.current.dispose();
                univerRef.current = null;
                univerAPIRef.current = null;
            }
        };
    }, []);

    // Prevent page scroll while hovering over the spreadsheet
    useEffect(() => {
        const el = containerRef.current;
        if (!el) return;
        const handler = (e) => { e.stopPropagation(); e.preventDefault(); };
        el.addEventListener('wheel', handler, { passive: false });
        return () => el.removeEventListener('wheel', handler);
    }, []);

    const handleImport = (e) => {
        const file = e.target.files?.[0];
        if (!file) return;
        const reader = new FileReader();
        reader.onload = (ev) => {
            const data = xlsxToWorkbookData(ev.target.result);
            initializeUniver(data);
        };
        reader.readAsArrayBuffer(file);
        e.target.value = ''; // reset so same file can be re-imported
    };

    return (
        <div className="appForm">
            <div className="appPageSection">
                <div style={{ marginBottom: '8px', display: 'flex', justifyContent: 'flex-end' }}>
                    <input
                        ref={fileInputRef}
                        type="file"
                        accept=".xlsx,.xls,.csv,.ods"
                        style={{ display: 'none' }}
                        onChange={handleImport}
                    />
                    <button
                        type="button"
                        className="p-button p-button-outlined p-button-sm"
                        onClick={() => fileInputRef.current?.click()}
                    >
                        {__('Importa foglio', 'gepafin')}
                    </button>
                </div>
                <div
                    ref={containerRef}
                    style={{ width: '100%', height: '700px' }}
                    onMouseMove={(e) => { mousePos.current = { x: e.clientX, y: e.clientY }; }}
                    onMouseLeave={() => setTagTooltip(null)}
                />
                {tagTooltip && (
                    <div style={{
                        position: 'fixed',
                        top: mousePos.current.y - 36,
                        left: mousePos.current.x + 12,
                        background: '#1e293b',
                        color: '#fff',
                        padding: '4px 8px',
                        borderRadius: '4px',
                        fontSize: '12px',
                        pointerEvents: 'none',
                        zIndex: 9999,
                        whiteSpace: 'nowrap',
                    }}>
                        {tagTooltip.label}
                    </div>
                )}
            </div>

            <div className="appPage__spacer"></div>

            <div className="appPageSection__hr">
                <span>{__('Azioni', 'gepafin')}</span>
            </div>

            <Toast ref={toast} />
            <BandoEditFormActions
                id={id}
                status={bandoStatus}
                submitFn={onSaveDraft}
                openPreview={openPreview}
                openPreviewEvaluation={openPreviewEvaluation}/>
        </div>
    )
})

export default BandoEditFormStep3Excel;
