/* global CRQQB_SETTINGS, CRQQB_VARS */
const { useState, useMemo, useEffect, useRef } = React;

const fmt2 = (n)=> new Intl.NumberFormat('en-IN',{minimumFractionDigits:2, maximumFractionDigits:2}).format(+n||0);

/**
 * Request the next quotation number from the server.  This call
 * posts to admin‑ajax.php with the action
 * `crq_next_quotation_number` and passes the front‑end nonce.  On
 * success the returned object contains a `number` property with
 * the formatted CRQ/yyMMdd/serial string.  In case of failure
 * the promise rejects with the error message.
 *
 * @returns {Promise<string>}
 */
async function fetchNextQuoteNumber() {
  if (!CRQQB_VARS || !CRQQB_VARS.ajax_url) {
    return Promise.reject('Missing AJAX configuration');
  }
  const body = new URLSearchParams();
  body.append('action', 'crq_next_quotation_number');
  if (CRQQB_VARS.nonce) body.append('nonce', CRQQB_VARS.nonce);
  const resp = await fetch(CRQQB_VARS.ajax_url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
    body: body.toString()
  });
  let json;
  try {
    json = await resp.json();
  } catch (e) {
    throw new Error('Invalid response');
  }
  if (!json || !json.success || !json.data || !json.data.number) {
    throw new Error(json && json.data && json.data.message ? json.data.message : 'Failed to fetch number');
  }
  return json.data.number;
}

function parseStateFromGSTIN(gstin){
  if (!gstin || gstin.length < 2) return {code:"", state:""};
  const map = {"27":"Maharashtra","24":"Gujarat","09":"Uttar Pradesh","07":"Delhi"}; // minimal map
  const code = gstin.slice(0,2);
  return {code, state: map[code] || ""};
}

const INDIA_STATES = [
  "Andhra Pradesh","Arunachal Pradesh","Assam","Bihar","Chhattisgarh","Goa","Gujarat","Haryana","Himachal Pradesh",
  "Jharkhand","Karnataka","Kerala","Madhya Pradesh","Maharashtra","Manipur","Meghalaya","Mizoram","Nagaland",
  "Odisha","Punjab","Rajasthan","Sikkim","Tamil Nadu","Telangana","Tripura","Uttar Pradesh","Uttarakhand","West Bengal",
  "Andaman and Nicobar Islands","Chandigarh","Dadra and Nagar Haveli and Daman and Diu","Delhi","Jammu and Kashmir",
  "Ladakh","Lakshadweep","Puducherry"
];
function inrWords(n){
  const a=["","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"];
  const b=["","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"];
  n = Math.floor(+n||0);
  const two = (x)=> x<20?a[x]:b[Math.floor(x/10)]+(x%10?(" "+a[x%10]):"");
  const three = (x)=> x<100?two(x):(a[Math.floor(x/100)]+" Hundred"+(x%100?(" "+two(x%100)):""));
  const crore=Math.floor(n/1e7), lakh=Math.floor((n%1e7)/1e5), th=Math.floor((n%1e5)/1e3), h=n%1e3;
  return [crore?two(crore)+" Crore":"", lakh?two(lakh)+" Lakh":"", th?two(th)+" Thousand":"", h?three(h):""].filter(Boolean).join(" ")+" Rupees Only";
}

function defaultsFromSettings() {
  const s = CRQQB_SETTINGS || {};
  const today = new Date();
  const y = String(today.getFullYear()).slice(-2);
  const m = String(today.getMonth()+1).padStart(2,'0');
  const defaults = {
    header: { doc_type: 'Quotation', number_label: '', cr_no: `CRQ/${y}${m}${String(today.getDate()).padStart(2,'0')}/0021`, cr_date: today.toISOString().slice(0,10), chip: s.seal_text, place_of_supply: s.place_of_supply, display_currency: 'INR', fx_rate: '' },
    job: {
      job_type: s.default_job_type || 'Re-rubberisation',
      // The selected machine can be a key from the machines list or the
      // sentinel value '__custom__' indicating that the user is
      // specifying their own machine.  The custom machine name is
      // stored separately in custom_machine.
      machine: '',
      model: '',
      rubber_grade: s.default_rubber_grade || '',
      employee_id: '',
      custom_rates: { inking: '', dampening: '' },
      global_rates: { ink: '', damp: '', other: '' },
      // When machine === '__custom__' these fields hold the user
      // provided values.  They remain empty otherwise.
      custom_machine: '',
      custom_model: ''
    },
    customer: { name: '', gstin: '', phone:'', email:'', contact_person:'', billing_address:'', pin:'', country:'India', state:'', state_code:'', shipping_same:true, shipping_address:'' },
    items: [],
    default_rate: 0,
    quote_discount: 0, freight: 0, packaging: 0,
    freight_taxable: true, packaging_taxable: true,
    gst_enabled: true,
    warranty_text: '',
    settings: {
      company: { name: s.company_name, website: s.company_website, office: s.office_address, plant: s.plant_address, branch: s.branch_address, phone: s.company_phone, email: s.company_email, gstin: s.gstin, logo_url: s.logo_url },
      banking: { bank_name: s.bank_name, account_name: s.account_name, account_no: s.account_no, ifsc: s.ifsc, branch: s.branch, upi_id: s.upi_id },
      tax: { mode: s.tax_mode || 'CGST+SGST', percent: +s.tax_percent || 18 },
      labels: { warranty: s.warranty_label || 'Warranty' },
      // Split terms on real newlines so each line becomes its own list item
      terms: (s.terms || '').split(/\r?\n/).filter(Boolean),
      footnote: s.footnote || '',
      print_theme: s.print_theme || 'classic',
      // Pass through signature and designation for the print template
      signature_url: s.signature_url,
      designation: s.designation
    }
  };
  // Override the default document type when the container defines
  // data-default-doc-type.  The alias shortcode sets this attribute
  // so Automatic Invoices start with the correct doc type.
  try {
    const rootEl = document.getElementById('crqqb-root');
    const attr = rootEl && rootEl.parentElement ? rootEl.parentElement.getAttribute('data-default-doc-type') : null;
    if (attr) {
      defaults.header.doc_type = attr;
    }
  } catch (e) {}
  return defaults;
}

function computeTotals(payload) {
  const isRe = payload.job?.job_type === 'Re-rubberisation';
  const defaultRate = +payload.default_rate || 0;
  const globalRates = payload.job?.global_rates || {};

  const subTotal = Math.round(payload.items.reduce((acc, it) => {
    const base = (Number(it.length_mm)||0) * (Number(it.diameter_mm)||0) / 100;
    const unit = (it.unit || 'Inking');
    let effRate;
    if (it.rate === '' || it.rate === undefined || it.rate === null) {
      const u = unit.toLowerCase();
      const gKey = u.startsWith('damp') ? 'damp' : (u.startsWith('ink') ? 'ink' : 'other');
      const gVal = globalRates[gKey];
      if (!(gVal === '' || gVal === undefined || gVal === null)) {
        effRate = Number(gVal) || 0;
      } else {
        effRate = defaultRate;
      }
    } else {
      effRate = Number(it.rate) || 0;
    }
    const line = base * effRate * (Number(it.qty)||0);
    const afterDisc = it.disc_type === '%' ? (line - (line * (Number(it.discount)||0) / 100)) : (line - (Number(it.discount)||0));
    const spindle = isRe ? 0 : (Number(it.spindle)||0);
    const withSpindle = afterDisc + spindle;
    return acc + Math.max(0, withSpindle);
  }, 0) * 100) / 100;

  const freight = Number(payload.freight)||0;
  const packaging = Number(payload.packaging)||0;
  const quoteDisc = Number(payload.quote_discount)||0;

  const taxableCharges = (payload.freight_taxable ? freight : 0) + (payload.packaging_taxable ? packaging : 0);
  const nontaxCharges = (payload.freight_taxable ? 0 : freight) + (payload.packaging_taxable ? 0 : packaging);

  const afterQuoteDisc = Math.max(0, subTotal - quoteDisc);
  const taxable = Math.round((afterQuoteDisc + taxableCharges) * 100) / 100;

  const gstEnabled = !!payload.gst_enabled;
  const taxPct = Number(payload.settings?.tax?.percent)||0;
  const isIGST = (payload.settings?.tax?.mode === 'IGST');

  let tax=0, cgst=0, sgst=0, igst=0;
  if (gstEnabled && taxPct>0) {
    tax = Math.round(taxable * taxPct) / 100;
    if (isIGST) {
      igst = tax;
    } else {
      cgst = Math.round((tax/2) * 100)/100;
      sgst = Math.round((tax/2) * 100)/100;
    }
  }

  const preRound = taxable + (gstEnabled ? tax : 0) + nontaxCharges;
  const grand = Math.round(preRound);
  const roundOff = Math.round((grand - preRound) * 100) / 100;

  return { subTotal, taxable, tax: (gstEnabled?tax:0), cgst, sgst, igst, nontaxCharges, roundOff, grand, words: inrWords(grand) };
}

function App() {
  const [payload, setPayload] = useState(defaultsFromSettings());
  // Pull in data structures from localized CRQQB_VARS.  These objects
  // contain nested machines and models, rubber grade rates, and
  // spindle rates per model defined in the settings.  They may be
  // undefined if not configured.
  const machines = (typeof CRQQB_VARS !== 'undefined' && CRQQB_VARS.machines) || {};
  const rubberGrades = (typeof CRQQB_VARS !== 'undefined' && CRQQB_VARS.rubberGrades) || {};
  const spindleRates = (typeof CRQQB_VARS !== 'undefined' && CRQQB_VARS.spindleRates) || {};
  const totals = useMemo(()=>computeTotals(payload), [payload]);
  const [customerSuggestions, setCustomerSuggestions] = useState([]);
  const [isSavingDoc, setIsSavingDoc] = useState(false);
  const [lastSavedUrl, setLastSavedUrl] = useState('');

  // Ref to ensure that the initial quotation number is fetched only
  // once when the component first renders or when the document type
  // switches back to Quotation.  Without this guard the number would
  // increment repeatedly on each state change.
  const hasFetchedInitialNo = useRef(false);

  useEffect(() => {
    // Automatically fetch the next quotation number on initial load
    // when the document type is Quotation and no custom number has
    // been set yet.  This ensures each new quotation across devices
    // receives a globally unique number without relying on
    // localStorage.
    if (payload.header?.doc_type === 'Quotation' && !hasFetchedInitialNo.current) {
      fetchNextQuoteNumber()
        .then(num => {
          setPayload(p => ({ ...p, header: { ...p.header, cr_no: num } }));
          hasFetchedInitialNo.current = true;
        })
        .catch(err => {
          console.error('Failed to fetch initial quotation number', err);
        });
    }
  }, [payload.header?.doc_type]);


  // Track the previously selected machine and model so that we can
  // detect when the selection changes.  When the machine or model
  // changes the items array should be rebuilt using the dataset; when
  // only the grade, custom rates or job type change we adjust rates
  // and spindle charges in place without overwriting user‑edited HSN
  // values.
  const selectionRef = useRef({ machine: '', model: '' });

  const addRow = ()=> setPayload(p=>{
    const grade = p.job?.rubber_grade || '';
    let rateVal = '';
    // Determine rate for a new row assuming unit is Inking
    if (grade && grade !== 'Custom Rubber' && rubberGrades[grade]) {
      rateVal = rubberGrades[grade]['Inking'] !== undefined ? rubberGrades[grade]['Inking'] : '';
    } else if (grade === 'Custom Rubber') {
      const cr = p.job?.custom_rates || {};
      const inking = cr.inking;
      rateVal = (inking === '' || inking === undefined) ? '' : Number(inking);
    }
    // Determine spindle based on job type and selected model
    const model = p.job?.model || '';
    const spVal = p.job?.job_type === 'Re-rubberisation' ? 0 : (spindleRates[model] || 0);
    // New rows default the HSN code to 84439100 per specification
    const newRow = { unit:'Inking', type:'', hsn:'84439100', qty:1, diameter_mm:0, length_mm:0, rubber_grade: grade, rate: rateVal, discount:0, disc_type:'%', spindle: spVal };
    return { ...p, items: [...p.items, newRow] };
  });
  const delRow = (idx)=> setPayload(p=>({...p, items: p.items.filter((_,i)=>i!==idx)}));

  const saveDocument = ()=>{
    if (!CRQQB_VARS || !CRQQB_VARS.ajax_url) return;
    const data = {...payload, totals};
    setIsSavingDoc(true);
    setLastSavedUrl('');
    const body = new URLSearchParams();
    body.append('action', 'crq_save_document');
    body.append('nonce', CRQQB_VARS.nonce || '');
    body.append('data', JSON.stringify(data));
    fetch(CRQQB_VARS.ajax_url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
      body: body.toString()
    }).then(r=>r.json()).then(resp=>{
      if (resp && resp.success && resp.data && resp.data.view_url) {
        setLastSavedUrl(resp.data.view_url);
      } else {
        console.error('Save failed', resp);
      }
    }).catch(err=>console.error('Save error', err)).finally(()=>setIsSavingDoc(false));
  };
  const updateRow = (idx, key, val)=> setPayload(p=>{
    const items = p.items.slice();
    const row = { ...items[idx] };
    row[key] = val;
    // If unit changes, update rate based on selected grade/custom rates
    if (key === 'unit') {
      const grade = p.job?.rubber_grade || '';
      let newRate = row.rate;
      if (grade && grade !== 'Custom Rubber' && rubberGrades[grade]) {
        const k = val.toString().toLowerCase().startsWith('damp') ? 'Dampening' : 'Inking';
        const gRates = rubberGrades[grade] || {};
        newRate = (gRates[k] !== undefined ? gRates[k] : '');
      } else if (grade === 'Custom Rubber') {
        const cr = p.job?.custom_rates || {};
        const k = val.toString().toLowerCase().startsWith('damp') ? 'dampening' : 'inking';
        const v = cr[k];
        newRate = (v === '' || v === undefined) ? '' : Number(v);
      }
      row.rate = newRate;
    }
    items[idx] = row;
    return { ...p, items };
  });
  const postToPrint = ()=> {
    const w = window.open(CRQQB_VARS?.print_url, '_blank');
    const data = {...payload, totals};
    let tries = 0;
    const send = ()=> {
      try { w.postMessage({type:'CRQ_PAYLOAD', payload: data}, '*'); } catch(e){}
      tries++;
      if (tries<14 && w && !w.closed) setTimeout(send, 250);
    };
    setTimeout(send, 350);
  };

  const gst = parseStateFromGSTIN(payload.customer.gstin||"");

  // Auto‑populate items when the machine/model selection changes and
  // update existing rows when only grade/custom rates/job type change.
  useEffect(() => {
    const m = payload.job?.machine || '';
    const model = payload.job?.model || '';
    const grade = payload.job?.rubber_grade || '';
    const custom = payload.job?.custom_rates || {};
    const globalRates = payload.job?.global_rates || {};
    const jobType = payload.job?.job_type || '';
    const prev = selectionRef.current;
    const changedMachine = (prev.machine !== m) || (prev.model !== model);
    selectionRef.current = { machine: m, model: model };

    // Determine if a dataset exists for the current selection.  When the
    // user selects a custom machine (denoted by '__custom__') or a
    // machine/model that does not appear in the dataset, skip the
    // automatic row rebuild.  In these cases the items array should
    // remain untouched; the user manually adds and edits rows.
    const hasDataset = m && m !== '__custom__' && machines[m] && model && machines[m][model];

    if (hasDataset && changedMachine) {
      // Build a fresh items array from rollers, defaulting HSN and
      // computing rates/spindles based on current grade/custom rates.
      const rollers = machines[m][model] || [];
      const newItems = rollers.map(r => {
        const unit = r.unit || 'Inking';
        let rateVal = '';
        const u = unit.toLowerCase();
        const gKey = u.startsWith('damp') ? 'damp' : (u.startsWith('ink') ? 'ink' : 'other');
        const gVal = globalRates[gKey];
        if (!(gVal === '' || gVal === undefined || gVal === null)) {
          rateVal = Number(gVal) || 0;
        } else if (grade && grade !== 'Custom Rubber' && rubberGrades[grade]) {
          const key = unit.toLowerCase().startsWith('damp') ? 'Dampening' : 'Inking';
          const gRates = rubberGrades[grade] || {};
          rateVal = (gRates[key] !== undefined ? gRates[key] : '');
        } else if (grade === 'Custom Rubber') {
          const key = unit.toLowerCase().startsWith('damp') ? 'dampening' : 'inking';
          const cVal = custom[key];
          rateVal = (cVal === '' || cVal === undefined) ? '' : Number(cVal);
        }
        const spindleVal = jobType === 'Re-rubberisation' ? 0 : (spindleRates[model] || 0);
        return {
          unit: unit,
          type: r.type || '',
          hsn: '84439100',
          qty: r.qty || 0,
          diameter_mm: r.diameter_mm || 0,
          length_mm: r.length_mm || 0,
          rubber_grade: grade || '',
          rate: rateVal,
          discount: 0,
          disc_type: '%',
          spindle: spindleVal
        };
      });
      setPayload(p => ({ ...p, items: newItems }));
    } else {
      // Update rates and spindle charges on existing rows.  Do not
      // overwrite HSN or other user‑edited fields.  This runs for
      // custom machines as well as dataset machines when only grade
      // or other job fields change.
      setPayload(p => {
        const items = p.items.map(row => {
          const unit = row.unit || 'Inking';
          let newRate = row.rate;
          const u = unit.toLowerCase();
          const gKey = u.startsWith('damp') ? 'damp' : (u.startsWith('ink') ? 'ink' : 'other');
          const gVal = globalRates[gKey];
          if (!(gVal === '' || gVal === undefined || gVal === null)) {
            newRate = Number(gVal) || 0;
          } else if (grade && grade !== 'Custom Rubber' && rubberGrades[grade]) {
            const key = unit.toLowerCase().startsWith('damp') ? 'Dampening' : 'Inking';
            const gRates = rubberGrades[grade] || {};
            if (gRates[key] !== undefined) newRate = gRates[key];
          } else if (grade === 'Custom Rubber') {
            const key = unit.toLowerCase().startsWith('damp') ? 'dampening' : 'inking';
            const val = custom[key];
            if (!(val === '' || val === undefined)) newRate = Number(val);
          }
          // Determine spindle based on dataset model when available;
          // custom machines do not have spindle charges unless user
          // enters values manually in the row.  When dataset exists
          // we use the spindleRates map; otherwise leave as is.
          let newSpindle = row.spindle;
          if (hasDataset) {
            newSpindle = jobType === 'Re-rubberisation' ? 0 : (spindleRates[model] || 0);
          } else {
            // For custom machines keep spindle as user entered or zero if re-rubberisation
            if (jobType === 'Re-rubberisation') newSpindle = 0;
          }
          return {
            ...row,
            rubber_grade: grade || '',
            rate: newRate,
            spindle: newSpindle
          };
        });
        return { ...p, items };
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [payload.job.machine, payload.job.model, payload.job.rubber_grade, payload.job.custom_rates, payload.job.job_type]);

  return (
    <div>
      <datalist id="crq-unit-suggestions">
        <option value="Inking" /><option value="Dampening" />
      </datalist>

      {/* Header */}
      <div className="section-title">Header</div>
      <div className="crq-grid">
        <div style={{gridColumn:'span 6 / span 6'}}>
          <label>{payload.header.number_label || (payload.header.doc_type==="Invoice" ? "Invoice No." : (payload.header.doc_type==="Pro Forma Invoice" ? "Pro Forma Invoice No." : "Quotation No."))}</label>
          <div style={{display:"flex", gap:6}}>
            <input className="crq-input" style={{flex:1}} value={payload.header.cr_no} onChange={e=>setPayload(p=>({...p, header:{...p.header, cr_no:e.target.value}}))} />
            <button
              type="button"
              className="crq-btn"
              onClick={async () => {
                try {
                  const num = await fetchNextQuoteNumber();
                  setPayload(p => ({ ...p, header: { ...p.header, cr_no: num } }));
                } catch (e) {
                  console.error('Auto number error', e);
                }
              }}
            >Auto</button>
          </div>
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Document Type</label>
          <select className="crq-select" value={payload.header.doc_type} onChange={e=>setPayload(p=>({...p, header:{...p.header, doc_type:e.target.value}}))}>
            <option>Quotation</option>
            <option>Pro Forma Invoice</option>
            <option>Invoice</option>
          </select>
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Number Label (optional)</label>
          <input className="crq-input" value={payload.header.number_label} onChange={e=>setPayload(p=>({...p, header:{...p.header, number_label:e.target.value}}))} />
        </div>
        <div style={{gridColumn:'span 6 / span 6'}}>
          <label>CR Date</label>
          <input className="crq-input" type="date" value={payload.header.cr_date} onChange={e=>setPayload(p=>({...p, header:{...p.header, cr_date:e.target.value}}))} />
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Header Chip</label>
          <select className="crq-select" value={payload.header.chip} onChange={e=>setPayload(p=>({...p, header:{...p.header, chip:e.target.value}}))}>
            <option>Original for Recipient</option><option>Duplicate</option><option>Triplicate</option>
          </select>
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Place of Supply</label>
          <input className="crq-input" value={payload.header.place_of_supply||''} onChange={e=>setPayload(p=>({...p, header:{...p.header, place_of_supply:e.target.value}}))} />
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Display Currency</label>
          <select className="crq-select"
                  value={payload.header.display_currency||'INR'}
                  onChange={e=>setPayload(p=>({...p, header:{...p.header, display_currency:e.target.value}}))}>
            <option value="INR">INR (₹)</option>
            <option value="USD">USD ($)</option>
            <option value="EUR">EUR (€)</option>
            <option value="GBP">GBP (£)</option>
          </select>
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>FX Rate (1 unit = INR)</label>
          <input className="crq-input" type="number" min="0" step="0.0001"
                 value={payload.header.fx_rate||''}
                 onChange={e=>setPayload(p=>({...p, header:{...p.header, fx_rate:e.target.value}}))} />
        </div>
      </div>

      {/* Customer */}
      <div className="section-title">Customer</div>
      <div className="crq-grid">
        <div style={{gridColumn:'span 6 / span 6'}}>
          <label>M/S</label>
          <input
            className="crq-input"
            value={payload.customer.name||''}
            onChange={e=>{
              const v = e.target.value;
              setPayload(p=>({...p, customer:{...p.customer, name:v}}));
              if (v && v.length >= 2 && CRQQB_VARS && CRQQB_VARS.ajax_url) {
                const params = new URLSearchParams();
                params.append('action', 'crq_search_customers');
                params.append('nonce', CRQQB_VARS.nonce || '');
                params.append('term', v);
                fetch(CRQQB_VARS.ajax_url + '?' + params.toString(), { method:'GET' })
                  .then(r=>r.json())
                  .then(resp=>{
                    if (resp && resp.success && resp.data && Array.isArray(resp.data.items)) {
                      setCustomerSuggestions(resp.data.items);
                    } else {
                      setCustomerSuggestions([]);
                    }
                  })
                  .catch(()=>setCustomerSuggestions([]));
              } else {
                setCustomerSuggestions([]);
              }
            }}
            onBlur={()=>setTimeout(()=>setCustomerSuggestions([]), 200)}
          />
          {customerSuggestions && customerSuggestions.length>0 && (
            <div className="crq-suggestions">
              {customerSuggestions.map(c=>(
                <button
                  key={c.id}
                  type="button"
                  className="crq-suggestion-item"
                  onClick={()=>{
                    setPayload(p=>({
                      ...p,
                      customer:{
                        ...p.customer,
                        name: c.name || '',
                        gstin: c.gstin || '',
                        phone: c.phone || '',
                        email: c.email || '',
                        country: c.country || '',
                        state: c.state || '',
                        state_code: c.state_code || '',
                        billing_address: c.billing_address || '',
                        shipping_address: c.shipping_address || '',
                      }
                    }));
                    setCustomerSuggestions([]);
                  }}
                >
                  {c.name || ''}{c.gstin ? ' — ' + c.gstin : ''}{c.phone ? ' — ' + c.phone : ''}
                </button>
              ))}
            </div>
          )}
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Contact Person</label>
          <input className="crq-input" value={payload.customer.contact_person||''}
                 onChange={e=>setPayload(p=>({...p, customer:{...p.customer, contact_person:e.target.value}}))} />
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Phone</label>
          <input
            className="crq-input"
            type="tel"
            pattern="[0-9+ -]*"
            inputMode="tel"
            value={payload.customer.phone||''}
            onChange={e=>setPayload(p=>({...p, customer:{...p.customer, phone:e.target.value}}))}
          />
        </div>
        <div style={{gridColumn:'span 12 / span 12'}}>
          <label>Billing Address</label>
          <textarea className="crq-textarea" value={payload.customer.billing_address||''}
                    onChange={e=>setPayload(p=>({...p, customer:{...p.customer, billing_address:e.target.value, ...(p.customer.shipping_same ? {shipping_address:e.target.value} : {})}}))} />
        </div>
        <div style={{gridColumn:'span 6 / span 6'}}>
          <label>GSTIN</label>
          <input className="crq-input" value={(payload.customer.gstin||'')}
                 onChange={e=>{ const v=e.target.value.toUpperCase(); const g=parseStateFromGSTIN(v);
                   setPayload(p=>({...p, customer:{...p.customer, gstin:v, state: (g.state||p.customer.state||''), state_code:(g.code||p.customer.state_code||'')}}));
                 }} />
        </div>
        <div style={{gridColumn:'span 6 / span 6'}}>
          <label>State</label>
          <select className="crq-select" value={payload.customer.state||''}
                  onChange={e=>setPayload(p=>({...p, customer:{...p.customer, state:e.target.value}}))}>
            <option value="">Select state</option>
            {INDIA_STATES.map(s=><option key={s} value={s}>{s}</option>)}
          </select>
        </div>

        <div style={{gridColumn:'span 6 / span 6'}}>
          <label>Country</label>
          <input
            className="crq-input"
            value={payload.customer.country||''}
            onChange={e=>setPayload(p=>({...p, customer:{...p.customer, country:e.target.value}}))}
          />
        </div>
        <div style={{gridColumn:'span 12 / span 12', display:'flex', gap:8, alignItems:'center'}}>
          <input id="ship_same" type="checkbox" checked={!!payload.customer.shipping_same}
                 onChange={e=>setPayload(p=>({...p, customer:{...p.customer, shipping_same:e.target.checked, shipping_address: e.target.checked ? (p.customer.billing_address||'') : p.customer.shipping_address}}))} />
          <label htmlFor="ship_same">Shipping same as Billing</label>
        </div>
        <div style={{gridColumn:'span 12 / span 12'}}>
          <label>Shipping Address</label>
          <textarea className="crq-textarea" value={payload.customer.shipping_address||''}
                    onChange={e=>setPayload(p=>({...p, customer:{...p.customer, shipping_address:e.target.value}}))} disabled={!!payload.customer.shipping_same} />
        </div>
      </div>


      {/* Job */}
      <div className="section-title">Job</div>
      <div className="crq-grid">
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Job Type</label>
          <select className="crq-select" value={payload.job.job_type} onChange={e=>setPayload(p=>({...p, job:{...p.job, job_type:e.target.value}}))}>
            <option>New Roller</option><option>Re-rubberisation</option>
          </select>
        </div>
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Machine</label>
          <select
            className="crq-select"
            value={payload.job.machine}
            onChange={e => {
              const val = e.target.value;
              if (val === '__custom__') {
                // Switch into custom machine mode: reset dataset values
                setPayload(p => ({
                  ...p,
                  job: {
                    ...p.job,
                    machine: '__custom__',
                    model: '',
                    custom_machine: '',
                    custom_model: ''
                  }
                }));
              } else {
                setPayload(p => ({
                  ...p,
                  job: {
                    ...p.job,
                    machine: val,
                    model: '',
                    custom_machine: '',
                    custom_model: ''
                  }
                }));
              }
            }}
          >
            <option value="">Select Machine</option>
            {Object.keys(machines).map(m => (<option key={m} value={m}>{m}</option>))}
            <option value="__custom__">Custom Machine</option>
          </select>
        </div>
        {/* When a predefined machine is selected show the model dropdown; when custom machine is selected show text inputs for machine and model */}
        {payload.job.machine !== '__custom__' ? (
          <div style={{gridColumn:'span 3 / span 3'}}>
            <label>Model</label>
            <select
              className="crq-select"
              value={payload.job.model}
              onChange={e => setPayload(p => ({ ...p, job: { ...p.job, model: e.target.value } }))}
              disabled={!payload.job.machine}
            >
              <option value="">Select Model</option>
              {payload.job.machine && machines[payload.job.machine] && Object.keys(machines[payload.job.machine]).map(md => (<option key={md} value={md}>{md}</option>))}
            </select>
          </div>
        ) : (
          <>
            <div style={{gridColumn:'span 3 / span 3'}}>
              <label>Custom Machine Name</label>
              <input
                className="crq-input"
                value={payload.job.custom_machine}
                onChange={e => setPayload(p => ({ ...p, job: { ...p.job, custom_machine: e.target.value } }))}
              />
            </div>
            <div style={{gridColumn:'span 3 / span 3'}}>
              <label>Custom Model Name</label>
              <input
                className="crq-input"
                value={payload.job.custom_model}
                onChange={e => setPayload(p => ({ ...p, job: { ...p.job, custom_model: e.target.value } }))}
              />
            </div>
          </>
        )}
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Rubber Grade</label>
          <select className="crq-select" value={payload.job.rubber_grade} onChange={e=>setPayload(p=>({...p, job:{...p.job, rubber_grade:e.target.value}}))}>
            <option value="">Select Grade</option>
            {Object.keys(rubberGrades).map(g=>(<option key={g} value={g}>{g}</option>))}
            <option value="Custom Rubber">Custom Rubber</option>
          </select>
        </div>
        {/* Custom rate fields appear when user selects "Custom Rubber" */}
        {payload.job.rubber_grade === 'Custom Rubber' && (
          <>
            <div style={{gridColumn:'span 3 / span 3'}}>
              <label>Custom Inking Rate (₹)</label>
              <input className="crq-input" type="number" min="0" step="0.01" value={payload.job.custom_rates?.inking || ''} onChange={e=>setPayload(p=>({ ...p, job:{...p.job, custom_rates:{...p.job.custom_rates, inking: e.target.value} } }))} />
            </div>
            <div style={{gridColumn:'span 3 / span 3'}}>
              <label>Custom Dampening Rate (₹)</label>
              <input className="crq-input" type="number" min="0" step="0.01" value={payload.job.custom_rates?.dampening || ''} onChange={e=>setPayload(p=>({ ...p, job:{...p.job, custom_rates:{...p.job.custom_rates, dampening: e.target.value} } }))} />
            </div>
          </>
        )}
        <div style={{gridColumn:'span 3 / span 3'}}>
          <label>Employee ID</label>
          <input className="crq-input" value={payload.job.employee_id} onChange={e=>setPayload(p=>({...p, job:{...p.job, employee_id:e.target.value}}))} />
        </div>
      </div>

      {/* Global */}
      <div className="section-title">Global</div>
      <div className="crq-grid" style={{marginTop:12, marginBottom:12}}>
        <div style={{gridColumn:'span 4 / span 4'}}>
          <label>Global Inking Rate (₹)</label>
          <input
            className="crq-input"
            type="number"
            min="0"
            step="0.01"
            value={payload.job?.global_rates?.ink ?? ''}
            onChange={e => setPayload(p => ({
              ...p,
              job: {
                ...p.job,
                global_rates: { ...(p.job?.global_rates || {}), ink: e.target.value }
              }
            }))}
          />
        </div>
        <div style={{gridColumn:'span 4 / span 4'}}>
          <label>Global Dampening Rate (₹)</label>
          <input
            className="crq-input"
            type="number"
            min="0"
            step="0.01"
            value={payload.job?.global_rates?.damp ?? ''}
            onChange={e => setPayload(p => ({
              ...p,
              job: {
                ...p.job,
                global_rates: { ...(p.job?.global_rates || {}), damp: e.target.value }
              }
            }))}
          />
        </div>
        <div style={{gridColumn:'span 4 / span 4'}}>
          <label>Global Other Rate (₹)</label>
          <input
            className="crq-input"
            type="number"
            min="0"
            step="0.01"
            value={payload.job?.global_rates?.other ?? ''}
            onChange={e => setPayload(p => ({
              ...p,
              job: {
                ...p.job,
                global_rates: { ...(p.job?.global_rates || {}), other: e.target.value }
              }
            }))}
          />
        </div>
      </div>

      {/* Items */}
      <div className="section-title">Items</div>
      <div className="crq-table-wrap">
        <table>
          <thead>
            <tr>
              <th>#</th>
              <th>Unit</th>
              <th>Type</th>
              <th>HSN</th>
              <th>Qty</th>
              <th>Dia (mm)</th>
              <th>R.L. (mm)</th>
              <th>Rate (₹)</th>
              <th>Amount (₹)</th>
              <th>Disc</th>
              <th>Disc Type</th>
              {payload.job?.job_type==="Re-rubberisation" ? null : <th>Spindle (₹)</th>}
              <th></th>
            </tr>
          </thead>
          <tbody>
            {payload.items.map((it, idx)=>{
              const isRe = payload.job?.job_type === 'Re-rubberisation';
              const base = (Number(it.length_mm)||0) * (Number(it.diameter_mm)||0) / 100;
              const qty = Number(it.qty)||0;
              const effRate = (it.rate === '' || it.rate === undefined || it.rate === null)
                ? (+payload.default_rate || 0)
                : (Number(it.rate)||0);
              const lineBase = base * effRate * qty;
              const disc = Number(it.discount)||0;
              const discType = (it.disc_type || '%');
              const afterDisc = discType === '%'
                ? (lineBase - (lineBase * disc / 100))
                : (lineBase - disc);
              const spindle = isRe ? 0 : (Number(it.spindle)||0);
              const lineTotal = Math.max(0, afterDisc + spindle);
              return (
                <tr key={idx}>
                  <td>{idx+1}</td>
                  <td><input list="crq-unit-suggestions" className="crq-input" value={it.unit||''} onChange={e=>updateRow(idx,'unit', e.target.value)} /></td>
                  <td><input className="crq-input" value={it.type||''} onChange={e=>updateRow(idx,'type', e.target.value)} /></td>
                  <td><input className="crq-input" value={it.hsn||''} onChange={e=>updateRow(idx,'hsn', e.target.value)} /></td>
                  <td><input className="crq-input" type="number" min="0" value={it.qty||0} onChange={e=>updateRow(idx,'qty', +e.target.value||0)} /></td>
                  <td><input className="crq-input" type="number" min="0" value={it.diameter_mm||0} onChange={e=>updateRow(idx,'diameter_mm', +e.target.value||0)} /></td>
                  <td><input className="crq-input" type="number" min="0" value={it.length_mm||0} onChange={e=>updateRow(idx,'length_mm', +e.target.value||0)} /></td>
                  <td><input className="crq-input" type="number" min="0" step="0.01" value={(it.rate===''||it.rate===undefined)?'':it.rate} onChange={e=>updateRow(idx,'rate', e.target.value===''?'':(+e.target.value||0))} /></td>
                  <td className="num">{fmt2(lineTotal)}</td>
                  <td><input className="crq-input" type="number" min="0" value={it.discount||0} onChange={e=>updateRow(idx,'discount', +e.target.value||0)} /></td>
                  <td>
                    <select className="crq-select" value={it.disc_type||'%'} onChange={e=>updateRow(idx,'disc_type', e.target.value)}>
                      <option value="%">%</option><option value="₹">₹</option>
                    </select>
                  </td>
                  <td><input className="crq-input" type="number" min="0" step="0.01" disabled={isRe} value={isRe?0:(it.spindle||0)} onChange={e=>updateRow(idx,'spindle', +e.target.value||0)} /></td>
                  <td><button className="crq-btn secondary" onClick={()=>delRow(idx)}>Del</button></td>
                </tr>
              );
            })}          </tbody>
          <tfoot>
            <tr>
              <td colSpan="13" className="sticky-bar">
                <div className="actions">
                  <button className="crq-btn" onClick={addRow}>+ Add Row</button>
                  <button className="crq-btn secondary" onClick={()=>navigator.clipboard.writeText(JSON.stringify(payload,null,2))}>Copy JSON</button>
                </div>
                <div className="actions">
                  <button className="crq-btn secondary" disabled={isSavingDoc} onClick={saveDocument}>
                    {isSavingDoc ? 'Saving…' : 'Save Quotation'}
                  </button>
                  <button className="crq-btn" onClick={postToPrint}>Print / Download</button>
                </div>
              </td>
            </tr>
          </tfoot>
        </table>
      </div>
      {lastSavedUrl && (
        <div className="crq-grid" style={{marginTop:8}}>
          <div style={{gridColumn:'span 12 / span 12', fontSize:12}}>
            Last saved quotation URL:&nbsp;
            <a href={lastSavedUrl} target="_blank" rel="noreferrer">{lastSavedUrl}</a>
          </div>
        </div>
      )}

      {/* Totals & Flags */}
      <div className="section-title">Totals</div>
      <div className="crq-grid">
        <div style={{gridColumn:'span 3 / span 3'}}><label>Quote Discount (₹)</label><input className="crq-input" type="number" min="0" step="0.01" value={payload.quote_discount} onChange={e=>setPayload(p=>({...p, quote_discount:+e.target.value||0}))} /></div>
        <div style={{gridColumn:'span 3 / span 3'}}><label>Freight (₹)</label><input className="crq-input" type="number" min="0" step="0.01" value={payload.freight} onChange={e=>setPayload(p=>({...p, freight:+e.target.value||0}))} /></div>
        <div style={{gridColumn:'span 3 / span 3'}}><label>Packaging (₹)</label><input className="crq-input" type="number" min="0" step="0.01" value={payload.packaging} onChange={e=>setPayload(p=>({...p, packaging:+e.target.value||0}))} /></div>
        <div style={{gridColumn:'span 3 / span 3', display:'flex', gap:12, alignItems:'end'}}>
          <label><input type="checkbox" checked={payload.freight_taxable} onChange={e=>setPayload(p=>({...p, freight_taxable:e.target.checked}))}/> Freight taxable</label>
          <label><input type="checkbox" checked={payload.packaging_taxable} onChange={e=>setPayload(p=>({...p, packaging_taxable:e.target.checked}))}/> Packaging taxable</label>
          <label><input type="checkbox" checked={payload.gst_enabled} onChange={e=>setPayload(p=>({...p, gst_enabled:e.target.checked}))}/> GST Enabled</label>
        </div>
      </div>

      <div className="crq-grid" style={{marginTop:8}}>
        <div style={{gridColumn:'span 4 / span 4'}} className="small">Sub Total: ₹ {fmt2(totals.subTotal)}</div>
        <div style={{gridColumn:'span 4 / span 4'}} className="small">Taxable Total: ₹ {fmt2(totals.taxable)}</div>
        <div style={{gridColumn:'span 4 / span 4'}} className="small">Non-taxable Charges: ₹ {fmt2(totals.nontaxCharges)}</div>
      </div>
      <div className="crq-grid">
        {payload.settings.tax.mode==='IGST'
          ? (<div style={{gridColumn:'span 4 / span 4'}}>IGST ({payload.settings.tax.percent}%): ₹ {fmt2(totals.igst)}</div>)
          : (<>
               <div style={{gridColumn:'span 4 / span 4'}}>CGST ({payload.settings.tax.percent/2}%): ₹ {fmt2(totals.cgst)}</div>
               <div style={{gridColumn:'span 4 / span 4'}}>SGST ({payload.settings.tax.percent/2}%): ₹ {fmt2(totals.sgst)}</div>
             </>)
        }
        <div style={{gridColumn:'span 4 / span 4'}}>Round-off: ₹ {fmt2(totals.roundOff)}</div>
      </div>
      <div className="crq-grid">
        <div style={{gridColumn:'span 12 / span 12', fontSize:18, fontWeight:600}}>Grand Total: ₹ {fmt2(totals.grand)}</div>
        <div style={{gridColumn:'span 12 / span 12'}} className="small">Amount in words: {totals.words}</div>
      </div>

      {/* Warranty */}
      <div className="section-title">{payload.settings.labels.warranty}</div>
      <textarea className="crq-textarea" placeholder="Write warranty terms for THIS quotation (shows on print)" value={payload.warranty_text} onChange={e=>setPayload(p=>({...p, warranty_text:e.target.value}))} />
    </div>
  );
}

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