// ==========================================
// Chat Surface — SidebarItems Component
// ==========================================
// Unified channel list with folder grouping, context menus,
// nested folders, and HTML5 drag-and-drop.

const html = window.html;
const { useState, useCallback, useRef, useEffect } = window.hooks;

// ── Icons ────────────────────────────────

const CHAT_SVG = html`
    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
    </svg>`;

const HASH_SVG = html`
    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <line x1="4" y1="9" x2="20" y2="9"/>
        <line x1="4" y1="15" x2="20" y2="15"/>
        <line x1="10" y1="3" x2="8" y2="21"/>
        <line x1="16" y1="3" x2="14" y2="21"/>
    </svg>`;

const FOLDER_SVG = html`
    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
    </svg>`;

const DOTS_SVG = html`
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/>
    </svg>`;

const CHEVRON_SVG = html`
    <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
        <polyline points="9 18 15 12 9 6"/>
    </svg>`;

function _iconForType(type) {
    if (type === 'channel' || type === 'group') return HASH_SVG;
    return CHAT_SVG;
}

// Max nesting depth for folders
const MAX_DEPTH = 3;

// ── Main Component ───────────────────────

export function SidebarItems({
    itemsByFolder, folders, folderTree, activeId, onSelect,
    onRename, onDelete, onMoveToFolder, onMoveFolderTo, onCreateFolder,
    onRenameFolder, onDeleteFolder,
}) {
    const [contextMenu, setContextMenu] = useState(null);
    const [dragOver, setDragOver] = useState(null);     // { id, type } of drop target
    const [dragging, setDragging] = useState(false);    // true while any drag in progress
    const [collapsedFolders, setCollapsedFolders] = useState({});
    const menuRef = useRef(null);

    // ── Context menu close ──────────────
    useEffect(() => {
        if (!contextMenu) return;
        function _close(e) {
            if (e.type === 'keydown' && e.key !== 'Escape') return;
            if (e.type === 'click' && menuRef.current?.contains(e.target)) return;
            setContextMenu(null);
        }
        document.addEventListener('click', _close);
        document.addEventListener('keydown', _close);
        return () => {
            document.removeEventListener('click', _close);
            document.removeEventListener('keydown', _close);
        };
    }, [contextMenu]);

    const _openMenu = useCallback((e, type, item) => {
        e.preventDefault();
        e.stopPropagation();
        const scale = _getScale();
        // The dots button may be display:none (zero rect) — fall back to parent
        let rect = e.currentTarget.getBoundingClientRect();
        if (!rect.width && !rect.height) {
            const parent = e.currentTarget.closest('.sw-chat-surface__item, .sw-chat-surface__folder-header');
            if (parent) rect = parent.getBoundingClientRect();
        }
        const x = rect.right / scale;
        const y = rect.bottom / scale;
        setContextMenu({ type, item, x, y });
    }, []);

    const _bodyContextMenu = useCallback((e) => {
        if (e.target.closest('.sw-chat-surface__item') || e.target.closest('.sw-chat-surface__folder-header')) return;
        e.preventDefault();
        const scale = _getScale();
        setContextMenu({ type: 'body', item: null, x: e.clientX / scale, y: e.clientY / scale });
    }, []);

    const _action = useCallback(async (action, item) => {
        setContextMenu(null);
        if (action === 'rename') {
            const newTitle = await window.sw.prompt('Rename:', item.title || item.name || '');
            if (newTitle && newTitle.trim()) {
                if (item.name !== undefined) await onRenameFolder(item.id, newTitle.trim());
                else await onRename(item.id, newTitle.trim());
            }
        } else if (action === 'delete') {
            const label = item.name !== undefined ? 'folder' : 'conversation';
            const ok = await window.sw.confirm('Delete this ' + label + '?', true);
            if (ok) {
                if (item.name !== undefined) await onDeleteFolder(item.id);
                else await onDelete(item.id);
            }
        } else if (action === 'move-out') {
            await onMoveToFolder(item.id, null);
        } else if (action === 'new-folder') {
            const name = await window.sw.prompt('Folder name:', '');
            if (name && name.trim()) await onCreateFolder(name.trim());
        } else if (action === 'new-subfolder') {
            const name = await window.sw.prompt('Subfolder name:', '');
            if (name && name.trim()) await onCreateFolder(name.trim(), item.id);
        } else if (action === 'unnest-folder') {
            await onMoveFolderTo(item.id, null);
        } else if (action.startsWith('move-to:')) {
            const fid = action.slice(8);
            await onMoveToFolder(item.id, fid);
        }
    }, [onRename, onDelete, onMoveToFolder, onMoveFolderTo, onCreateFolder, onRenameFolder, onDeleteFolder]);

    // ── Folder collapse toggle ──────────
    const _toggleFolder = useCallback((folderId) => {
        setCollapsedFolders(prev => ({ ...prev, [folderId]: !prev[folderId] }));
    }, []);

    // ── Drag & Drop ─────────────────────
    const _onDragStart = useCallback((e, dragType, item) => {
        e.dataTransfer.effectAllowed = 'move';
        e.dataTransfer.setData('text/plain', JSON.stringify({ dragType, id: item.id }));
        setDragging(true);
    }, []);

    const _onDragOver = useCallback((e, targetId, targetType) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';
        setDragOver({ id: targetId, type: targetType });
    }, []);

    const _onDragLeave = useCallback(() => {
        setDragOver(null);
    }, []);

    const _onDropOnFolder = useCallback((e, folderId) => {
        e.preventDefault();
        setDragOver(null);
        try {
            const data = JSON.parse(e.dataTransfer.getData('text/plain'));
            if (data.dragType === 'channel') {
                onMoveToFolder(data.id, folderId);
            } else if (data.dragType === 'folder' && data.id !== folderId) {
                onMoveFolderTo(data.id, folderId);
            }
        } catch (_) {}
    }, [onMoveToFolder, onMoveFolderTo]);

    const _onDropOnRoot = useCallback((e) => {
        e.preventDefault();
        setDragOver(null);
        setDragging(false);
        try {
            const data = JSON.parse(e.dataTransfer.getData('text/plain'));
            if (data.dragType === 'channel') {
                onMoveToFolder(data.id, null);
            } else if (data.dragType === 'folder') {
                onMoveFolderTo(data.id, null);
            }
        } catch (_) {}
    }, [onMoveToFolder, onMoveFolderTo]);

    const _onDragEnd = useCallback(() => {
        setDragging(false);
        setDragOver(null);
    }, []);

    // ── Render ───────────────────────────
    const unfolderedItems = itemsByFolder[''] || [];
    const totalItems = Object.values(itemsByFolder).reduce((sum, arr) => sum + arr.length, 0);
    const tree = folderTree || [];

    const rootDropActive = dragging && dragOver?.id === '__root' && dragOver?.type === 'root';

    return html`
        <div class="sw-chat-surface__section-body"
             role="listbox"
             onContextMenu=${_bodyContextMenu}
             onDragOver=${(e) => { e.preventDefault(); }}
             onDrop=${_onDropOnRoot}
             onDragEnd=${_onDragEnd}>
            ${/* Render folder tree recursively */''}
            ${tree.map(node => html`
                <${FolderNode}
                    key=${'f-' + node.id}
                    node=${node}
                    depth=${0}
                    itemsByFolder=${itemsByFolder}
                    activeId=${activeId}
                    collapsedFolders=${collapsedFolders}
                    dragOver=${dragOver}
                    onSelect=${onSelect}
                    onOpenMenu=${_openMenu}
                    onToggleFolder=${_toggleFolder}
                    onDragStart=${_onDragStart}
                    onDragOver=${_onDragOver}
                    onDragLeave=${_onDragLeave}
                    onDropOnFolder=${_onDropOnFolder} />`)}
            ${/* Unfoldered items */''}
            ${unfolderedItems.map(ch => html`
                <${ChannelItem} key=${ch.id} channel=${ch} activeId=${activeId}
                                onSelect=${onSelect} onOpenMenu=${_openMenu}
                                onDragStart=${_onDragStart} />`)}
            ${totalItems === 0 && tree.length === 0 && html`
                <div class="sw-chat-surface__empty">No conversations yet</div>`}
            ${/* Visible root drop zone — shown during drag */''}
            ${dragging && tree.length > 0 && html`
                <div class=${'sw-chat-surface__root-drop' + (rootDropActive ? ' sw-chat-surface__root-drop--active' : '')}
                     onDragOver=${(e) => _onDragOver(e, '__root', 'root')}
                     onDragLeave=${_onDragLeave}
                     onDrop=${_onDropOnRoot}>
                    Drop here to remove from folder
                </div>`}
        </div>

        ${/* Context Menu */''}
        ${contextMenu && html`
            <div class="sw-chat-surface__context-menu" ref=${menuRef}
                 style=${'left:' + contextMenu.x + 'px;top:' + contextMenu.y + 'px;'}>
                ${contextMenu.type === 'chat' && html`
                    <button onClick=${() => _action('rename', contextMenu.item)}>Rename</button>
                    ${folders.length > 0 && folders.map(f => html`
                        <button key=${f.id} onClick=${() => _action('move-to:' + f.id, contextMenu.item)}>
                            Move to ${f.name}
                        </button>`)}
                    ${contextMenu.item.folder_id && html`
                        <button onClick=${() => _action('move-out', contextMenu.item)}>Remove from folder</button>`}
                    <button class="sw-chat-surface__ctx-danger"
                            onClick=${() => _action('delete', contextMenu.item)}>Delete</button>
                `}
                ${contextMenu.type === 'folder' && html`
                    <button onClick=${() => _action('rename', contextMenu.item)}>Rename</button>
                    <button onClick=${() => _action('new-subfolder', contextMenu.item)}>New subfolder</button>
                    ${contextMenu.item.parent_id && html`
                        <button onClick=${() => _action('unnest-folder', contextMenu.item)}>Move to root</button>`}
                    <button class="sw-chat-surface__ctx-danger"
                            onClick=${() => _action('delete', contextMenu.item)}>Delete</button>
                `}
                ${contextMenu.type === 'body' && html`
                    <button onClick=${() => _action('new-folder', null)}>New Folder</button>
                `}
            </div>`}
    `;
}

// ── FolderNode (recursive) ───────────────

function FolderNode({
    node, depth, itemsByFolder, activeId, collapsedFolders, dragOver,
    onSelect, onOpenMenu, onToggleFolder,
    onDragStart, onDragOver, onDragLeave, onDropOnFolder,
}) {
    const folderItems = itemsByFolder[node.id] || [];
    const totalCount = folderItems.length + (node.children || []).length;
    const isCollapsed = !!collapsedFolders[node.id];
    const isDragTarget = dragOver?.id === node.id && dragOver?.type === 'folder';
    const hasChildren = (node.children?.length > 0) || folderItems.length > 0;
    const indent = depth * 12;

    return html`
        <div key=${'f-' + node.id}
             class=${'sw-chat-surface__folder' + (isDragTarget ? ' sw-chat-surface__folder--drag-over' : '')}
             style=${indent ? 'padding-left:' + indent + 'px' : ''}
             draggable=${depth < MAX_DEPTH}
             onDragStart=${(e) => { e.stopPropagation(); onDragStart(e, 'folder', node); }}
             onDragOver=${(e) => { if (depth < MAX_DEPTH - 1) onDragOver(e, node.id, 'folder'); }}
             onDragLeave=${onDragLeave}
             onDrop=${(e) => { e.stopPropagation(); onDropOnFolder(e, node.id); }}>
            <div class="sw-chat-surface__folder-header"
                 onClick=${() => onToggleFolder(node.id)}>
                <span class=${'sw-chat-surface__chevron' + (isCollapsed ? '' : ' sw-chat-surface__chevron--open')}>
                    ${CHEVRON_SVG}
                </span>
                <span class="sw-chat-surface__item-icon">${FOLDER_SVG}</span>
                <span class="sw-chat-surface__folder-name">${node.name}</span>
                <span class="sw-chat-surface__folder-count">${totalCount}</span>
                <button class="sw-chat-surface__item-menu"
                        onClick=${(e) => { e.stopPropagation(); onOpenMenu(e, 'folder', node); }}
                        title="Folder actions"
                        aria-label="Folder actions">
                    ${DOTS_SVG}
                </button>
            </div>
            ${!isCollapsed && html`
                ${/* Child folders */''}
                ${(node.children || []).map(child => html`
                    <${FolderNode}
                        key=${'f-' + child.id}
                        node=${child}
                        depth=${depth + 1}
                        itemsByFolder=${itemsByFolder}
                        activeId=${activeId}
                        collapsedFolders=${collapsedFolders}
                        dragOver=${dragOver}
                        onSelect=${onSelect}
                        onOpenMenu=${onOpenMenu}
                        onToggleFolder=${onToggleFolder}
                        onDragStart=${onDragStart}
                        onDragOver=${onDragOver}
                        onDragLeave=${onDragLeave}
                        onDropOnFolder=${onDropOnFolder} />`)}
                ${/* Channel items in this folder */''}
                ${folderItems.map(ch => html`
                    <${ChannelItem} key=${ch.id} channel=${ch} activeId=${activeId}
                                    onSelect=${onSelect} onOpenMenu=${onOpenMenu}
                                    onDragStart=${onDragStart}
                                    indent=${true} />`)}
            `}
        </div>`;
}

// ── ChannelItem ──────────────────────────

function ChannelItem({ channel, activeId, onSelect, onOpenMenu, onDragStart, indent }) {
    const icon = _iconForType(channel.type);
    return html`
        <button class=${'sw-chat-surface__item' + (channel.id === activeId ? ' sw-chat-surface__item--active' : '') + (indent ? ' sw-chat-surface__item--indent' : '')}
                onClick=${() => onSelect(channel.id, channel.type)}
                onContextMenu=${(e) => { e.preventDefault(); onOpenMenu(e, 'chat', channel); }}
                draggable=${true}
                onDragStart=${(e) => onDragStart(e, 'channel', channel)}
                role="option"
                aria-selected=${channel.id === activeId}
                title=${channel.title || 'Untitled'}>
            <span class="sw-chat-surface__item-icon">${icon}</span>
            <span class="sw-chat-surface__item-title">${channel.title || 'Untitled'}</span>
            ${(channel.unread_count || 0) > 0 && html`
                <span class="sw-chat-surface__unread">${channel.unread_count}</span>`}
            <button class="sw-chat-surface__item-menu"
                    onClick=${(e) => { e.stopPropagation(); onOpenMenu(e, 'chat', channel); }}
                    title="Actions"
                    aria-label="Actions">
                ${DOTS_SVG}
            </button>
        </button>`;
}

// Read the CSS scale transform on .surface-inner (set by appearance zoom).
// Context menus use position:fixed which breaks under transforms,
// so we divide getBoundingClientRect values by scale to compensate.
function _getScale() {
    const el = document.getElementById('surfaceInner');
    if (!el) return 1;
    const t = getComputedStyle(el).transform;
    if (!t || t === 'none') return 1;
    const m = t.match(/matrix\(([^,]+)/);
    return m ? parseFloat(m[1]) || 1 : 1;
}

// Folder count = direct children only (subfolders + channels in this folder).
