/* 業務OS Prototype — Shared UI components */
const { useState, useEffect, useRef, useCallback, Fragment } = React;

/* ── Lucide Icon ── */
function Icon({ name, size = 14, style = {}, className = '' }) {
  const ref = useRef(null);
  useEffect(() => {
    if (!ref.current || !window.lucide) return;
    ref.current.innerHTML = '';
    const el = document.createElement('i');
    el.setAttribute('data-lucide', name);
    ref.current.appendChild(el);
    window.lucide.createIcons({ attrs: { width: size, height: size }, nameAttr: 'data-lucide' });
  }, [name, size]);
  return <span ref={ref} className={className} style={{ display: 'inline-flex', alignItems: 'center', lineHeight: 1, ...style }} />;
}

/* ── Badges ── */
function PriorityBadge({ p }) {
  const c = { P1: { bg:'var(--danger-bg)', c:'var(--danger)', b:'rgba(200,29,29,.2)' }, P2: { bg:'var(--warning-bg)', c:'var(--warning)', b:'rgba(201,138,8,.2)' }, P3: { bg:'var(--bg-3)', c:'var(--text-2)', b:'var(--border-subtle)' } };
  const s = c[p] || c.P3;
  return <span style={{ fontFamily:'var(--font-mono)', fontSize:9, fontWeight:700, letterSpacing:'.04em', padding:'2px 6px', borderRadius:3, background:s.bg, color:s.c, border:'1px solid '+s.b, lineHeight:1.2, whiteSpace:'nowrap' }}>{p}</span>;
}

function ModeBadge({ mode, label }) {
  const m = { ai:{bg:'rgba(46,125,214,.1)',c:'var(--info)',i:'zap'}, approve:{bg:'rgba(173,0,33,.08)',c:'var(--accent)',i:'shield-check'}, collaborate:{bg:'rgba(91,95,199,.1)',c:'var(--stage-s0)',i:'users'}, human:{bg:'var(--bg-3)',c:'var(--text-2)',i:'user'} };
  const s = m[mode] || m.human;
  return <span style={{ display:'inline-flex', alignItems:'center', gap:3, fontSize:9, fontWeight:600, letterSpacing:'.03em', padding:'2px 7px', borderRadius:3, background:s.bg, color:s.c, whiteSpace:'nowrap' }}><Icon name={s.i} size={10} />{label}</span>;
}

function SourceBadge({ source, icon }) {
  return <span style={{ display:'inline-flex', alignItems:'center', gap:3, fontSize:9, color:'var(--text-3)', whiteSpace:'nowrap' }}><Icon name={icon} size={10} />{source}</span>;
}

function CategoryLabel({ cat }) {
  const l = { trigger:'トリガー', routine:'定常', carryover:'持越し', pj:'PJ' };
  const c = { trigger:'var(--warning)', routine:'var(--text-3)', carryover:'var(--info)', pj:'var(--stage-s0)' };
  return <span style={{ fontSize:9, fontWeight:600, color:c[cat]||'var(--text-3)', letterSpacing:'.03em' }}>{l[cat]||cat}</span>;
}

function StatusDot({ status, size = 7 }) {
  const c = { connected:'var(--success)', warning:'var(--warning)', error:'var(--danger)', offline:'var(--text-4)' };
  return <span style={{ display:'inline-block', width:size, height:size, borderRadius:'50%', background:c[status]||c.offline, flexShrink:0 }} />;
}

function StatusBadge({ status }) {
  const map = {
    '待機': { bg:'var(--warning-bg)', c:'var(--warning)' },
    '進行中': { bg:'rgba(46,125,214,.1)', c:'var(--info)' },
    '実行中': { bg:'rgba(46,125,214,.1)', c:'var(--info)' },
    '完了': { bg:'var(--success-bg)', c:'var(--success)' },
  };
  const s = map[status] || { bg:'var(--bg-3)', c:'var(--text-3)' };
  return <span style={{ fontSize:9, fontWeight:600, padding:'2px 7px', borderRadius:3, background:s.bg, color:s.c }}>{status}</span>;
}

/* ── Section header ── */
function SectionHead({ title, titleEn, count, children }) {
  return (
    <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
      <div style={{ fontSize:10, fontWeight:600, letterSpacing:'.08em', textTransform:'uppercase', color:'var(--text-2)', display:'flex', alignItems:'center', gap:8 }}>
        <span style={{ width:3, height:12, background:'var(--accent)', borderRadius:2, flexShrink:0 }} />
        {title}
        {titleEn && <span style={{ textTransform:'none', fontWeight:500, letterSpacing:'.02em' }}>/ {titleEn}</span>}
      </div>
      {count != null && <span style={{ fontFamily:'var(--font-mono)', fontSize:10, color:'var(--text-3)' }}>{count}</span>}
      <div style={{ flex:1 }} />
      {children}
    </div>
  );
}

/* ── Task card ── */
function TaskCard({ task, compact, selected, onClick }) {
  const [h, setH] = useState(false);
  return (
    <div onClick={onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        background: selected ? 'var(--accent-soft)' : h ? 'var(--surface-hover)' : 'var(--surface)',
        border: '1px solid '+(selected?'var(--accent)':h?'var(--border)':'var(--border-subtle)'),
        boxShadow: selected?'var(--glow-accent)':'none',
        borderRadius:6, padding: compact?'8px 10px':'10px 12px', cursor:'pointer', transition:'all .12s',
        borderLeft: task.urgent?'3px solid var(--danger)':undefined,
      }}>
      <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:4 }}>
        <PriorityBadge p={task.p} />
        <span style={{ fontSize:12, fontWeight:600, color:'var(--text-0)', flex:1, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{task.title}</span>
        <ModeBadge mode={task.mode} label={task.modeL} />
      </div>
      <div style={{ fontSize:10, color:'var(--text-2)', marginBottom: compact?4:6, lineHeight:1.4 }}>{task.sub}</div>
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <CategoryLabel cat={task.cat} />
        <SourceBadge source={task.src} icon={task.srcI} />
        <span style={{ marginLeft:'auto', fontFamily:'var(--font-mono)', fontSize:9, color:task.urgent?'var(--danger)':'var(--text-3)' }}>{task.due}</span>
      </div>
      {!compact && task.aiSt && (
        <div style={{ marginTop:6, padding:'5px 8px', background:'var(--bg-3)', borderRadius:4, fontSize:10, color:'var(--text-2)', display:'flex', alignItems:'center', gap:4 }}>
          <Icon name="zap" size={10} style={{ color:'var(--info)' }} />{task.aiSt}
        </div>
      )}
    </div>
  );
}

/* ── File tree ── */
function FileTreeNode({ node, depth = 0 }) {
  const [open, setOpen] = useState(depth < 3);
  const isDir = !!node.children;
  return (
    <div>
      <div onClick={() => isDir && setOpen(!open)}
        style={{ display:'flex', alignItems:'center', gap:4, padding:'2px 6px 2px '+(8+depth*12)+'px', fontSize:11, color:'var(--text-1)', cursor:isDir?'pointer':'default', borderRadius:3, transition:'background .1s' }}
        onMouseEnter={e => e.currentTarget.style.background='var(--bg-hover)'}
        onMouseLeave={e => e.currentTarget.style.background='transparent'}>
        {isDir ? <Icon name={open?'chevron-down':'chevron-right'} size={10} style={{ color:'var(--text-3)' }} /> : <span style={{ width:10 }} />}
        <Icon name={isDir?(open?'folder-open':'folder'):(node.icon||'file')} size={13} style={{ color:isDir?'var(--warning)':'var(--text-3)', flexShrink:0 }} />
        <span style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{node.name}</span>
      </div>
      {isDir && open && node.children.map((c, i) => <FileTreeNode key={i} node={c} depth={depth + 1} />)}
    </div>
  );
}

function FileTree({ data, style = {} }) {
  return <div style={{ overflowY:'auto', padding:'6px 0', ...style }}>{data.children.map((c,i) => <FileTreeNode key={i} node={c} depth={0} />)}</div>;
}

/* ── Integration list ── */
function IntegrationList({ items }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:2 }}>
      {items.map((itg, i) => (
        <div key={i} style={{ display:'flex', alignItems:'center', gap:6, padding:'3px 8px', fontSize:10, color:'var(--text-2)', borderRadius:3 }}>
          <StatusDot status={itg.status} size={6} />
          <Icon name={itg.icon} size={12} />
          <span style={{ fontWeight:500 }}>{itg.name}</span>
          <span style={{ marginLeft:'auto', fontFamily:'var(--font-mono)', fontSize:9, color:'var(--text-3)' }}>{itg.lastSync}</span>
        </div>
      ))}
    </div>
  );
}

/* ── Calendar strip ── */
function CalendarStrip({ events, style = {} }) {
  return (
    <div style={{ display:'flex', gap:6, ...style }}>
      {events.map((ev, i) => (
        <div key={i} style={{ flex:1, padding:'8px 10px', background:ev.important?'var(--accent-soft)':'var(--bg-3)', border:'1px solid '+(ev.important?'rgba(173,0,33,.15)':'var(--border-subtle)'), borderRadius:6 }}>
          <div style={{ fontFamily:'var(--font-mono)', fontSize:10, fontWeight:600, color:ev.important?'var(--accent)':'var(--text-2)', marginBottom:2 }}>{ev.time}–{ev.end}</div>
          <div style={{ fontSize:11, fontWeight:500, color:'var(--text-0)', lineHeight:1.3 }}>{ev.title}</div>
        </div>
      ))}
    </div>
  );
}

/* ── AI Chat ── */
function AIChatPanel({ messages, style = {} }) {
  const [input, setInput] = useState('');
  return (
    <div style={{ display:'flex', flexDirection:'column', height:'100%', ...style }}>
      <div style={{ flex:1, overflowY:'auto', padding:'10px 12px', display:'flex', flexDirection:'column', gap:8 }}>
        {messages.map((msg, i) => (
          <div key={i} style={{ display:'flex', flexDirection:'column', alignItems:msg.role==='user'?'flex-end':'flex-start' }}>
            <div style={{ maxWidth:'88%', padding:'8px 10px', borderRadius:6, background:msg.role==='user'?'var(--accent)':'var(--bg-3)', color:msg.role==='user'?'#fff':'var(--text-1)', fontSize:11, lineHeight:1.55, whiteSpace:'pre-line' }}>{msg.text}</div>
            <span style={{ fontSize:9, color:'var(--text-4)', marginTop:2, fontFamily:'var(--font-mono)' }}>{msg.time}</span>
          </div>
        ))}
      </div>
      <div style={{ padding:'8px 10px', borderTop:'1px solid var(--border-subtle)', display:'flex', gap:6 }}>
        <input value={input} onChange={e => setInput(e.target.value)} placeholder="AIに質問・指示..."
          style={{ flex:1, fontSize:11, padding:'6px 8px', border:'1px solid var(--border)', borderRadius:4, background:'var(--bg-3)', color:'var(--text-1)', fontFamily:'var(--font-sans)', outline:'none' }} />
        <button style={{ background:'var(--accent)', color:'#fff', border:'none', borderRadius:4, padding:'6px 10px', cursor:'pointer', display:'flex', alignItems:'center' }}>
          <Icon name="send" size={12} style={{ color:'#fff' }} />
        </button>
      </div>
    </div>
  );
}

/* ── Stats summary ── */
function StatsSummary({ stats }) {
  const items = [
    { label:'全タスク', value:stats.total, color:'var(--text-0)' },
    { label:'緊急', value:stats.p1, color:'var(--danger)' },
    { label:'AI自動', value:stats.aiAuto, color:'var(--info)' },
    { label:'承認待ち', value:stats.approval, color:'var(--accent)' },
  ];
  return (
    <div style={{ display:'flex', gap:12 }}>
      {items.map((it,i) => (
        <div key={i} style={{ display:'flex', alignItems:'baseline', gap:4 }}>
          <span style={{ fontFamily:'var(--font-mono)', fontSize:18, fontWeight:600, color:it.color, letterSpacing:'-.02em' }}>{it.value}</span>
          <span style={{ fontSize:9, fontWeight:600, letterSpacing:'.04em', color:'var(--text-3)', textTransform:'uppercase' }}>{it.label}</span>
        </div>
      ))}
    </div>
  );
}

/* ── Btn helper ── */
function Btn({ children, primary, danger, small, onClick, style: sx = {} }) {
  return (
    <button onClick={onClick} style={{
      fontFamily:'var(--font-sans)', fontSize: small?10:11, fontWeight: primary||danger?600:500,
      padding: small?'4px 10px':'5px 12px', border:'1px solid '+(primary?'var(--accent)':danger?'var(--danger)':'var(--border)'),
      borderRadius:4, cursor:'pointer', transition:'all .12s', display:'inline-flex', alignItems:'center', gap:6,
      background: primary?'var(--accent)':danger?'var(--danger)':'var(--surface)',
      color: primary||danger?'#fff':'var(--text-2)', ...sx,
    }}>{children}</button>
  );
}

/* ── Filter chip ── */
function FilterChip({ label, active, onClick }) {
  return (
    <button onClick={onClick} style={{
      fontFamily:'var(--font-sans)', fontSize:10, fontWeight:600, letterSpacing:'.04em',
      padding:'4px 12px', border:'1px solid '+(active?'var(--accent)':'var(--border)'),
      borderRadius:'var(--radius-pill)', cursor:'pointer', transition:'all .15s',
      background: active?'var(--accent)':'var(--surface)', color: active?'#fff':'var(--text-2)',
    }}>{label}</button>
  );
}

Object.assign(window, {
  Icon, PriorityBadge, ModeBadge, SourceBadge, CategoryLabel, StatusDot, StatusBadge,
  SectionHead, TaskCard, FileTreeNode, FileTree, IntegrationList, CalendarStrip,
  AIChatPanel, StatsSummary, Btn, FilterChip, Fragment,
});
