/**
 * ProjectDetail — two-column detail view with inline chat + metadata sidebar.
 *
 * Props:
 *   project   — project object
 *   onBack    — () => void  (return to list)
 *   onUpdate  — (deleted?: boolean) => void
 *
 * Left panel toggles: conversation list ↔ embedded ChatPane.
 * Right sidebar: collapsible sections (Description, Instructions, KBs, Notes, Files).
 */
const html = window.html;
const h = window.preact.h;
const { useState, useEffect, useCallback, useRef } = window.hooks;

import { ChatPane } from '../../components/chat-pane/index.js';
import { UserMenu } from '../../shell/user-menu.js';

const COLORS = ['#4f8cff','#34d399','#f59e0b','#ef4444','#a78bfa','#ec4899','#06b6d4','#8b5cf6'];

function fmtDate(d) {
    if (!d) return '\u2014';
    return new Date(d).toLocaleString(undefined, { dateStyle: 'short', timeStyle: 'short' });
}
function formatBytes(b) {
    if (!b) return '0 B';
    if (b < 1024) return b + ' B';
    if (b < 1048576) return (b / 1024).toFixed(1) + ' KB';
    return (b / 1048576).toFixed(1) + ' MB';
}
function relTime(dateStr) {
    if (!dateStr) return '';
    const DIVS = [[60,'second'],[60,'minute'],[24,'hour'],[30,'day'],[12,'month'],[Infinity,'year']];
    let val = Math.floor((Date.now() - new Date(dateStr).getTime()) / 1000);
    if (val < 10) return 'just now';
    for (const [div, unit] of DIVS) {
        if (val < div) { const n = Math.floor(val); return `${n} ${unit}${n!==1?'s':''} ago`; }
        val /= div;
    }
    return '';
}

export function ProjectDetail({ project, onBack, onUpdate }) {
    const BASE = window.__BASE__ || '';
    const chatRef = useRef(null);

    // ── State ──
    const [activeChannelId, setActiveChannelId] = useState(null);
    const [assoc, setAssoc] = useState({ channels: [], kbs: [], notes: [], files: [] });
    const [editingName, setEditingName] = useState(false);
    const [nameVal, setNameVal] = useState(project.name || '');
    const [menuOpen, setMenuOpen] = useState(false);
    const [sections, setSections] = useState({ desc: true, instructions: false, kbs: false, notes: false, files: false });
    const [desc, setDesc] = useState(project.description || '');
    const [instructions, setInstructions] = useState(project.settings?.instructions || '');
    const [descDirty, setDescDirty] = useState(false);
    const [instrDirty, setInstrDirty] = useState(false);
    const [starred, setStarred] = useState(!!project.settings?.starred);

    // Picker state
    const [pickerOpen, setPickerOpen] = useState('');
    const [pickerItems, setPickerItems] = useState([]);
    const [pickerLoading, setPickerLoading] = useState(false);

    // Drag state for files
    const [dragActive, setDragActive] = useState(false);

    // ── Load associations ──
    const loadAssoc = useCallback(async () => {
        const id = project.id;
        const [ch, kb, nt, fi] = await Promise.all([
            sw.api.projects.channels(id).then(r => r?.data || r || []).catch(() => []),
            sw.api.projects.kbs(id).then(r => r?.data || r || []).catch(() => []),
            sw.api.projects.notes(id).then(r => r?.data || r || []).catch(() => []),
            sw.api.projects.files(id).then(r => r?.data || r?.files || r || []).catch(() => []),
        ]);
        setAssoc({ channels: ch, kbs: kb, notes: nt, files: fi });
    }, [project.id]);

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

    // ── Toggle section ──
    function toggleSection(key) {
        setSections(prev => ({ ...prev, [key]: !prev[key] }));
    }

    // ── Name editing ──
    async function saveName() {
        const name = nameVal.trim();
        if (!name || name === project.name) { setEditingName(false); return; }
        try {
            await sw.api.projects.update(project.id, { name });
            sw.toast('Renamed', 'success');
            setEditingName(false);
            onUpdate();
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    // ── Description / Instructions save ──
    async function saveDesc() {
        try {
            await sw.api.projects.update(project.id, { description: desc });
            sw.toast('Description saved', 'success');
            setDescDirty(false);
            onUpdate();
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    async function saveInstructions() {
        try {
            const settings = { ...(project.settings || {}), instructions };
            await sw.api.projects.update(project.id, { settings });
            sw.toast('Instructions saved', 'success');
            setInstrDirty(false);
            onUpdate();
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    // ── Star toggle ──
    async function toggleStar() {
        const next = !starred;
        setStarred(next);
        try {
            const settings = { ...(project.settings || {}), starred: next };
            await sw.api.projects.update(project.id, { settings });
        } catch (e) { sw.toast(e.message, 'error'); setStarred(!next); }
    }

    // ── Context menu actions ──
    async function handleColor(c) {
        try {
            await sw.api.projects.update(project.id, { color: c });
            sw.toast('Color updated', 'success');
            setMenuOpen(false);
            onUpdate();
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    async function toggleArchive() {
        try {
            await sw.api.projects.update(project.id, { is_archived: !project.is_archived });
            sw.toast(project.is_archived ? 'Unarchived' : 'Archived', 'success');
            setMenuOpen(false);
            onUpdate();
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    async function deleteProject() {
        setMenuOpen(false);
        if (!await sw.confirm('Delete this project? This cannot be undone.', true)) return;
        try {
            await sw.api.projects.del(project.id);
            sw.toast('Project deleted', 'success');
            onUpdate(true);
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    // ── Picker helpers ──
    async function openPicker(type) {
        if (pickerOpen === type) { setPickerOpen(''); return; }
        setPickerOpen(type);
        setSections(prev => ({ ...prev, [type]: true }));
        setPickerLoading(true);
        setPickerItems([]);
        try {
            let items = [];
            if (type === 'kbs') {
                const r = await sw.api.knowledge.list();
                const all = r?.data || r || [];
                const attached = new Set(assoc.kbs.map(k => k.id || k.kb_id));
                items = all.filter(k => !attached.has(k.id));
            } else if (type === 'notes') {
                const r = await sw.api.notes.list();
                const all = r?.data || r || [];
                const attached = new Set(assoc.notes.map(n => n.id || n.note_id));
                items = all.filter(n => !attached.has(n.id));
            }
            setPickerItems(items);
        } catch (e) { sw.toast(e.message, 'error'); }
        setPickerLoading(false);
    }

    async function pickItem(type, item) {
        try {
            if (type === 'kbs') await sw.api.projects.addKb(project.id, item.id, false);
            else if (type === 'notes') await sw.api.projects.addNote(project.id, item.id);
            sw.toast('Added', 'success');
            setPickerOpen('');
            loadAssoc();
            onUpdate();
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    // ── Remove handlers ──
    async function removeKb(kbId) {
        try { await sw.api.projects.removeKb(project.id, kbId); sw.toast('Removed', 'success'); loadAssoc(); onUpdate(); }
        catch (e) { sw.toast(e.message, 'error'); }
    }
    async function removeNote(noteId) {
        try { await sw.api.projects.removeNote(project.id, noteId); sw.toast('Removed', 'success'); loadAssoc(); onUpdate(); }
        catch (e) { sw.toast(e.message, 'error'); }
    }
    async function removeChannel(chId) {
        try { await sw.api.projects.removeChannel(project.id, chId); sw.toast('Removed', 'success'); loadAssoc(); onUpdate(); }
        catch (e) { sw.toast(e.message, 'error'); }
    }

    // ── File upload ──
    async function uploadFiles(files) {
        for (const file of files) {
            try {
                await sw.api.projects.uploadFile(project.id, file);
                sw.toast(`Uploaded ${file.name}`, 'success');
            } catch (e) { sw.toast(e.message, 'error'); }
        }
        loadAssoc();
    }

    function handleUploadClick() {
        const input = document.createElement('input');
        input.type = 'file';
        input.multiple = true;
        input.onchange = () => { if (input.files.length) uploadFiles(input.files); };
        input.click();
    }

    function handleDrop(e) {
        e.preventDefault();
        setDragActive(false);
        if (e.dataTransfer.files.length) uploadFiles(e.dataTransfer.files);
    }

    // ── New conversation ──
    async function newConversation() {
        try {
            const ch = await sw.api.channels.create({ type: 'direct', title: 'New Chat' });
            const chId = ch?.id || ch?.data?.id;
            if (chId) {
                await sw.api.projects.addChannel(project.id, chId);
                await loadAssoc();
                setActiveChannelId(chId);
            }
        } catch (e) { sw.toast(e.message, 'error'); }
    }

    // ── Render: Picker dropdown ──
    function renderPicker(type, emptyHint) {
        if (pickerOpen !== type) return null;
        return html`<div class="sw-projects__picker">
            ${pickerLoading && html`<div class="sw-projects__picker-hint">Loading\u2026</div>`}
            ${!pickerLoading && pickerItems.length === 0 && html`<div class="sw-projects__picker-hint">${emptyHint}</div>`}
            ${!pickerLoading && pickerItems.map(item => html`
                <div key=${item.id} class="sw-projects__picker-item" onClick=${() => pickItem(type, item)}>
                    ${item.title || item.name || item.id}
                </div>
            `)}
        </div>`;
    }

    // ── Render: Collapsible section ──
    function renderSection(key, title, count, content, addAction) {
        const open = sections[key];
        return html`<div class="sw-projects__section">
            <div class="sw-projects__section-header" onClick=${e => { if (e.target.closest('.sw-projects__section-add')) return; toggleSection(key); }}>
                <div>
                    <span class="sw-projects__section-title">${title}</span>
                    ${count != null && html`<span class="sw-projects__section-count">${count}</span>`}
                </div>
                <div class="sw-projects__section-actions">
                    ${addAction && html`<button class="sw-projects__section-add"
                        onClick=${e => { e.stopPropagation(); addAction(); }}>+</button>`}
                    <span class=${'sw-projects__section-chevron' + (open ? ' sw-projects__section-chevron--open' : '')}>\u25B6</span>
                </div>
            </div>
            ${open && html`<div class="sw-projects__section-body">${content}</div>`}
        </div>`;
    }

    // ── Render: Left panel ──
    function renderLeftPanel() {
        if (activeChannelId) {
            return html`<div class="sw-projects__chat-wrap">
                <div class="sw-projects__chat-back" onClick=${() => setActiveChannelId(null)}>
                    \u2190 Back to conversations
                </div>
                <${ChatPane}
                    channelId=${activeChannelId}
                    standalone=${false}
                    handleRef=${chatRef}
                    className="sw-projects__chat-pane" />
            </div>`;
        }

        return html`<div class="sw-projects__conversations">
            <div class="sw-projects__conv-header">
                <span style="font-size:13px;font-weight:600;color:var(--text-2);">Conversations</span>
                <button class="sw-projects__new-btn" style="font-size:12px;padding:5px 12px;" onClick=${newConversation}>+ New</button>
            </div>
            <div class="sw-projects__conv-list">
                ${assoc.channels.length === 0 && html`
                    <div class="sw-projects__conv-empty">
                        No conversations yet.<br/>
                        <button class="sw-projects__new-btn" style="margin-top:12px;font-size:12px;padding:5px 12px;" onClick=${newConversation}>Start a conversation</button>
                    </div>
                `}
                ${assoc.channels.map(ch => {
                    const chId = ch.id || ch.channel_id;
                    return html`<div key=${chId} class="sw-projects__conv-item" onClick=${() => setActiveChannelId(chId)}>
                        <div class="sw-projects__conv-title">${ch.title || ch.name || chId}</div>
                        <div class="sw-projects__conv-meta">Last message ${relTime(ch.updated_at)}</div>
                    </div>`;
                })}
            </div>
        </div>`;
    }

    // ── Render: Right sidebar ──
    function renderSidebar() {
        return html`<div class="sw-projects__sidebar">
            ${renderSection('desc', 'Description', null, html`
                <textarea class="sw-projects__section-textarea" rows="3"
                    value=${desc}
                    onInput=${e => { setDesc(e.target.value); setDescDirty(true); }}
                    placeholder="Add a project description\u2026" />
                ${descDirty && html`<button class="sw-projects__new-btn" style="margin-top:6px;font-size:12px;padding:4px 10px;" onClick=${saveDesc}>Save</button>`}
            `)}

            ${renderSection('instructions', 'Instructions', null, html`
                <textarea class="sw-projects__section-textarea" rows="4"
                    value=${instructions}
                    onInput=${e => { setInstructions(e.target.value); setInstrDirty(true); }}
                    placeholder="Add instructions to tailor responses\u2026" />
                ${instrDirty && html`<button class="sw-projects__new-btn" style="margin-top:6px;font-size:12px;padding:4px 10px;" onClick=${saveInstructions}>Save</button>`}
            `)}

            ${renderSection('kbs', 'Knowledge Bases', assoc.kbs.length, html`
                ${assoc.kbs.length === 0 && html`<div class="sw-projects__section-hint">No knowledge bases linked.</div>`}
                ${assoc.kbs.map(kb => html`
                    <div key=${kb.id || kb.kb_id} class="sw-projects__section-item">
                        <span class="sw-projects__section-item-name">${kb.name || kb.kb_id}</span>
                        <button class="sw-projects__section-item-remove" onClick=${() => removeKb(kb.id || kb.kb_id)}>Remove</button>
                    </div>
                `)}
                ${renderPicker('kbs', 'No knowledge bases available.')}
            `, () => openPicker('kbs'))}

            ${renderSection('notes', 'Notes', assoc.notes.length, html`
                ${assoc.notes.length === 0 && html`<div class="sw-projects__section-hint">No notes linked.</div>`}
                ${assoc.notes.map(n => html`
                    <div key=${n.id || n.note_id} class="sw-projects__section-item">
                        <span class="sw-projects__section-item-name">${n.title || n.note_id}</span>
                        <span class="sw-projects__section-item-meta">${fmtDate(n.created_at || n.added_at)}</span>
                        <button class="sw-projects__section-item-remove" onClick=${() => removeNote(n.id || n.note_id)}>Remove</button>
                    </div>
                `)}
                ${renderPicker('notes', 'No notes available.')}
            `, () => openPicker('notes'))}

            ${renderSection('files', 'Files', assoc.files.length, html`
                ${assoc.files.map(f => html`
                    <div key=${f.id} class="sw-projects__section-item">
                        <span class="sw-projects__section-item-name">${f.filename || f.name}</span>
                        <span class="sw-projects__section-item-meta">${formatBytes(f.size_bytes || f.size)}</span>
                    </div>
                `)}
                <div class=${'sw-projects__dropzone' + (dragActive ? ' sw-projects__dropzone--active' : '')}
                     onClick=${handleUploadClick}
                     onDragOver=${e => { e.preventDefault(); setDragActive(true); }}
                     onDragLeave=${() => setDragActive(false)}
                     onDrop=${handleDrop}>
                    ${dragActive ? 'Drop files here' : 'Add PDFs, documents, or other text to reference in this project.'}
                </div>
            `, handleUploadClick)}
        </div>`;
    }

    // ── Main render ──
    return html`<div class="sw-projects__detail">
        <div class="sw-projects__detail-header">
            <${UserMenu} placement="down-right" />
            <a class="sw-projects__back" onClick=${onBack}>\u2190 All projects</a>
            ${editingName
                ? html`<input class="sw-projects__detail-name-input"
                    value=${nameVal}
                    onInput=${e => setNameVal(e.target.value)}
                    onBlur=${saveName}
                    onKeyDown=${e => { if (e.key === 'Enter') saveName(); if (e.key === 'Escape') setEditingName(false); }}
                    autoFocus />`
                : html`<h2 class="sw-projects__detail-name"
                    onClick=${() => { setNameVal(project.name || ''); setEditingName(true); }}>
                    ${(project.icon ? project.icon + ' ' : '') + project.name}
                  </h2>`
            }
            <div class="sw-projects__header-actions">
                <button class=${'sw-projects__icon-btn' + (starred ? ' sw-projects__icon-btn--active' : '')}
                        onClick=${toggleStar} title="Star project">
                    ${starred ? '\u2605' : '\u2606'}
                </button>
                <div style="position:relative">
                    <button class="sw-projects__icon-btn"
                            onClick=${() => setMenuOpen(!menuOpen)} title="More options">\u22EF</button>
                    ${menuOpen && html`
                        <div class="sw-projects__ctx-menu">
                            <button class="sw-projects__ctx-item"
                                onClick=${() => { setMenuOpen(false); setNameVal(project.name || ''); setEditingName(true); }}>Rename</button>
                            <div class="sw-projects__color-row">
                                ${COLORS.map(c => html`
                                    <span key=${c}
                                          class=${'sw-projects__color-swatch' + (project.color === c ? ' sw-projects__color-swatch--active' : '')}
                                          style=${'background:' + c}
                                          onClick=${() => handleColor(c)} />
                                `)}
                            </div>
                            <div class="sw-projects__ctx-divider" />
                            <button class="sw-projects__ctx-item" onClick=${toggleArchive}>
                                ${project.is_archived ? 'Unarchive' : 'Archive'}</button>
                            <button class="sw-projects__ctx-item sw-projects__ctx-item--danger"
                                onClick=${deleteProject}>Delete</button>
                        </div>
                    `}
                </div>
            </div>
        </div>
        <div class="sw-projects__detail-body">
            ${renderLeftPanel()}
            ${renderSidebar()}
        </div>
    </div>`;
}
