// ==========================================
// Chat Surface — useSidebar Hook
// ==========================================
// Loads and manages sidebar data: all channels (unified)
// and folders. Subscribes to WS events for live updates.

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

const COLLAPSE_KEY = 'sw-chat-sidebar-collapsed';

/**
 * @param {{ activeId: string|null }} opts
 */
export function useSidebar(opts = {}) {
    const { activeId } = opts;

    const [allChannels, setAllChannels] = useState([]);
    const [folders, setFolders] = useState([]);
    const [search, setSearch] = useState('');
    const [collapsed, setCollapsed] = useState(_loadCollapsed);
    const [loading, setLoading] = useState(true);
    const activeIdRef = useRef(activeId);
    activeIdRef.current = activeId;

    // ── Load data ───────────────────────────
    const reload = useCallback(async () => {
        if (!window.sw?.api?.channels?.list) return;

        try {
            const foldersPromise = window.sw.api.folders?.list
                ? window.sw.api.folders.list().catch(() => [])
                : Promise.resolve([]);

            const [allResp, fResp] = await Promise.all([
                window.sw.api.channels.list({ page: 1, per_page: 200, types: 'direct,dm,group,channel' }).catch(() => []),
                foldersPromise,
            ]);

            const fresh = _extract(allResp);
            // Zero unread for the active channel (mark-read already fired)
            const aid = activeIdRef.current;
            if (aid) {
                const idx = fresh.findIndex(c => c.id === aid);
                if (idx !== -1) fresh[idx] = { ...fresh[idx], unread_count: 0 };
            }
            setAllChannels(fresh);
            setFolders(_extract(fResp));
        } catch (_) {}

        setLoading(false);
    }, []);

    useEffect(() => { reload(); }, [reload]);

    // ── Clear unread badge when channel becomes active ──
    useEffect(() => {
        if (!activeId) return;
        setAllChannels(prev => prev.map(c =>
            c.id === activeId && c.unread_count > 0
                ? { ...c, unread_count: 0 }
                : c
        ));
    }, [activeId]);

    // ── WebSocket live updates ──────────────
    useEffect(() => {
        if (!window.sw?.on) return;

        const handlers = {
            'channel.created': reload,
            'channel.updated': reload,
            'channel.deleted': reload,
            'folder.created':  reload,
            'folder.updated':  reload,
            'folder.deleted':  reload,
        };

        Object.entries(handlers).forEach(([ev, fn]) => window.sw.on(ev, fn));
        return () => {
            Object.entries(handlers).forEach(([ev, fn]) => window.sw.off?.(ev, fn));
        };
    }, [reload]);

    // ── Search filter ───────────────────────
    const filtered = useMemo(() => {
        if (!search) return allChannels;
        const q = search.toLowerCase();
        return allChannels.filter(c => (c.title || '').toLowerCase().includes(q));
    }, [allChannels, search]);

    // Group all channels by folder
    const itemsByFolder = useMemo(() => {
        const map = { '': [] };
        for (const f of (folders || [])) map[f.id] = [];
        for (const c of filtered) {
            const fid = c.folder_id || '';
            if (!map[fid]) map[fid] = [];
            map[fid].push(c);
        }
        return map;
    }, [filtered, folders]);

    // Build nested folder tree (max 3 levels)
    const folderTree = useMemo(() => {
        if (!folders || !folders.length) return [];
        const byId = {};
        for (const f of folders) byId[f.id] = { ...f, children: [] };
        const roots = [];
        for (const f of folders) {
            const node = byId[f.id];
            if (f.parent_id && byId[f.parent_id]) {
                byId[f.parent_id].children.push(node);
            } else {
                roots.push(node);
            }
        }
        return roots;
    }, [folders]);

    // ── Collapse folders ────────────────────
    const toggleCollapsed = useCallback((key) => {
        setCollapsed(prev => {
            const next = { ...prev, [key]: !prev[key] };
            try { localStorage.setItem(COLLAPSE_KEY, JSON.stringify(next)); } catch (_) {}
            return next;
        });
    }, []);

    // ── CRUD helpers ────────────────────────
    const createFolder = useCallback(async (name, parentId) => {
        if (!window.sw?.api?.folders?.create) return;
        await window.sw.api.folders.create(name, parentId ? { parent_id: parentId } : undefined);
        reload();
    }, [reload]);

    const moveFolderTo = useCallback(async (folderId, parentId) => {
        if (!window.sw?.api?.folders?.update) return;
        await window.sw.api.folders.update(folderId, { parent_id: parentId || null });
        reload();
    }, [reload]);

    const renameChat = useCallback(async (id, title) => {
        await window.sw.api.channels.update(id, { title });
        reload();
    }, [reload]);

    const deleteChat = useCallback(async (id) => {
        await window.sw.api.channels.del(id);
        reload();
    }, [reload]);

    const moveToFolder = useCallback(async (chatId, folderId) => {
        await window.sw.api.channels.update(chatId, { folder_id: folderId || null });
        reload();
    }, [reload]);

    const renameFolder = useCallback(async (id, name) => {
        await window.sw.api.folders.update(id, { name });
        reload();
    }, [reload]);

    const deleteFolder = useCallback(async (id) => {
        await window.sw.api.folders.del(id);
        reload();
    }, [reload]);

    return {
        items: filtered,
        itemsByFolder,
        folders,
        folderTree,
        search,
        setSearch,
        collapsed,
        toggleCollapsed,
        loading,
        reload,
        // CRUD
        createFolder,
        renameChat,
        deleteChat,
        moveToFolder,
        moveFolderTo,
        renameFolder,
        deleteFolder,
    };
}

function _extract(resp) {
    if (!resp) return [];
    if (Array.isArray(resp)) return resp;
    if (Array.isArray(resp.data)) return resp.data;
    // Handle wrapped responses like { folders: [], channels: [] }
    const vals = Object.values(resp);
    for (const v of vals) {
        if (Array.isArray(v)) return v;
    }
    return [];
}

function _loadCollapsed() {
    try {
        return JSON.parse(localStorage.getItem(COLLAPSE_KEY)) || {};
    } catch (_) { return {}; }
}
