// app.jsx — App shell, context, reducer, Header, StatsBar
const { useState, useReducer, useEffect, useRef, useMemo, createContext, useContext } = React;

const AppCtx = createContext(null);

// ── Reducer ──────────────────────────────────────────────────────────────────

const EMPTY = { workspaces: [], activeWorkspaceId: null, components: [], combos: [] };

function mkComp(id, type, wsId, data = {}) {
  return { id, type, workspaceId: wsId, description: '', script: '', videoLink: '',
    status: 'Testing', angle: '', notes: '', editingStatus: 'Not Started',
    createdAt: new Date().toISOString(), ...data };
}
function mkCombo(id, wsId, data = {}) {
  return { id, workspaceId: wsId, name: data.name || id, hookId: '', leadId: '', bodyId: '',
    status: 'Draft', launchDate: '', postId: '', notes: '',
    createdAt: new Date().toISOString(), ...data };
}

function reducer(state, action) {
  let next = state;
  switch (action.type) {
    case 'INIT': return action.payload;
    case 'ADD_WS': {
      const ws = { id: MBT.uid(), name: action.name, createdAt: new Date().toISOString() };
      next = { ...state, workspaces: [...state.workspaces, ws], activeWorkspaceId: ws.id }; break;
    }
    case 'RENAME_WS':
      next = { ...state, workspaces: state.workspaces.map(w => w.id === action.id ? { ...w, name: action.name } : w) }; break;
    case 'DEL_WS': {
      const wss = state.workspaces.filter(w => w.id !== action.id);
      const aid = state.activeWorkspaceId === action.id ? (wss[0]?.id || null) : state.activeWorkspaceId;
      next = { ...state, workspaces: wss, activeWorkspaceId: aid,
        components: state.components.filter(c => c.workspaceId !== action.id),
        combos: state.combos.filter(c => c.workspaceId !== action.id) }; break;
    }
    case 'SET_WS': next = { ...state, activeWorkspaceId: action.id }; break;
    case 'ADD_COMP': {
      const id = MBT.nextCompId(state, state.activeWorkspaceId, action.compType);
      next = { ...state, components: [...state.components, mkComp(id, action.compType, state.activeWorkspaceId, action.data || {})] }; break;
    }
    case 'UPD_COMP':
      next = { ...state, components: state.components.map(c => c.id === action.id && c.workspaceId === state.activeWorkspaceId ? { ...c, ...action.data } : c) }; break;
    case 'DEL_COMP':
      next = { ...state, components: state.components.filter(c => !(c.id === action.id && c.workspaceId === state.activeWorkspaceId)) }; break;
    case 'ADD_COMBO': {
      const id = MBT.nextComboId(state, state.activeWorkspaceId);
      next = { ...state, combos: [...state.combos, mkCombo(id, state.activeWorkspaceId, action.data || {})] }; break;
    }
    case 'UPD_COMBO':
      next = { ...state, combos: state.combos.map(c => c.id === action.id && c.workspaceId === state.activeWorkspaceId ? { ...c, ...action.data } : c) }; break;
    case 'DEL_COMBO':
      next = { ...state, combos: state.combos.filter(c => !(c.id === action.id && c.workspaceId === state.activeWorkspaceId)) }; break;
    case 'ADD_COMBOS_BULK': {
      let tmp = state;
      const newCombos = [];
      for (const d of action.combos) {
        const id = MBT.nextComboId(tmp, state.activeWorkspaceId);
        const combo = mkCombo(id, state.activeWorkspaceId, d);
        newCombos.push(combo);
        tmp = { ...tmp, combos: [...tmp.combos, combo] };
      }
      next = { ...state, combos: [...state.combos, ...newCombos] }; break;
    }
    default: return state;
  }
  MBT.save(next);
  return next;
}

// ── StatsBar ─────────────────────────────────────────────────────────────────

function StatsBar() {
  const { state } = useContext(AppCtx);
  const wsId = state.activeWorkspaceId;
  const comps = state.components.filter(c => c.workspaceId === wsId && c.status === 'Winner');
  const wH = comps.filter(c => c.type === 'hook').length;
  const wL = comps.filter(c => c.type === 'lead').length;
  const wB = comps.filter(c => c.type === 'body').length;
  const N = wH * (wL + 1) * wB;
  return (
    <div className="stats-bar">
      <span><strong className="stat-val">{wH}</strong> winning hooks</span>
      <span style={{ color: '#2a2a40' }}>×</span>
      <span><strong className="stat-val">{wL + 1}</strong> lead options</span>
      <span style={{ color: '#2a2a40' }}>×</span>
      <span><strong className="stat-val">{wB}</strong> winning bodies</span>
      <span style={{ color: '#2a2a40' }}>=</span>
      <span><strong style={{ color: '#46c97a', fontSize: 13, fontWeight: 600 }}>{N}</strong> possible ad combos</span>
      <span style={{ color: '#2a2a40', fontSize: 10 }}>({wL} winning leads + no-lead option)</span>
    </div>
  );
}

// ── Workspace Dropdown ────────────────────────────────────────────────────────

function WsDropdown({ onClose }) {
  const { state, dispatch } = useContext(AppCtx);
  const [renaming, setRenaming] = useState(null);
  const [renameVal, setRenameVal] = useState('');
  const [adding, setAdding] = useState(false);
  const [newName, setNewName] = useState('');
  const ref = useRef();

  useEffect(() => {
    const h = e => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    setTimeout(() => document.addEventListener('mousedown', h), 0);
    return () => document.removeEventListener('mousedown', h);
  }, [onClose]);

  return (
    <div className="ws-dropdown" ref={ref}>
      {state.workspaces.map(ws => (
        <div key={ws.id} className={`ws-item${ws.id === state.activeWorkspaceId ? ' active' : ''}`}
          onClick={() => { dispatch({ type: 'SET_WS', id: ws.id }); onClose(); }}
        >
          {renaming === ws.id ? (
            <input
              className="fi" value={renameVal} autoFocus
              style={{ padding: '2px 6px', fontSize: 12, height: 26 }}
              onClick={e => e.stopPropagation()}
              onChange={e => setRenameVal(e.target.value)}
              onKeyDown={e => {
                if (e.key === 'Enter' && renameVal.trim()) {
                  dispatch({ type: 'RENAME_WS', id: ws.id, name: renameVal.trim() });
                  setRenaming(null);
                }
                if (e.key === 'Escape') setRenaming(null);
              }}
              onBlur={() => setRenaming(null)}
            />
          ) : (
            <span className="ws-item-name">{ws.name}</span>
          )}
          {ws.id === state.activeWorkspaceId && <span style={{ color: '#46c97a', fontSize: 12 }}>✓</span>}
          <div className="ws-item-actions" onClick={e => e.stopPropagation()}>
            <button className="btn-icon" style={{ fontSize: 11 }} onClick={() => { setRenaming(ws.id); setRenameVal(ws.name); }}>✎</button>
            {state.workspaces.length > 1 && (
              <button className="btn-icon" style={{ fontSize: 11, color: '#d45b5b' }}
                onClick={() => { if (confirm(`Delete workspace "${ws.name}"?`)) dispatch({ type: 'DEL_WS', id: ws.id }); }}>✕</button>
            )}
          </div>
        </div>
      ))}
      <div style={{ borderTop: '1px solid var(--bd)', padding: '8px' }}>
        {adding ? (
          <input
            className="fi" value={newName} autoFocus placeholder="Workspace name…"
            style={{ fontSize: 12 }}
            onChange={e => setNewName(e.target.value)}
            onKeyDown={e => {
              if (e.key === 'Enter' && newName.trim()) {
                dispatch({ type: 'ADD_WS', name: newName.trim() });
                setNewName(''); setAdding(false); onClose();
              }
              if (e.key === 'Escape') { setAdding(false); setNewName(''); }
            }}
            onBlur={() => { if (!newName.trim()) setAdding(false); }}
          />
        ) : (
          <button className="btn btn-ghost btn-sm" style={{ width: '100%', justifyContent: 'center' }}
            onClick={() => setAdding(true)}>+ New Workspace</button>
        )}
      </div>
    </div>
  );
}

// ── Search ────────────────────────────────────────────────────────────────────

function SearchBar({ query, setQuery, onResult }) {
  const { state } = useContext(AppCtx);
  const wsId = state.activeWorkspaceId;
  const [open, setOpen] = useState(false);
  const ref = useRef();

  const results = useMemo(() => {
    if (!query.trim()) return [];
    const q = query.toLowerCase();
    const comps = state.components.filter(c => c.workspaceId === wsId &&
      (c.id.toLowerCase().includes(q) || c.description?.toLowerCase().includes(q) || c.angle?.toLowerCase().includes(q)));
    const combos = state.combos.filter(c => c.workspaceId === wsId &&
      (c.id.toLowerCase().includes(q) || c.name?.toLowerCase().includes(q)));
    return [
      ...comps.slice(0, 6).map(c => ({ kind: 'comp', id: c.id, label: c.description || c.id, type: c.type })),
      ...combos.slice(0, 4).map(c => ({ kind: 'combo', id: c.id, label: c.name || c.id })),
    ];
  }, [query, state.components, state.combos, wsId]);

  useEffect(() => {
    const h = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, []);

  return (
    <div className="search-wrap" ref={ref}>
      <span className="search-icon">⌕</span>
      <input
        className="search-input"
        placeholder="Search…"
        value={query}
        onChange={e => { setQuery(e.target.value); setOpen(true); }}
        onFocus={() => setOpen(true)}
        onKeyDown={e => e.key === 'Escape' && setOpen(false)}
      />
      {open && results.length > 0 && (
        <div className="search-results">
          {results.map((r, i) => (
            <div key={i} className="search-result-item" onClick={() => { onResult(r); setOpen(false); setQuery(''); }}>
              <span className="search-cat">{r.kind === 'comp' ? r.type : 'combo'}</span>
              <window.IdBadge id={r.id} />
              <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: 12 }}>{r.label}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Header ────────────────────────────────────────────────────────────────────

function Header({ view, setView, onMatrix, onImport, onExport, theme, onToggleTheme }) {
  const { state } = useContext(AppCtx);
  const [wsOpen, setWsOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [searchResult, setSearchResult] = useState(null);
  const activeWs = state.workspaces.find(w => w.id === state.activeWorkspaceId);

  const handleResult = r => {
    if (r.kind === 'comp') { setView('components'); setSearchResult(r); }
    else { setView('combos'); setSearchResult(r); }
  };

  return (
    <>
      <div className="app-header">
        {/* Logo mark */}
        <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--accent)', letterSpacing: '-.02em', marginRight: 16, userSelect: 'none' }}>MBT</div>

        {/* Workspace switcher */}
        <div style={{ position: 'relative' }}>
          <button className="ws-btn" onClick={() => setWsOpen(o => !o)}>
            <span>{activeWs?.name || 'No Workspace'}</span>
            <span style={{ color: '#4a4a68', fontSize: 10 }}>▾</span>
          </button>
          {wsOpen && <WsDropdown onClose={() => setWsOpen(false)} />}
        </div>

        <div className="nav-sep" />

        {/* Nav pill toggle */}
        <div className="nav-pill">
          <button className={`nav-pill-opt${view==='components'?' active':''}`} onClick={() => setView('components')}>Components</button>
          <button className={`nav-pill-opt${view==='combos'?' active':''}`} onClick={() => setView('combos')}>Combos</button>
        </div>

        <div className="nav-sep" />

        {/* Launch Test */}
        <button className="btn-launch" onClick={onMatrix}>⚡ Launch Test</button>

        <div className="nav-spacer" />

        <SearchBar query={searchQuery} setQuery={setSearchQuery} onResult={handleResult} />

        <div style={{ display: 'flex', gap: 5, marginLeft: 8, alignItems: 'center' }}>
          <button className="btn btn-ghost btn-sm" onClick={onImport} title="Import CSV">↓ Import</button>
          <button className="btn btn-ghost btn-sm" onClick={onExport} title="Export CSV">↑ Export</button>
          <button className="theme-toggle" onClick={onToggleTheme} title="Toggle light/dark">{theme === 'light' ? '🌙' : '☀️'}</button>
        </div>
      </div>
    </>
  );
}

// ── Setup Screen ──────────────────────────────────────────────────────────────

function SetupScreen({ onDone }) {
  const [name, setName] = useState('');
  return (
    <div className="setup-screen">
      <div className="setup-card">
        <div style={{ fontSize: 28, fontWeight: 700, color: 'var(--accent)', marginBottom: 16, letterSpacing: '-.02em' }}>MBT</div>
        <h1>Media Buying Tracker</h1>
        <p>Name your first workspace — this can be a client, brand, or campaign.</p>
        <input
          className="fi"
          style={{ textAlign: 'center', fontSize: 15, marginBottom: 16 }}
          placeholder="e.g. Acme Corp, Q2 Campaign…"
          value={name}
          onChange={e => setName(e.target.value)}
          autoFocus
          onKeyDown={e => e.key === 'Enter' && name.trim() && onDone(name.trim())}
        />
        <button
          className="btn btn-primary"
          style={{ width: '100%', justifyContent: 'center', padding: '9px 0', fontSize: 14 }}
          disabled={!name.trim()}
          onClick={() => name.trim() && onDone(name.trim())}
        >Create Workspace →</button>
      </div>
    </div>
  );
}

// ── CSV Export ────────────────────────────────────────────────────────────────

function doExport(state) {
  const wsId = state.activeWorkspaceId;
  const ws = state.workspaces.find(w => w.id === wsId);
  const slug = (ws?.name || 'workspace').replace(/[^a-z0-9]/gi, '_').toLowerCase();

  const comps = state.components.filter(c => c.workspaceId === wsId);
  if (comps.length) {
    MBT.exportCSV(comps.map(({ id, type, description, script, videoLink, status, angle, notes, editingStatus, createdAt }) =>
      ({ id, type, description, script, videoLink, status, angle, notes, editingStatus, createdAt })
    ), `${slug}_components.csv`);
  }

  setTimeout(() => {
    const combos = state.combos.filter(c => c.workspaceId === wsId);
    if (combos.length) {
      MBT.exportCSV(combos.map(({ id, name, hookId, leadId, bodyId, status, launchDate, postId, notes, createdAt }) =>
        ({ id, name, hookId, leadId, bodyId, status, launchDate, postId, notes, createdAt })
      ), `${slug}_combos.csv`);
    }
  }, 300);
}

// ── App ───────────────────────────────────────────────────────────────────────

function App() {
  const saved = MBT.load();
  const [state, dispatch] = useReducer(reducer, saved || EMPTY);
  const [view, setView] = useState(() => localStorage.getItem('mbt-view') || 'components');
  const [theme, setTheme] = useState(() => localStorage.getItem('mbt-theme') || 'dark');
  const [showMatrix, setShowMatrix] = useState(false);
  const [showImport, setShowImport] = useState(false);
  const [openCompId, setOpenCompId] = useState(null);

  useEffect(() => { localStorage.setItem('mbt-view', view); }, [view]);
  useEffect(() => {
    localStorage.setItem('mbt-theme', theme);
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
  }, []);

  // Export AppCtx to window for child script files
  window.AppCtx = AppCtx;

  const needsSetup = !state.workspaces.length;
  if (needsSetup) return (
    <AppCtx.Provider value={{ state, dispatch }}>
      <SetupScreen onDone={name => dispatch({ type: 'ADD_WS', name })} />
    </AppCtx.Provider>
  );

  if (!state.activeWorkspaceId && state.workspaces.length) {
    dispatch({ type: 'SET_WS', id: state.workspaces[0].id });
  }

  return (
    <AppCtx.Provider value={{ state, dispatch }}>
      <div className="app-shell">
        <Header
          view={view} setView={setView}
          onMatrix={() => setShowMatrix(true)}
          onImport={() => setShowImport(true)}
          onExport={() => doExport(state)}
          theme={theme}
          onToggleTheme={() => setTheme(t => t === 'dark' ? 'light' : 'dark')}
        />
        <StatsBar />
        <div className="app-body">
          {view === 'components' && (
            <window.ComponentsView
              searchQuery=""
              onOpenComponent={id => setOpenCompId(id)}
            />
          )}
          {view === 'combos' && (
            <window.CombosView
              searchQuery=""
              onOpenComponent={id => setOpenCompId(id)}
            />
          )}
        </div>
      </div>
      {showMatrix && <window.MatrixModal onClose={() => setShowMatrix(false)} />}
      {showImport && <window.CSVImportModal onClose={() => setShowImport(false)} />}
      {openCompId && (
        <window.ComponentDetailModal
          itemId={openCompId}
          onClose={() => setOpenCompId(null)}
          onOpenComponent={id => setOpenCompId(id)}
        />
      )}
    </AppCtx.Provider>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
