// General Information form (image 3) — full workflow with validation & DB
//
// Request No. format: CF-YYMM####  (e.g. CF-26050000, CF-26050001, …)
// Continues from the highest existing Request No. for the current month.
function genNextCfNo(){
  const now = new Date();
  const yy = String(now.getFullYear()).slice(2);
  const mm = String(now.getMonth()+1).padStart(2,'0');
  const prefix = `CF-${yy}${mm}`;
  let maxN = -1;
  try {
    const saved = JSON.parse(localStorage.getItem('finx_cf_requests_v1') || '{}');
    Object.keys(saved).forEach(k => {
      if (k.startsWith(prefix)){
        const n = parseInt(k.slice(prefix.length), 10);
        if (!isNaN(n) && n > maxN) maxN = n;
      }
    });
  } catch(_){}
  const issuedKey = 'finx_cf_run_'+prefix;
  const issuedMax = parseInt(localStorage.getItem(issuedKey) || '-1', 10);
  if (!isNaN(issuedMax) && issuedMax > maxN) maxN = issuedMax;
  const next = maxN + 1;
  localStorage.setItem(issuedKey, String(next));
  return `${prefix}${String(next).padStart(4,'0')}`;
}

// Default = empty form (everything blank). Request No. issued only on Add Item.
const emptyForm = () => ({
  reqNo:'',
  reqDate:'',
  currency:'',
  person:'',
  dept:'',
  fy:'',
  fm:'',
  sales: '',
  expense: '',
  payChq: '',
  payMNI: '',
  payJS: '',
  interest: '',
  notes:'',
  status:'Draft',
});

// Field labels for validation messages
const FIELD_LABELS = {
  reqNo:'Request No.', reqDate:'Request Date', currency:'Currency',
  person:'Responsible Person', dept:'Department',
  fy:'Fiscal Year', fm:'Fiscal Month',
  sales:'Sales', expense:'Expense', payChq:'Payment Cheque',
  payMNI:'Payment MNI', payJS:'Payment JS', interest:'Interest',
};

const GENERAL_FIELDS   = ['reqNo','reqDate','currency','person','dept','fy','fm'];
const FINANCIAL_FIELDS = ['sales','expense','payChq','payMNI','payJS','interest'];

const isEmpty = (v) => v === '' || v === null || v === undefined;
const missingIn = (form, keys) => keys.filter(k => isEmpty(form[k]));

function GeneralInfoView({ onNav }){
  const clock = useSystemClock();
  const [form, setForm] = useState(()=> emptyForm());
  const [step, setStep] = useState(1);
  const [files, setFiles] = useState([]);
  const [locked, setLocked] = useState(false);      // true once Request No. issued or record loaded
  const [reqSearch, setReqSearch] = useState('');
  const [editMode, setEditMode] = useState(false);
  // Section unlocks — gated by clicking "Next: …" after filling required fields
  const [financialUnlocked, setFinancialUnlocked]   = useState(false);
  const [attachmentsUnlocked, setAttachmentsUnlocked] = useState(false);
  const fileRef = useRef();
  const dirtyRef = useRef(false);

  const totalAmount =
    (parseFloat(form.sales)||0) - (parseFloat(form.expense)||0) - (parseFloat(form.interest)||0);

  const set = (k,v)=> { dirtyRef.current = true; setForm(f=>({...f,[k]:v})); };
  const setNum = (k) => (e) => {
    const raw = e.target.value.replace(/,/g,'');
    set(k, raw);
  };

  // Auto-fill department from person
  const onPersonChange = (e) => {
    const name = e.target.value;
    const user = USERS.find(u => u.name === name);
    dirtyRef.current = true;
    setForm(f => ({...f, person:name, dept: user ? user.dept : ''}));
  };

  // Auto-save toast every 30s if dirty
  useEffect(()=>{
    const t = setInterval(()=>{
      if (dirtyRef.current){
        dirtyRef.current = false;
        window.toast('Draft auto-saved · '+new Date().toLocaleTimeString(), {tone:'info', ttl:1800});
      }
    }, 30000);
    return ()=>clearInterval(t);
  },[]);

  const [open1, setOpen1] = useState(true);
  const [open2, setOpen2] = useState(true);
  const [open3, setOpen3] = useState(true);

  // --- Validation helpers ---
  const missingGeneral   = missingIn(form, GENERAL_FIELDS);
  const missingFinancial = missingIn(form, FINANCIAL_FIELDS);   // empty string = not entered (0 is OK)
  const isGeneralOk      = missingGeneral.length === 0;
  const isFinancialOk    = missingFinancial.length === 0;
  const canSubmit        = isGeneralOk && isFinancialOk;

  const warn = (title, missing) => {
    window.toast(
      'ยังขาด: ' + missing.map(k=>FIELD_LABELS[k]).join(', '),
      { tone:'warn', title, ttl:4500 }
    );
  };

  // Load a saved record into the form
  const loadRecord = (rec) => {
    setForm({...emptyForm(), ...rec});
    setFiles(rec.files || []);
    setLocked(true);
    setEditMode(false);
    setReqSearch('');
    // A loaded record is already complete — unlock all sections
    setFinancialUnlocked(true);
    setAttachmentsUnlocked(true);
    dirtyRef.current = false;
  };

  // Search by Request No. — tries D1 first, falls back to localStorage
  const onSearchReqNo = () => {
    const q = reqSearch.trim().toUpperCase();
    if (!q){ window.toast('กรอกเลขที่ Request No. ที่ต้องการค้นหา', {tone:'info'}); return; }
    const tryLocal = () => {
      const saved = JSON.parse(localStorage.getItem('finx_cf_requests_v1') || '{}');
      if (saved[q]){
        loadRecord(saved[q]);
        window.toast(`โหลดรายการ ${q} สำเร็จ`, {tone:'success', title:'พบข้อมูล'});
      } else {
        window.toast(`ไม่พบเลขที่ ${q} ในระบบ`, {tone:'warn', title:'ค้นหาไม่พบ'});
      }
    };
    window.finxDB.getCfRequest(q).then(rec => {
      if (rec) {
        loadRecord({
          reqNo: rec.req_no, reqDate: rec.req_date || '', currency: rec.currency || '',
          person: rec.person || '', dept: rec.dept || '',
          fy: rec.fiscal_year || '', fm: rec.fiscal_month || '',
          sales: rec.sales, expense: rec.expense,
          payChq: rec.pay_chq, payMNI: rec.pay_mni, payJS: rec.pay_js,
          interest: rec.interest, notes: rec.notes || '',
          status: rec.status || 'Draft',
          files: (() => { try { return JSON.parse(rec.files_meta || '[]'); } catch(_){ return []; } })(),
        });
        window.toast(`โหลดรายการ ${q} จาก D1 สำเร็จ`, {tone:'success', title:'พบข้อมูล'});
      } else { tryLocal(); }
    }).catch(tryLocal);
  };

  // --- Action handlers ---
  const onPreview = () => {
    if (!form.reqNo){
      window.toast('กรุณากด Add Item เพื่อออกเลขที่ Request No. ก่อนดู Preview', {tone:'warn'});
      return;
    }
    window.openModal({
      title:'Preview · '+form.reqNo,
      size:'lg',
      message: <PreviewBody form={form} totalAmount={totalAmount} files={files}/>,
      actions:[
        { label:'Close', kind:'ghost' },
        { label:'Submit now', kind:'primary', onClick:onSubmit }
      ]
    });
  };
  const onExit = () => {
    if (!dirtyRef.current && JSON.stringify(form)===JSON.stringify(emptyForm())){
      onNav && onNav('dashboard'); return;
    }
    window.confirmDialog({
      title:'Exit without saving?',
      message:'You have unsaved changes. Leaving will discard your edits.',
      tone:'danger', okLabel:'Discard & exit',
      onOk: ()=>{ resetAll(); onNav && onNav('dashboard'); }
    });
  };

  const resetAll = () => {
    setForm(emptyForm());
    setFiles([]);
    setStep(1);
    setLocked(false);
    setEditMode(false);
    setReqSearch('');
    setOpen1(true); setOpen2(true); setOpen3(true);
    setFinancialUnlocked(false);
    setAttachmentsUnlocked(false);
    dirtyRef.current = false;
  };

  const persistRecord = (status) => {
    const saved = JSON.parse(localStorage.getItem('finx_cf_requests_v1') || '{}');
    saved[form.reqNo] = {
      ...form,
      status,
      files,
      submittedAt: status==='Submitted' ? new Date().toISOString() : (saved[form.reqNo]?.submittedAt || null),
      savedAt: new Date().toISOString(),
    };
    localStorage.setItem('finx_cf_requests_v1', JSON.stringify(saved));
    // Also persist to Cloudflare D1
    window.finxDB.saveCfRequest(form, files, status).catch(() => {});
  };

  const onSaveDraft = () => {
    if (!form.reqNo){ window.toast('กรุณากด Add Item เพื่อออกเลขที่ Request No. ก่อน', {tone:'warn'}); return; }
    persistRecord('Draft');
    const no = form.reqNo;
    resetAll();
    window.toast(no+' saved as draft · ฟอร์มถูกล้างพร้อมสร้างรายการใหม่',
      {tone:'success', title:'Saved', ttl:3500});
  };

  const onSubmit = () => {
    if (!form.reqNo){ window.toast('กรุณากด Add Item เพื่อออกเลขที่ Request No. ก่อน', {tone:'warn'}); return; }
    if (!canSubmit){
      warn('กรุณากรอกข้อมูลให้ครบทุกช่อง', [...missingGeneral, ...missingFinancial]);
      return;
    }
    window.confirmDialog({
      title:'Submit '+form.reqNo+'?',
      message:'ระบบจะส่งคำขอนี้เข้าสู่ขั้นตอนอนุมัติ และล้างฟอร์มกลับเป็นค่าเริ่มต้นโดยอัตโนมัติ',
      okLabel:'Submit', tone:'primary',
      onOk: ()=>{
        persistRecord('Submitted');
        const no = form.reqNo;
        resetAll();
        window.toast(no+' submitted · ฟอร์มถูกล้างพร้อมสร้างรายการใหม่',
          {tone:'success', title:'Submitted & saved', ttl:3800});
      }
    });
  };

  const onReset = () => {
    window.confirmDialog({
      title:'Reset form?',
      message:'ล้างค่าทั้งหมดในกรอบ General Information, Financial Details, และ Attachments & Notes กลับเป็นค่าเริ่มต้น',
      tone:'danger', okLabel:'Reset',
      onOk: ()=>{ resetAll(); window.toast('Form reset · ล้างค่าทุกช่องแล้ว'); }
    });
  };

  const onAddItem = () => {
    if (locked){
      window.toast('Request No. already issued · '+form.reqNo, {tone:'info'});
      return;
    }
    const reqNo = genNextCfNo();
    setForm(f => ({...f, reqNo}));
    setLocked(true);
    setReqSearch('');
    window.toast('Request No. issued · '+reqNo, {tone:'success', title:'Add Item'});
  };

  const onEdit = () => {
    window.openModal({
      title:'Edit existing request',
      size:'md',
      message: <EditLookupForm onSubmit={(reqNo)=>{
        const saved = JSON.parse(localStorage.getItem('finx_cf_requests_v1') || '{}');
        const rec = saved[reqNo];
        if (!rec){
          window.toast(`ไม่พบเลขที่ ${reqNo} ในระบบ`, {tone:'warn', title:'ค้นหาไม่พบ'});
          return;
        }
        if (rec.status === 'Approved'){
          window.toast(`รายการ ${reqNo} ถูก Approve แล้ว ไม่สามารถแก้ไขได้`, {tone:'danger', title:'Edit not allowed'});
          return;
        }
        loadRecord(rec);
        setEditMode(true);
        window.toast(`โหลด ${reqNo} เพื่อแก้ไข · สถานะ: ${rec.status||'Draft'}`,
          {tone:'success', title:'Edit mode'});
      }}/>
    });
  };

  const handleFiles = (list) => {
    const arr = Array.from(list).map(f => ({name:f.name, size:f.size, type:f.type}));
    setFiles(fs => [...fs, ...arr]);
    window.toast(`Attached ${arr.length} file(s)`, {tone:'success'});
  };

  // --- Render ---
  return (
    <div className="page">
      <div className="page-head">
        <div>
          <div className="page-title">
            General Information
            {editMode && <span className="chip amber" style={{marginLeft:10,fontSize:11}}>EDIT MODE</span>}
          </div>
          <div className="page-sub">
            {form.reqNo
              ? <>{editMode?'Editing':'New cash flow request'} · <b className="mono">{form.reqNo}</b> · status: {form.status}</>
              : 'New cash flow request · กด Add Item เพื่อออกเลขที่'}
          </div>
        </div>
        <div className="row" style={{gap:8}}>
          <button className="btn" onClick={onPreview}><I.Eye size={14}/> Preview</button>
          <button className="btn danger" onClick={onExit}><I.Logout size={14}/> Exit</button>
          <button className="btn success" onClick={onSaveDraft}><I.Save size={14}/> Save draft</button>
          <button className="btn primary" onClick={onSubmit}><I.Check size={14}/> Submit</button>
        </div>
      </div>

      {/* Stepper */}
      <div className="card" style={{padding:'16px 20px',marginBottom:18}}>
        <div className="row" style={{gap:8,alignItems:'center'}}>
          {['General','Financial','Attachments','Review'].map((s,i)=>{
            const idx = i+1;
            const active = step===idx;
            const done = step>idx;
            return (
              <React.Fragment key={i}>
                <div className="row" style={{gap:10,cursor:'pointer'}} onClick={()=>setStep(idx)}>
                  <div style={{
                    width:30,height:30,borderRadius:50,display:'grid',placeItems:'center',fontWeight:700,fontSize:13,
                    background: (active||done) ? 'linear-gradient(135deg,#2cb8b0,#1f2a8e)' : '#eef1f8',
                    color: (active||done) ? '#fff' : '#7b87a8',
                    boxShadow: active ? '0 0 0 4px rgba(31,42,142,.12)' : 'none',
                    transition:'all .2s ease',
                  }}>{done ? <I.Check size={14}/> : idx}</div>
                  <div>
                    <div style={{fontSize:11,color:'var(--muted)',letterSpacing:'.06em',textTransform:'uppercase'}}>Step {idx}</div>
                    <div style={{fontWeight:700,fontSize:13}}>{s}</div>
                  </div>
                </div>
                {i<3 && <div style={{flex:1,height:2,background: step>idx?'linear-gradient(90deg,#2cb8b0,#1f2a8e)':'#eef1f8',borderRadius:2,transition:'background .3s ease'}}/>}
              </React.Fragment>
            );
          })}
        </div>
      </div>

      <div className="stack" style={{gap:18}}>
        {/* General Information */}
        <Pane title="General Information" open={open1} onToggle={()=>setOpen1(!open1)} accent>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr 1fr auto',gap:14,alignItems:'flex-end'}}>
            <div className="field">
              <label>Request No. <span className="req">*</span> <span style={{color:'#7b87a8',fontWeight:500,fontSize:11,marginLeft:4}}>{locked ? '(locked)' : '(auto / search)'}</span></label>
              <div style={{position:'relative'}}>
                <input className="input mono"
                       value={locked ? form.reqNo : reqSearch}
                       readOnly={locked}
                       placeholder={locked ? '' : 'ค้นหา หรือกด Add Item'}
                       title={locked ? 'Request No. is auto-generated and cannot be edited' : 'พิมพ์เลข Request No. แล้วกด Enter เพื่อค้นหารายการเดิม'}
                       onChange={e => !locked && setReqSearch(e.target.value.toUpperCase())}
                       onKeyDown={e => { if (!locked && e.key === 'Enter'){ e.preventDefault(); onSearchReqNo(); } }}
                       onFocus={e => { if (!locked) e.target.placeholder = ''; }}
                       onBlur={e => { if (!locked) e.target.placeholder = 'ค้นหา หรือกด Add Item'; }}
                       style={{
                         background: locked ? 'linear-gradient(135deg,#eef1f8,#fff)' : '#fff',
                         color: locked ? '#1f2a8e' : 'var(--ink)',
                         fontWeight:700,letterSpacing:'.04em',
                         paddingRight: locked ? 36 : 12,
                         cursor: locked ? 'not-allowed' : 'text'
                       }}/>
                {locked && (
                  <I.Lock size={14} stroke="#7b87a8"
                    style={{position:'absolute',right:12,top:'50%',transform:'translateY(-50%)'}}/>
                )}
              </div>
            </div>
            <div className="field">
              <label>Request Date <span className="req">*</span></label>
              <div className="dateinput">
                <I.Cal size={14} stroke="#7b87a8"/>
                <input type="date" value={form.reqDate} onChange={e=>set('reqDate',e.target.value)}/>
              </div>
            </div>
            <div className="field">
              <label>Currency <span className="req">*</span></label>
              <select className="select" value={form.currency} onChange={e=>set('currency',e.target.value)}>
                <option value="">— Select —</option>
                <option>THB</option>
              </select>
            </div>
            <div className="row" style={{gap:8}}>
              <button className="btn success" onClick={onAddItem}><I.Plus size={14}/> Add Item</button>
              <button className="btn" onClick={onEdit}><I.Edit size={14}/> Edit</button>
              <button className="btn primary" onClick={onReset}><I.Reset size={14}/> Reset</button>
            </div>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr 1fr 1fr',gap:14,marginTop:14}}>
            <div className="field">
              <label>Responsible Person <span className="req">*</span></label>
              <select className="select thai" value={form.person} onChange={onPersonChange}>
                <option value="">— Select —</option>
                {USERS.filter(u => u.status !== 'inactive').map(u => (
                  <option key={u.id} value={u.name}>{u.name}</option>
                ))}
              </select>
            </div>
            <div className="field">
              <label>Department <span className="req">*</span> <span style={{color:'#7b87a8',fontWeight:500,fontSize:11,marginLeft:4}}>(auto)</span></label>
              <div style={{position:'relative'}}>
                <input className="input thai" value={form.dept} readOnly
                       placeholder="— เลือก Responsible Person ก่อน —"
                       style={{
                         background: form.dept ? 'linear-gradient(135deg,#eef1f8,#fff)' : '#fafbff',
                         color: form.dept ? 'var(--ink)' : '#9aa3c2',
                         fontWeight:600,paddingRight:32,cursor:'not-allowed'
                       }}/>
                <I.Lock size={14} stroke="#7b87a8"
                  style={{position:'absolute',right:12,top:'50%',transform:'translateY(-50%)'}}/>
              </div>
            </div>
            <div className="field">
              <label>Fiscal Year <span className="req">*</span></label>
              <select className="select" value={form.fy} onChange={e=>set('fy',e.target.value)}>
                <option value="">— Select —</option>
                {['2026','2027','2028'].map(y=><option key={y}>{y}</option>)}
              </select>
            </div>
            <div className="field">
              <label>Fiscal Month <span className="req">*</span></label>
              <select className="select" value={form.fm} onChange={e=>set('fm',e.target.value)}>
                <option value="">— Select —</option>
                {['January','February','March','April','May','June','July','August','September','October','November','December'].map(m=><option key={m}>{m}</option>)}
              </select>
            </div>
          </div>
          <div style={{marginTop:18,display:'flex',justifyContent:'flex-end'}}>
            <button className="btn primary" onClick={()=>{
              if (!isGeneralOk){ warn('กรุณากรอกข้อมูลให้ครบทุกช่อง', missingGeneral); return; }
              setFinancialUnlocked(true);
              setStep(2);
              window.toast('Financial Details ปลดล็อคแล้ว · เริ่มกรอกข้อมูลทางการเงินได้', {tone:'success'});
            }}>Next: Financial <I.Chev size={12}/></button>
          </div>
        </Pane>

        {/* Financial Details */}
        <Pane title="Financial Details" open={open2} onToggle={()=>setOpen2(!open2)} accent>
          <div style={{
            opacity: financialUnlocked ? 1 : 0.45,
            filter:  financialUnlocked ? 'none' : 'grayscale(.55)',
            pointerEvents: financialUnlocked ? 'auto' : 'none',
            transition:'opacity .25s ease, filter .25s ease',
          }}>
          <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:14}}>
            <Money label="Sales"          value={form.sales}    onChange={setNum('sales')}   tone="#16a34a"/>
            <Money label="Expense"        value={form.expense}  onChange={setNum('expense')} tone="#dc2626"/>
            <Money label="Payment Cheque" value={form.payChq}   onChange={setNum('payChq')}  tone="#1f2a8e"/>
            <Money label="Payment MNI"    value={form.payMNI}   onChange={setNum('payMNI')}  tone="#1f2a8e"/>
            <Money label="Payment JS"     value={form.payJS}    onChange={setNum('payJS')}   tone="#1f2a8e"/>
            <Money label="Interest"       value={form.interest} onChange={setNum('interest')} tone="#d97706"/>
            <div className="field" style={{gridColumn:'span 2'}}>
              <label>Total Amount (auto)</label>
              <div className="input-group">
                <input className="input lg mono"
                       style={{background:'linear-gradient(135deg,#eef1f8,#fff)',fontWeight:700,color:'var(--brand)'}}
                       value={fmt(totalAmount)} readOnly/>
                <span className="suffix">THB</span>
              </div>
              <div style={{fontSize:11.5,color:'var(--muted)',marginTop:4}}>= Sales − Expense − Interest</div>
            </div>
          </div>

          <div className="row" style={{gap:8,marginTop:18,flexWrap:'wrap'}}>
            <span className={"chip "+(totalAmount>=0?'green':'red')}>
              {totalAmount>=0 ? <I.TrendUp size={11}/> : <I.TrendDown size={11}/>}
              Net {totalAmount>=0?'positive':'negative'}
            </span>
            <span className="chip">Cash impact: <b className="mono" style={{marginLeft:4}}>{fmt(totalAmount)}</b></span>
            <span className="chip">Ratio E/S: <b className="mono" style={{marginLeft:4}}>{(parseFloat(form.sales)||0) ? (((parseFloat(form.expense)||0)/(parseFloat(form.sales)||1))*100).toFixed(1):0}%</b></span>
            <span className="chip">หากช่องไหนไม่มีตัวเลข ให้กรอก 0</span>
          </div>

          <div style={{marginTop:18,display:'flex',justifyContent:'space-between'}}>
            <button className="btn" onClick={()=>setStep(1)}>← Back</button>
            <button className="btn primary" onClick={()=>{
              if (!isFinancialOk){ warn('กรุณากรอกข้อมูล Financial Details ให้ครบ (ใส่ 0 หากไม่มี)', missingFinancial); return; }
              setAttachmentsUnlocked(true);
              setStep(3);
              window.toast('Attachments & Notes ปลดล็อคแล้ว', {tone:'success'});
            }}>Next: Attachments <I.Chev size={12}/></button>
          </div>
          </div>{/* /financial lock wrapper */}
        </Pane>

        {/* Attachments & Notes */}
        <Pane title="Attachments & Notes" open={open3} onToggle={()=>setOpen3(!open3)} accent>
          <div style={{
            opacity: attachmentsUnlocked ? 1 : 0.45,
            filter:  attachmentsUnlocked ? 'none' : 'grayscale(.55)',
            pointerEvents: attachmentsUnlocked ? 'auto' : 'none',
            transition:'opacity .25s ease, filter .25s ease',
          }}>
          <div style={{display:'grid',gridTemplateColumns:'2fr 1fr',gap:14}}>
            <div className="field">
              <label>Notes</label>
              <textarea className="input" style={{height:96,padding:'10px 12px',resize:'vertical'}}
                value={form.notes} onChange={e=>set('notes',e.target.value)}
                placeholder="Add context or justification for this cash flow request…"/>
            </div>
            <div className="field">
              <label>Attachments {files.length>0 && <span className="chip" style={{marginLeft:6}}>{files.length}</span>}</label>
              <div style={{
                border:'1.5px dashed #cdd5ea',borderRadius:12,padding:18,textAlign:'center',
                background:'linear-gradient(180deg,#f7f8fc,#fff)',cursor:'pointer',transition:'.15s'
              }}
                onClick={()=> fileRef.current.click()}
                onDragOver={e=>{ e.preventDefault(); e.currentTarget.style.background='#eef1f8'; }}
                onDragLeave={e=>{ e.currentTarget.style.background='linear-gradient(180deg,#f7f8fc,#fff)'; }}
                onDrop={e=>{ e.preventDefault(); e.currentTarget.style.background='linear-gradient(180deg,#f7f8fc,#fff)'; handleFiles(e.dataTransfer.files); }}>
                <I.Download size={22} stroke="#7b87a8"/>
                <div style={{marginTop:6,fontSize:13,fontWeight:600}}>Drop files here</div>
                <div style={{fontSize:11.5,color:'var(--muted)'}}>or click to browse</div>
                <input ref={fileRef} type="file" multiple style={{display:'none'}}
                       onChange={e=> handleFiles(e.target.files)}/>
              </div>
            </div>
          </div>
          {files.length>0 && (
            <div style={{marginTop:14,display:'flex',flexDirection:'column',gap:6}}>
              {files.map((f,i)=>(
                <div key={i} style={{display:'flex',alignItems:'center',gap:10,padding:'8px 12px',background:'#f7f8fc',borderRadius:10,fontSize:13}}>
                  <I.Doc size={14} stroke="#1f2a8e"/>
                  <span style={{flex:1,fontWeight:600}}>{f.name}</span>
                  <span className="muted" style={{fontSize:11}}>{((f.size||0)/1024).toFixed(1)} KB</span>
                  <button className="icon-btn" style={{width:28,height:28}} onClick={()=>setFiles(fs=>fs.filter((_,j)=>j!==i))}><I.Trash size={12}/></button>
                </div>
              ))}
            </div>
          )}
          <div style={{marginTop:18,display:'flex',justifyContent:'space-between'}}>
            <button className="btn" onClick={()=>setStep(2)}>← Back</button>
            <button className="btn primary" onClick={()=>{ setStep(4); onPreview(); }}>Review <I.Chev size={12}/></button>
          </div>
          </div>{/* /attachments lock wrapper */}
        </Pane>
      </div>

      <div style={{marginTop:18,display:'flex',justifyContent:'space-between',color:'var(--muted)',fontSize:12,fontStyle:'italic'}}>
        <span>{dirtyRef.current ? 'Unsaved changes…' : 'All changes saved'}</span>
        <span>{clock}</span>
      </div>
    </div>
  );
}

// Edit lookup modal — asks for Request No., validates not approved
function EditLookupForm({ onSubmit }){
  const [no, setNo] = useState('');
  return (
    <div style={{display:'grid',gap:12}}>
      <div style={{fontSize:13.5,color:'var(--ink-2)',lineHeight:1.55}}>
        กรอกเลขที่ Request No. ที่ต้องการแก้ไข — สามารถแก้ไขได้เฉพาะรายการที่ยังไม่ Approve เท่านั้น
      </div>
      <div className="field">
        <label>Request No. <span className="req">*</span></label>
        <input className="input mono" autoFocus
               value={no}
               placeholder="เช่น CF-26050001"
               onChange={e=> setNo(e.target.value.toUpperCase())}
               onKeyDown={e=>{ if (e.key==='Enter' && no.trim()){ onSubmit(no.trim()); window.closeModal(); } }}
               style={{fontWeight:700,letterSpacing:'.04em'}}/>
      </div>
      <div className="row" style={{gap:8,justifyContent:'flex-end'}}>
        <button className="btn" onClick={()=> window.closeModal()}>Cancel</button>
        <button className="btn primary" disabled={!no.trim()}
                onClick={()=>{ onSubmit(no.trim()); window.closeModal(); }}>
          <I.Search size={14}/> Load for editing
        </button>
      </div>
    </div>
  );
}

function PreviewBody({ form, totalAmount, files }){
  const cur = form.currency || 'THB';
  const lines = [
    ['Request No.',    form.reqNo || '(no number)'],
    ['Date',           form.reqDate || '—'],
    ['Currency',       form.currency || '—'],
    ['Responsible',    form.person || '—'],
    ['Department',     form.dept || '—'],
    ['Period',         (form.fm && form.fy) ? `${form.fm} ${form.fy}` : '—'],
    ['Sales',          fmt(parseFloat(form.sales)||0)    + ' ' + cur],
    ['Expense',        fmt(parseFloat(form.expense)||0)  + ' ' + cur],
    ['Payment Cheque', fmt(parseFloat(form.payChq)||0)   + ' ' + cur],
    ['Payment MNI',    fmt(parseFloat(form.payMNI)||0)   + ' ' + cur],
    ['Payment JS',     fmt(parseFloat(form.payJS)||0)    + ' ' + cur],
    ['Interest',       fmt(parseFloat(form.interest)||0) + ' ' + cur],
  ];
  return (
    <div>
      <div style={{
        background:'linear-gradient(135deg,#1f2a8e,#2e3bbf)',color:'#fff',
        padding:18,borderRadius:14,marginBottom:18,
        display:'flex',justifyContent:'space-between',alignItems:'center'
      }}>
        <div>
          <div style={{fontSize:11,letterSpacing:'.1em',textTransform:'uppercase',opacity:.7}}>Total Amount</div>
          <div style={{display:'flex',alignItems:'baseline',gap:8,marginTop:4}}>
            <span className="mono" style={{fontSize:32,fontWeight:800,lineHeight:1}}>{fmt(totalAmount)}</span>
            <span style={{fontSize:13,opacity:.7,fontWeight:600}}>{cur}</span>
          </div>
        </div>
        <div style={{textAlign:'right'}}>
          <div style={{fontSize:11,opacity:.7}}>Status</div>
          <div className="chip" style={{background:'rgba(255,255,255,.18)',color:'#fff',border:0,marginTop:4}}>{form.status||'Draft'}</div>
        </div>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:6}}>
        {lines.map(([k,v],i)=>(
          <div key={i} style={{display:'flex',justifyContent:'space-between',padding:'8px 12px',background:i%2?'#f7f8fc':'transparent',borderRadius:6,fontSize:13}}>
            <span style={{color:'var(--muted)'}}>{k}</span>
            <span className="thai" style={{fontWeight:600}}>{v}</span>
          </div>
        ))}
      </div>
      {form.notes && (
        <div style={{marginTop:14,padding:12,background:'#fffbeb',border:'1px solid #fde68a',borderRadius:8,fontSize:13}}>
          <div style={{fontWeight:700,marginBottom:4}}>Notes</div>{form.notes}
        </div>
      )}
      {files && files.length>0 && (
        <div style={{marginTop:14,fontSize:13}}>
          <div style={{fontWeight:700,marginBottom:6}}>Attachments ({files.length})</div>
          {files.map((f,i)=><div key={i} style={{padding:'4px 0',color:'var(--ink-2)'}}>📎 {f.name}</div>)}
        </div>
      )}
    </div>
  );
}

function Pane({ title, children, open, onToggle, accent }){
  return (
    <div className="pane">
      <div className="pane-bar" onClick={onToggle} style={{cursor:'pointer',userSelect:'none'}}>
        <div className="title">{accent && <span className="swatch"/>}{title}</div>
        <div style={{
          width:24,height:24,borderRadius:6,display:'grid',placeItems:'center',
          transform:open?'rotate(0)':'rotate(-90deg)',transition:'.18s',color:'#7b87a8'
        }}>
          <span style={{display:'block',width:10,height:2,background:'currentColor'}}/>
        </div>
      </div>
      {open && <div className="pane-body" style={{animation:'fadein .25s ease'}}>{children}</div>}
    </div>
  );
}

// Money input with focus/blur formatting: show plain digits while editing, formatted on blur.
function Money({ label, value, onChange, tone }){
  const [focused, setFocused] = useState(false);
  const display = focused
    ? (value === '' || value === null || value === undefined ? '' : String(value))
    : (value === '' || value === null || value === undefined ? '' : fmt(parseFloat(value)||0));
  return (
    <div className="field">
      <label>{label} <span className="req">*</span></label>
      <div className="input-group">
        <input className="input lg mono"
               type="text" inputMode="decimal"
               style={{color: tone, fontWeight:700}}
               value={display}
               placeholder={focused ? '' : '0.00'}
               onFocus={()=> setFocused(true)}
               onBlur={()=> setFocused(false)}
               onChange={(e)=>{
                 const raw = e.target.value.replace(/[^\d.\-]/g,'');
                 const parts = raw.split('.');
                 const cleaned = parts.length>1 ? parts[0]+'.'+parts.slice(1).join('').slice(0,2) : raw;
                 onChange({target:{value:cleaned}});
               }}
               onKeyDown={(e)=>{
                 if (e.key === 'Enter'){
                   e.preventDefault();
                   e.target.blur();
                   // jump to next money input
                   setTimeout(()=>{
                     const inputs = Array.from(document.querySelectorAll('.field .input.lg.mono'));
                     const idx = inputs.indexOf(e.target);
                     if (idx >= 0 && inputs[idx+1]) inputs[idx+1].focus();
                   }, 0);
                 }
               }}/>
      </div>
    </div>
  );
}

window.GeneralInfoView = GeneralInfoView;
