/* global React, API, useApp */
const { useState, useEffect, useCallback } = React;

const fmtEur = v => v == null ? '—' : `€${Number(v).toLocaleString('nl-NL',{minimumFractionDigits:2,maximumFractionDigits:2})}`;
const SOURCE_LABELS = { recurring:'Recurring', passthrough:'Passthrough', time:'Time', manual:'Manual' };
const SOURCE_COLORS = { recurring:'var(--teal)', passthrough:'var(--amber)', time:'var(--fg-muted)', manual:'var(--ember)' };

function QueueItem({ item, approvalMode, onApprove, onReject, onDelete }) {
  const [editingDesc, setEditingDesc] = useState(false);
  const [desc, setDesc]               = useState(item.description);
  useEffect(() => { setDesc(item.description); }, [item.description]);

  async function saveDesc() {
    setEditingDesc(false);
    if (desc === item.description) return;
    await API.patch(`/billing-queue/${item.id}`, { description: desc }).catch(() => setDesc(item.description));
  }

  const isAuto   = approvalMode === 'auto';
  const subtotal = item.quantity * item.unit_price;
  const total    = subtotal * (1 + item.vat_rate);

  return (
    <div style={{display:'grid',gridTemplateColumns:'90px 1fr 60px 80px 80px 110px',gap:8,alignItems:'center',
      padding:'8px 0',borderBottom:'1px solid var(--border)',fontSize:12,
      opacity: item.virtual ? 0.8 : 1}}>
      <span style={{fontSize:10,fontFamily:'var(--font-mono)',color:SOURCE_COLORS[item.source_type]||'var(--fg-muted)',
        textTransform:'uppercase',letterSpacing:'0.08em'}}>
        {SOURCE_LABELS[item.source_type]||item.source_type}
      </span>
      <span>
        {!item.virtual && editingDesc ? (
          <input autoFocus value={desc} onChange={e => setDesc(e.target.value)}
            onBlur={saveDesc}
            onKeyDown={e => { if (e.key==='Enter') e.target.blur(); if (e.key==='Escape') { setDesc(item.description); setEditingDesc(false); } }}
            style={{fontSize:12,width:'100%',background:'transparent',border:'1px solid var(--border)',
              borderRadius:2,padding:'1px 5px',fontFamily:'inherit',color:'inherit'}} />
        ) : (
          <span onClick={() => !item.virtual && setEditingDesc(true)}
            style={{cursor:item.virtual?'default':'text',
              fontWeight:item.approved===1?500:400,
              color:item.approved===0?'var(--fg-subtle)':'inherit'}}
            title={item.virtual?undefined:'Click to edit'}>
            {desc}
          </span>
        )}
        {item.next_run_at && (
          <div style={{fontSize:10,color:'var(--fg-subtle)',fontFamily:'var(--font-mono)',marginTop:1}}>
            due {item.next_run_at}{item.frequency ? ` · ${item.frequency}` : ''}
          </div>
        )}
      </span>
      <span className="mono" style={{color:'var(--fg-subtle)',fontSize:11}}>{item.quantity}×</span>
      <span className="mono" style={{textAlign:'right'}}>{fmtEur(item.unit_price)}</span>
      <span className="mono" style={{textAlign:'right',fontWeight:600}}>{fmtEur(total)}</span>
      <div style={{display:'flex',gap:4,justifyContent:'flex-end'}}>
        {isAuto ? (
          <span style={{fontSize:10,color:'var(--teal)',fontFamily:'var(--font-mono)',opacity:0.65}}>✓ auto</span>
        ) : item.approved === 1 ? (
          <span style={{fontSize:10,color:'var(--teal)',fontFamily:'var(--font-mono)'}}>✓ approved</span>
        ) : item.approved === 0 ? (
          <span style={{fontSize:10,color:'var(--fg-subtle)',fontFamily:'var(--font-mono)'}}>✗ rejected</span>
        ) : (
          <>
            <button className="btn btn--primary btn--sm" style={{padding:'2px 8px',fontSize:10}} onClick={onApprove}>✓</button>
            <button className="btn btn--ghost btn--sm"  style={{padding:'2px 8px',fontSize:10}} onClick={onReject}>✗</button>
          </>
        )}
        {!item.virtual && (
          <button className="btn btn--danger btn--sm" style={{padding:'2px 6px',fontSize:10}} onClick={onDelete}>×</button>
        )}
      </div>
    </div>
  );
}

function AddItemForm({ companyId, onAdded, onCancel }) {
  const [f, setF] = useState({ description:'', quantity:1, unit_price:'', vat_rate:0.21, source_type:'manual' });
  const [busy, setBusy] = useState(false);
  const { toast } = useApp();
  const up = k => e => setF(p => ({...p,[k]:e.target.value}));

  async function submit() {
    if (!f.description || !f.unit_price) { toast('Description and price required','error'); return; }
    setBusy(true);
    try {
      await API.post('/billing-queue', { company_id: companyId, ...f,
        quantity: Number(f.quantity), unit_price: Number(f.unit_price), vat_rate: Number(f.vat_rate) });
      onAdded();
    } catch(e) { toast(e.error||'Error','error'); }
    finally { setBusy(false); }
  }

  return (
    <div style={{display:'grid',gridTemplateColumns:'120px 1fr 60px 90px 70px auto auto',gap:6,alignItems:'end',
      marginTop:10,padding:'10px 0',borderTop:'1px solid var(--border)'}}>
      <select className="field-select" style={{fontSize:11}} value={f.source_type} onChange={up('source_type')}>
        <option value="manual">Manual</option>
        <option value="time">Time</option>
        <option value="recurring">Recurring</option>
      </select>
      <input className="field-input" style={{fontSize:11}} placeholder="Description" value={f.description} onChange={up('description')} />
      <input className="field-input mono" style={{fontSize:11}} type="number" step="0.01" placeholder="Qty" value={f.quantity} onChange={up('quantity')} />
      <input className="field-input mono" style={{fontSize:11}} type="number" step="0.01" placeholder="Unit price (ex VAT)" value={f.unit_price} onChange={up('unit_price')} />
      <select className="field-select" style={{fontSize:11}} value={f.vat_rate} onChange={up('vat_rate')}>
        <option value="0.21">21%</option><option value="0.09">9%</option><option value="0.00">0%</option>
      </select>
      <button className="btn btn--primary btn--sm" onClick={submit} disabled={busy}>{busy?'…':'Add'}</button>
      <button className="btn btn--ghost btn--sm" onClick={onCancel}>✕</button>
    </div>
  );
}

function CustomerQueue({ customer, onInvoiced }) {
  const [items, setItems]               = useState([]);
  const [approvalMode, setApprovalMode] = useState('manual');
  const [adding, setAdding]             = useState(false);
  const [busy, setBusy]                 = useState(false);
  const { toast } = useApp();

  const load = useCallback(() => {
    API.get(`/billing-queue?company_id=${customer.company_id}`).then(setItems).catch(()=>{});
  }, [customer.company_id]);

  useEffect(() => {
    load();
    API.get(`/companies/${customer.company_id}/rate`)
      .then(r => setApprovalMode(r.invoice_approval || 'manual'))
      .catch(() => {});
  }, [load]);

  async function materialise(item, approved) {
    return API.post('/billing-queue', {
      company_id:  customer.company_id,
      source_type: item.source_type,
      source_id:   item.source_id,
      description: item.description,
      quantity:    item.quantity,
      unit_price:  item.unit_price,
      vat_rate:    item.vat_rate,
      approved,
    });
  }

  async function approve(item) {
    if (item.virtual) await materialise(item, 1);
    else await API.patch(`/billing-queue/${item.id}`, { approved: 1 });
    load();
  }

  async function reject(item) {
    if (item.virtual) await materialise(item, 0);
    else await API.patch(`/billing-queue/${item.id}`, { approved: 0 });
    load();
  }

  async function del(id) { await API.del(`/billing-queue/${id}`).catch(()=>{}); load(); }

  async function approveAll() {
    const pending = items.filter(i => i.virtual || i.approved === null);
    await Promise.all(pending.map(i =>
      i.virtual ? materialise(i, 1) : API.patch(`/billing-queue/${i.id}`, { approved: 1 })
    ));
    load();
  }

  async function runInvoice() {
    setBusy(true);
    try {
      // Materialise any remaining virtual items — auto mode picks up approved=null
      const virtual = items.filter(i => i.virtual);
      if (virtual.length) await Promise.all(virtual.map(v => materialise(v, null)));
      const result = await API.post('/billing-queue/run', { company_id: customer.company_id });
      toast(`Invoice ${result.invoice_number} created (${result.items} lines)`);
      load(); onInvoiced();
    } catch(e) { toast(e.error||'Error','error'); }
    finally { setBusy(false); }
  }

  const isAuto   = approvalMode === 'auto';
  const real     = items.filter(i => !i.virtual);
  const virtual  = items.filter(i => i.virtual);
  const approved = real.filter(i => i.approved === 1);
  const pending  = real.filter(i => i.approved === null);
  const total    = real.reduce((s,i) => s + i.quantity * i.unit_price * (1 + i.vat_rate), 0);
  const canRun   = isAuto ? items.length > 0 : approved.length > 0;

  return (
    <div className="card" style={{margin:0,marginBottom:16}}>
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:12}}>
        <div>
          <div style={{display:'flex',alignItems:'center',gap:8}}>
            <div style={{fontWeight:600,fontSize:14}}>{customer.company_name}</div>
            {isAuto && (
              <span style={{fontSize:9,fontFamily:'var(--font-mono)',letterSpacing:'0.08em',textTransform:'uppercase',
                padding:'2px 7px',borderRadius:10,background:'rgba(111,227,209,0.08)',
                border:'1px solid rgba(111,227,209,0.25)',color:'var(--teal)'}}>auto-approve</span>
            )}
          </div>
          <div style={{fontSize:11,color:'var(--fg-subtle)',fontFamily:'var(--font-mono)',marginTop:2}}>
            {items.length} item{items.length!==1?'s':''}
            {virtual.length > 0 && <span style={{color:'var(--amber)'}}> · {virtual.length} upcoming</span>}
            {!isAuto && real.length > 0 && ` · ${approved.length} approved · ${pending.length} pending`}
          </div>
        </div>
        <div style={{display:'flex',gap:8,alignItems:'center'}}>
          {real.length > 0 && <span style={{fontSize:13,fontWeight:700,fontFamily:'var(--font-mono)',color:'var(--teal)'}}>{fmtEur(total)}</span>}
          {!isAuto && (pending.length > 0 || virtual.length > 0) && (
            <button className="btn btn--ghost btn--sm" onClick={approveAll}>✓ Approve all</button>
          )}
          {canRun && (
            <button className="btn btn--primary btn--sm" onClick={runInvoice} disabled={busy}>{busy?'Creating…':'Run invoice'}</button>
          )}
          <button className="btn btn--ghost btn--sm" onClick={() => setAdding(v=>!v)}>+ Add item</button>
        </div>
      </div>

      <div style={{display:'grid',gridTemplateColumns:'90px 1fr 60px 80px 80px 110px',gap:8,
        padding:'6px 0',borderBottom:'1px solid var(--border)',marginBottom:4}}>
        {['Source','Description','Qty','Price','Total incl.',''].map((h,i) =>
          <span key={i} style={{fontSize:10,fontFamily:'var(--font-mono)',color:'var(--fg-subtle)',
            textTransform:'uppercase',letterSpacing:'0.08em',textAlign:i>=3&&i<=4?'right':'left'}}>{h}</span>
        )}
      </div>

      {items.length === 0 && (
        <div style={{fontSize:12,color:'var(--fg-subtle)',padding:'12px 0'}}>No items.</div>
      )}

      {items.map(item => (
        <QueueItem key={item.id} item={item} approvalMode={approvalMode}
          onApprove={() => approve(item)}
          onReject={() => reject(item)}
          onDelete={() => del(item.id)} />
      ))}

      {adding && (
        <AddItemForm companyId={customer.company_id}
          onAdded={()=>{load();setAdding(false);}} onCancel={()=>setAdding(false)} />
      )}
    </div>
  );
}

function BillingQueue() {
  const [summary, setSummary] = useState([]);
  const [tick,    setTick]    = useState(0);
  const reload = () => { API.get('/billing-queue').then(setSummary).catch(()=>{}); setTick(t=>t+1); };
  useEffect(() => { reload(); }, []);

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h1 className="page-title">Billing Queue</h1>
          <div className="page-subtitle">All billable items per customer — approve then run the invoice.</div>
        </div>
      </div>

      {summary.length === 0 && (
        <div className="card" style={{margin:0,color:'var(--fg-subtle)',fontSize:13,textAlign:'center',padding:40}}>
          No pending or upcoming items.
        </div>
      )}

      {summary.map(c => (
        <CustomerQueue key={`${c.company_id}-${tick}`} customer={c} onInvoiced={reload} />
      ))}
    </div>
  );
}
