import { useRef, useState } from 'react';
import {
    IconFileDescription, IconComponents, IconKeyboard, IconChevronDown, IconChevronUp,
    IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand,
    IconCopyPlus, IconTrash,
    IconLetterT, IconVariable, IconTextOrientation,
    IconQrcode, IconBarcode, IconPhotoScan, IconTable, IconPhoto, IconBoxMultiple, IconBoxMultipleFilled,
    IconUpload, IconLink, IconFileVector,
} from '@tabler/icons-react';
import {
    DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem,
} from '@/components/ui/dropdown-menu';
import ImageLinkDialog from '../ui/ImageLinkDialog';
import { usePrintEditorStore } from '../state/usePrintEditorStore';
import { ELEMENT_TYPES } from '../schema/documentSchema';
import { getShapeDef } from '../schema/shapeLibrary';
import { TEXT_PATH_INSERT } from '../utils/textPathLayout';
import { shapeGlyphIcon } from '../ui/shapeGlyph';
import { filesToImagePayloads, isArtworkFile } from '../utils/imageFiles';
import { useArtworkImport, ARTWORK_ACCEPT, ARTWORK_TITLE } from './useArtworkImport';
import { T } from '../ui/figma';
import LayersList from './LayersList';
import ShortcutsPanel from './ShortcutsPanel';

/* ------------------------------------------------------------------ *
 *  Elements — insert grid (admin)
 * ------------------------------------------------------------------ */

/** Shapes offered in the insert grid — the full catalogue lives in the toolbar menu. */
const ASSET_SHAPES = ['rect', 'ellipse', 'line', 'triangle', 'polygon', 'star', 'arrow', 'diamond'];

const ASSET_ITEMS = [
    { type: ELEMENT_TYPES.TEXT, label: 'Text', Icon: IconLetterT },
    {
        type: ELEMENT_TYPES.TEXT, label: 'Text on path', Icon: IconTextOrientation,
        overrides: TEXT_PATH_INSERT,
    },
    { type: ELEMENT_TYPES.PLACEHOLDER, label: 'Placeholder', Icon: IconVariable },
    ...ASSET_SHAPES.map((shape) => ({
        type: ELEMENT_TYPES.SHAPE,
        label: getShapeDef(shape).label,
        Icon: shapeGlyphIcon(shape),
        overrides: { shape },
    })),
    { type: ELEMENT_TYPES.QRCODE, label: 'QR code', Icon: IconQrcode },
    {
        type: ELEMENT_TYPES.QRCODE, label: 'QR + logo', Icon: IconPhotoScan,
        overrides: { name: 'QR + logo' }, withLogo: true,
    },
    { type: ELEMENT_TYPES.BARCODE, label: 'Barcode', Icon: IconBarcode },
    { type: ELEMENT_TYPES.TABLE, label: 'Table', Icon: IconTable },
];

function ElementsGrid() {
    const addElement = usePrintEditorStore((s) => s.addElement);
    const fileRef = useRef(null);
    // The QR-with-logo tile inserts the code, then asks for the picture that goes
    // in its middle — which is the QR element's own `src` (see utils/qrCode).
    const qrLogoRef = useRef(null);
    const qrLogoTarget = useRef(null);
    const [uploading, setUploading] = useState(false);
    const [linkOpen, setLinkOpen] = useState(false);
    const {
        importing, inputRef: importRef, openPicker, onArtworkSelected, runArtworkImport,
    } = useArtworkImport();

    const onImagesSelected = async (e) => {
        const files = Array.from(e.target.files || []);
        e.target.value = '';
        if (!files.length) return;
        // A file picker set to image/* still lists .psd / .tif / .svg (their MIME
        // types start with "image/"). Send those to the artwork importer: the
        // first two can never decode as an image, and an SVG carries a layer tree
        // that the flat-image path would throw away.
        const artwork = files.find(isArtworkFile);
        if (artwork) { runArtworkImport(artwork, { resize: false }); return; }
        setUploading(true);
        try {
            const payloads = await filesToImagePayloads(files, { maxSide: 280 });
            if (payloads.length) {
                usePrintEditorStore.getState().addElements(payloads.map((p) => ({
                    type: ELEMENT_TYPES.IMAGE, src: p.src, name: p.name, width: p.width, height: p.height,
                })));
            }
        } catch (err) {
            console.error('[print-editor] Image upload failed', err);
        } finally {
            setUploading(false);
        }
    };

    const onQrLogoSelected = async (e) => {
        const [file] = Array.from(e.target.files || []);
        e.target.value = '';
        const id = qrLogoTarget.current;
        qrLogoTarget.current = null;
        if (!file || !id) return;
        try {
            const [payload] = await filesToImagePayloads([file], { maxSide: 512 });
            if (payload?.src) usePrintEditorStore.getState().updateElement(id, { src: payload.src });
        } catch (err) {
            console.error('[print-editor] QR logo upload failed', err);
        }
    };

    const tile = 'flex flex-col items-center justify-center gap-1.5 aspect-square rounded-[6px] border ' +
        'border-[#e6e6e6] dark:border-[#444444] text-black/70 dark:text-white/70 ' +
        'hover:border-[#0d99ff] hover:text-[#0d99ff] transition-colors cursor-pointer';

    return (
        <div className="p-3 grid grid-cols-3 gap-2">
            <input ref={fileRef} type="file" accept="image/*" multiple className="hidden" onChange={onImagesSelected} />
            <input
                ref={importRef}
                type="file"
                accept={ARTWORK_ACCEPT}
                className="hidden"
                onChange={onArtworkSelected}
            />
            <input ref={qrLogoRef} type="file" accept="image/*" className="hidden" onChange={onQrLogoSelected} />
            {ASSET_ITEMS.map(({ type, label, Icon, overrides, withLogo }) => (
                <button
                    key={label}
                    type="button"
                    title={withLogo ? 'Insert a QR code and pick the logo for its middle' : `Insert ${label}`}
                    className={tile}
                    onClick={() => {
                        const el = addElement(type, overrides);
                        if (!withLogo || !el) return;
                        qrLogoTarget.current = el.id;
                        qrLogoRef.current?.click();
                    }}
                >
                    <Icon size={18} stroke={1.5} />
                    <span className="text-[9px] leading-none">{label}</span>
                </button>
            ))}
            <DropdownMenu>
                <DropdownMenuTrigger asChild>
                    <button
                        type="button"
                        title="Add an image — upload or from a link"
                        disabled={uploading}
                        className={`${tile} disabled:opacity-40`}
                    >
                        <IconPhoto size={18} stroke={1.5} />
                        <span className="text-[9px] leading-none">{uploading ? 'Uploading…' : 'Image'}</span>
                    </button>
                </DropdownMenuTrigger>
                <DropdownMenuContent align="start" sideOffset={6} className="min-w-44">
                    <DropdownMenuItem
                        className="text-[11px] gap-2 cursor-pointer"
                        onSelect={() => setTimeout(() => fileRef.current?.click(), 0)}
                    >
                        <IconUpload size={13} /> Upload from device
                    </DropdownMenuItem>
                    <DropdownMenuItem
                        className="text-[11px] gap-2 cursor-pointer"
                        // Defer past the menu's close/focus teardown, or the overlay
                        // can be mounted mid-teardown and never appear.
                        onSelect={() => setTimeout(() => setLinkOpen(true), 0)}
                    >
                        <IconLink size={13} /> Image from link
                    </DropdownMenuItem>
                </DropdownMenuContent>
            </DropdownMenu>

            <button
                type="button"
                title={ARTWORK_TITLE}
                disabled={importing}
                onClick={openPicker}
                className={`${tile} disabled:opacity-40`}
            >
                <IconFileVector size={18} stroke={1.5} />
                <span className="text-[9px] leading-none text-center">{importing ? 'Importing…' : 'Import file'}</span>
            </button>

            <ImageLinkDialog open={linkOpen} onClose={() => setLinkOpen(false)} />
        </div>
    );
}

/* ------------------------------------------------------------------ *
 *  Left panel — rail + file header + Layers / Elements
 * ------------------------------------------------------------------ */

export default function LeftPanel({
    headerLeft, metaSlot, subtitle, autosaveActive = false,
    collapsed = false, onToggleCollapsed,
}) {
    const [view, setView] = useState('file'); // file | elements | shortcuts
    // Template settings (slug / category / status / pricing) open INSIDE the panel,
    // above the layers — the title chevron toggles the section, it is not a popover.
    const [metaOpen, setMetaOpen] = useState(false);
    const {
        document: doc, selectedIds, duplicateSelected, deleteSelected,
        groupSelected, ungroupSelected, dirty,
    } = usePrintEditorStore();
    // The rail's own import — the same action as the Import tile inside Elements,
    // reachable without first switching panels. Its own hidden input, since the
    // grid's belongs to a panel that may not be mounted.
    const artwork = useArtworkImport();

    const selectionHasGroup = selectedIds.some((id) => (
        doc.elements.find((e) => e.id === id)?.groupId
    ));

    /** Rail chrome. `onClick`/`active` are for rail buttons that act instead of
     *  switching panels — the Import button below. */
    const railButton = ({ key, label, title, Icon, active = false, disabled = false, onClick }) => (
        <button
            key={key}
            type="button"
            title={title || label}
            disabled={disabled}
            onClick={onClick}
            className={`w-full flex flex-col items-center gap-1 py-2.5 transition-colors
                disabled:opacity-40 disabled:pointer-events-none
                ${active ? T.text : `${T.textSoft} hover:text-black dark:hover:text-white`}`}
        >
            <span className={`h-7 w-8 flex items-center justify-center rounded-[6px] ${active ? T.activeBg : ''}`}>
                <Icon size={17} stroke={1.6} />
            </span>
            <span className="text-[9px] leading-none">{label}</span>
        </button>
    );

    // Picking a panel while the sidebar is shut opens it: a rail button that
    // silently switches a view nobody can see would read as a dead button.
    const railItem = (id, label, Icon) => railButton({
        key: id,
        label,
        Icon,
        active: !collapsed && view === id,
        onClick: () => {
            setView(id);
            if (collapsed) onToggleCollapsed?.();
        },
    });

    return (
        <div className="flex h-full w-full min-h-0">
            {/* Icon rail */}
            <div className={`w-12 shrink-0 border-r ${T.border} flex flex-col items-center pt-1.5`}>
                {/* Give the canvas the panel's width back. On a laptop the two
                    sidebars leave little between them, and the layers are not
                    what an admin is looking at while nudging artwork. */}
                {onToggleCollapsed && railButton({
                    key: 'collapse',
                    label: collapsed ? 'Show' : 'Hide',
                    title: `${collapsed ? 'Show the sidebar' : 'Hide the sidebar — more room for the canvas'} (${
                        /Mac|iPhone|iPad|iPod/i.test(navigator.platform || navigator.userAgent || '') ? 'Cmd' : 'Ctrl'}+\\)`,
                    Icon: collapsed ? IconLayoutSidebarLeftExpand : IconLayoutSidebarLeftCollapse,
                    onClick: onToggleCollapsed,
                })}
                {railItem('file', 'File', IconFileDescription)}
                {railItem('elements', 'Elements', IconComponents)}
                {railButton({
                    key: 'import',
                    label: artwork.importing ? 'Importing…' : 'Import',
                    title: ARTWORK_TITLE,
                    Icon: IconFileVector,
                    disabled: artwork.importing,
                    onClick: artwork.openPicker,
                })}
                {railItem('shortcuts', 'Keys', IconKeyboard)}
                <input
                    ref={artwork.inputRef}
                    type="file"
                    accept={ARTWORK_ACCEPT}
                    className="hidden"
                    onChange={artwork.onArtworkSelected}
                />
            </div>

            {/* Panel content — unmounted while collapsed, not merely hidden: the
                layers list is the heaviest thing in here and it has no reason to
                keep re-rendering behind a closed panel. */}
            {!collapsed && (
            <div className="flex-1 min-w-0 flex flex-col min-h-0">
                {/* File header — back / title / meta popover / subtitle */}
                <div className={`shrink-0 px-3 pt-2 pb-2 border-b ${T.border}`}>
                    <div className="flex items-center gap-0.5 min-w-0">
                        <div className="flex-1 min-w-0 flex items-center gap-1">
                            {headerLeft}
                        </div>
                        {metaSlot && (
                            <button
                                type="button"
                                title="Template settings"
                                aria-expanded={metaOpen}
                                onClick={() => {
                                    // The settings live in the File view, so opening them
                                    // from Elements/Shortcuts has to switch back or the
                                    // click would appear to do nothing.
                                    if (!metaOpen) setView('file');
                                    setMetaOpen((v) => !v);
                                }}
                                className={`h-6 w-5 shrink-0 flex items-center justify-center rounded-[4px] ${T.hoverBg}
                                    ${metaOpen ? T.text : T.textSoft}`}
                            >
                                <IconChevronDown
                                    size={12}
                                    className={`transition-transform ${metaOpen ? 'rotate-180' : ''}`}
                                />
                            </button>
                        )}
                    </div>
                    {(subtitle || (dirty && !autosaveActive)) && (
                        <div className={`pl-8 pr-1 mt-0.5 flex items-center gap-1.5 text-[11px] ${T.textSoft}`}>
                            <span className="truncate">{subtitle}</span>
                            {/* Autosave handles persistence — an "Unsaved" warning would
                                just flash during the debounce and alarm for no reason. */}
                            {dirty && !autosaveActive && (
                                <span className="flex items-center gap-1 shrink-0 text-[#e68a00]">
                                    <span className="h-1 w-1 rounded-full bg-[#e68a00]" />
                                    Unsaved
                                </span>
                            )}
                        </div>
                    )}
                </div>

                {/* Template settings — a section of the panel, above the layers, not a
                    popover: it is edited alongside the design rather than on top of it.
                    Capped and scrollable so a long form can never squeeze out Layers. */}
                {view === 'file' && metaSlot && metaOpen && (
                    <div className={`shrink-0 border-b ${T.border}`}>
                        <div className="h-9 flex items-center justify-between pl-4 pr-2">
                            <span className={`text-[11px] font-semibold ${T.text}`}>Template settings</span>
                            <button
                                type="button"
                                title="Hide template settings"
                                onClick={() => setMetaOpen(false)}
                                className={`h-6 w-6 flex items-center justify-center rounded-[5px] ${T.hoverBg} ${T.textSoft}`}
                            >
                                <IconChevronUp size={13} />
                            </button>
                        </div>
                        <div className="px-4 pb-3 max-h-[45vh] overflow-y-auto fig-scroll">
                            {metaSlot}
                        </div>
                    </div>
                )}

                {view === 'file' ? (
                    <>
                        {/* Layers header */}
                        <div className="shrink-0 h-9 flex items-center justify-between pl-4 pr-2">
                            <span className={`text-[11px] font-semibold ${T.text}`}>Layers</span>
                            {selectedIds.length > 0 && (
                                <div className="flex items-center gap-0.5">
                                    {/* Structure cluster — bundle / unbundle (no new elements) */}
                                    {selectedIds.length >= 2 && (
                                        <button
                                            type="button"
                                            title="Group — bundle into one group (⌘G)"
                                            onClick={groupSelected}
                                            className={`h-6 w-6 flex items-center justify-center rounded-[5px] ${T.hoverBg} ${T.textSoft} hover:!text-[#8638e5] dark:hover:!text-[#c79bff]`}
                                        >
                                            <IconBoxMultiple size={13} />
                                        </button>
                                    )}
                                    {selectionHasGroup && (
                                        <button
                                            type="button"
                                            title="Ungroup — split back into loose items (⌘⇧G)"
                                            onClick={ungroupSelected}
                                            className={`h-6 w-6 flex items-center justify-center rounded-[5px] ${T.hoverBg} ${T.textSoft} hover:!text-[#8638e5] dark:hover:!text-[#c79bff]`}
                                        >
                                            <IconBoxMultipleFilled size={13} />
                                        </button>
                                    )}

                                    {/* Divider — separates structure actions from element actions */}
                                    {(selectedIds.length >= 2 || selectionHasGroup) && (
                                        <span className="mx-1 h-4 w-px bg-[#e6e6e6] dark:bg-[#444444]" aria-hidden="true" />
                                    )}

                                    {/* Element cluster — create a copy / remove */}
                                    <button
                                        type="button"
                                        title="Duplicate — make a copy (⌘D, or ⌥/Alt-drag it on the canvas)"
                                        onClick={duplicateSelected}
                                        className={`h-6 w-6 flex items-center justify-center rounded-[5px] ${T.hoverBg} ${T.textSoft} hover:!text-black dark:hover:!text-white`}
                                    >
                                        <IconCopyPlus size={13} />
                                    </button>
                                    <button
                                        type="button"
                                        title="Delete (⌫)"
                                        onClick={deleteSelected}
                                        className={`h-6 w-6 flex items-center justify-center rounded-[5px] ${T.hoverBg} ${T.textSoft} hover:!text-[#e53e3e] dark:hover:!text-[#ff6b6b]`}
                                    >
                                        <IconTrash size={13} />
                                    </button>
                                </div>
                            )}
                        </div>
                        <div className="flex-1 min-h-0 overflow-y-auto fig-scroll">
                            <LayersList />
                        </div>
                    </>
                ) : view === 'elements' ? (
                    <>
                        <div className="shrink-0 h-9 flex items-center pl-4 pr-2">
                            <span className={`text-[11px] font-semibold ${T.text}`}>Elements</span>
                        </div>
                        <div className="flex-1 min-h-0 overflow-y-auto fig-scroll">
                            <ElementsGrid />
                        </div>
                    </>
                ) : (
                    <>
                        <div className="shrink-0 h-9 flex items-center pl-4 pr-2">
                            <span className={`text-[11px] font-semibold ${T.text}`}>Shortcuts</span>
                        </div>
                        <div className="flex-1 min-h-0 overflow-y-auto fig-scroll">
                            <ShortcutsPanel />
                        </div>
                    </>
                )}
            </div>
            )}
        </div>
    );
}
