// Pricing engine — linear-foot driven with side-panel exceptions
// All prices flow from these defaults; admin can edit them live.

const DEFAULT_PRICING = {
  // Core linear-foot rates
  linear_ft_rate:     { label: 'Standard linear foot rate',  unit: 'per lin. ft', price: 145, note: 'Covers face frames, doors, drawers, shelves, refinishing — the bulk of the work.' },
  toe_kick_rate:      { label: 'Toe kick',                   unit: 'per lin. ft', price: 38,  note: 'Toe kick fabrication & install per linear foot.' },

  // Per-side finished panels (the exception to the linear-ft model)
  side_panel_one:     { label: 'Finished side panel — single (L or R)', unit: 'per cabinet', price: 185, note: 'One finished end panel.' },
  side_panel_both:    { label: 'Finished side panels — both ends',      unit: 'per cabinet', price: 320, note: 'Both ends finished.' },

  // Surcharges (multipliers, applied to linear-ft subtotal)
  rush_surcharge_pct: { label: 'Rush / priority surcharge',  unit: '% of subtotal', price: 15, note: 'Applied when priority is ASAP or 2 weeks.' },
  island_surcharge_pct:{ label: 'Island / peninsula surcharge', unit: '% of cabinet line', price: 10, note: 'Applied per cabinet flagged Island or Peninsula.' },

  // Material multipliers (applied to that cabinet's linear-ft line)
  mat_birch:          { label: 'Birch plywood',     unit: 'multiplier', price: 1.00, note: 'Baseline.' },
  mat_maple:          { label: 'Hardrock maple',    unit: 'multiplier', price: 1.18 },
  mat_maple_ply:      { label: 'Maple plywood',     unit: 'multiplier', price: 1.10 },
  mat_cherry:         { label: 'Cherry plywood',    unit: 'multiplier', price: 1.22 },
  mat_oak:            { label: 'Oak plywood',       unit: 'multiplier', price: 1.08 },
  mat_walnut:         { label: 'Walnut plywood',    unit: 'multiplier', price: 1.30 },
  mat_melamine_white: { label: 'Melamine — white',  unit: 'multiplier', price: 0.85 },
  mat_melamine_wood:  { label: 'Melamine — wood-look', unit: 'multiplier', price: 0.90 },
  mat_mdf:            { label: 'MDF',               unit: 'multiplier', price: 0.80 },
  mat_particle:       { label: 'Particle board',    unit: 'multiplier', price: 0.75 },
  mat_other:          { label: 'Other / custom',    unit: 'multiplier', price: 1.00 },

  // Flat fees
  trip_charge:        { label: 'Trip charge',  unit: 'flat', price: 95 },
  minimum_job:        { label: 'Minimum job',  unit: 'flat', price: 350 },
  tax_rate_pct:       { label: 'Tax rate',     unit: '% of subtotal', price: 0 },
};

// Map BOX_MATERIALS dropdown labels → pricing keys
const MATERIAL_KEY_MAP = {
  'Birch plywood': 'mat_birch',
  'Hardrock maple': 'mat_maple',
  'Maple plywood': 'mat_maple_ply',
  'Cherry plywood': 'mat_cherry',
  'Oak plywood': 'mat_oak',
  'Walnut plywood': 'mat_walnut',
  'Melamine — white': 'mat_melamine_white',
  'Melamine — wood-look': 'mat_melamine_wood',
  'MDF': 'mat_mdf',
  'Particle board': 'mat_particle',
  'Other': 'mat_other',
};

// Convert a dimension value+unit to inches
function toInches(val, unit) {
  const v = parseFloat(val);
  if (!v || isNaN(v)) return 0;
  if (unit === 'mm') return v / 25.4;
  return v;
}

// Billable linear feet for a single cabinet:
// Use the cabinet's width in feet as the spine, then add component
// uplifts so a wide cabinet with lots of doors/drawers prices more
// than a wide empty box.
function cabinetLinearFt(cab) {
  const wIn = toInches(cab.w, cab.wu);
  const widthFt = wIn / 12;
  if (!widthFt) return 0;

  const doors = parseInt(cab.doors) || 0;
  const drawers = parseInt(cab.drawers) || 0;
  const shelves = parseInt(cab.shelves) || 0;

  // Component uplifts in linear-foot equivalents
  const componentLF = (doors * 0.5) + (drawers * 0.4) + (shelves * 0.25);

  return widthFt + componentLF;
}

// Compute the full estimate for an order
function computeEstimate(data, pricing) {
  const cabinets = data.cabinets || [];
  const tk = data.toeKick || {};
  const linePrice = pricing.linear_ft_rate?.price || 0;
  const tkPrice = pricing.toe_kick_rate?.price || 0;
  const islandPct = (pricing.island_surcharge_pct?.price || 0) / 100;
  const rushPct = (pricing.rush_surcharge_pct?.price || 0) / 100;
  const taxPct = (pricing.tax_rate_pct?.price || 0) / 100;

  const lineItems = [];
  let subtotal = 0;

  // Per-cabinet line items
  for (let i = 0; i < cabinets.length; i++) {
    const c = cabinets[i];
    const lf = cabinetLinearFt(c);
    const matKey = MATERIAL_KEY_MAP[c.boxMaterial];
    const mult = matKey && pricing[matKey] ? pricing[matKey].price : 1;

    let cabBase = lf * linePrice * mult;
    let islandUplift = 0;
    if (c.cabType === 'Island' || c.cabType === 'Peninsula') {
      islandUplift = cabBase * islandPct;
    }
    const cabTotal = cabBase + islandUplift;

    lineItems.push({
      type: 'cabinet',
      label: `Cab ${String(i + 1).padStart(2, '0')}${c.name ? ' — ' + c.name : ''}`,
      detail: `${lf.toFixed(2)} lin. ft × $${linePrice}${mult !== 1 ? ` × ${mult.toFixed(2)} (${c.boxMaterial})` : ''}${islandUplift > 0 ? ` + ${(islandPct * 100).toFixed(0)}% ${c.cabType.toLowerCase()}` : ''}`,
      qty: lf, rate: linePrice * mult, amount: cabTotal,
    });
    subtotal += cabTotal;

    // Finished side panel(s) — separate line
    if (c.finishedSide === 'Yes' && c.finishedWhich) {
      const isBoth = c.finishedWhich === 'Both';
      const sp = isBoth ? pricing.side_panel_both : pricing.side_panel_one;
      if (sp) {
        lineItems.push({
          type: 'side_panel',
          label: `↳ Finished side — ${c.finishedWhich}`,
          detail: sp.label,
          qty: 1, rate: sp.price, amount: sp.price,
        });
        subtotal += sp.price;
      }
    }
  }

  // Toe kick line
  const tkFt = parseFloat(tk.linearFt) || 0;
  if (tkFt > 0) {
    const tkAmount = tkFt * tkPrice;
    lineItems.push({
      type: 'toe_kick',
      label: 'Toe kick',
      detail: `${tkFt} lin. ft × $${tkPrice}${tk.thickness ? ` · ${tk.thickness}` : ''}`,
      qty: tkFt, rate: tkPrice, amount: tkAmount,
    });
    subtotal += tkAmount;
  }

  // Trip charge
  const trip = pricing.trip_charge?.price || 0;
  if (subtotal > 0 && trip > 0) {
    lineItems.push({ type: 'fee', label: 'Trip charge', detail: 'Flat fee', qty: 1, rate: trip, amount: trip });
    subtotal += trip;
  }

  // Rush surcharge
  let rushAmount = 0;
  if (subtotal > 0 && (data.timeframe === 'asap' || data.timeframe === '2wk')) {
    rushAmount = subtotal * rushPct;
    if (rushAmount > 0) {
      lineItems.push({
        type: 'surcharge',
        label: 'Rush / priority',
        detail: `${(rushPct * 100).toFixed(0)}% of subtotal`,
        qty: 1, rate: rushAmount, amount: rushAmount,
      });
      subtotal += rushAmount;
    }
  }

  // Minimum job
  const minimum = pricing.minimum_job?.price || 0;
  let minimumApplied = 0;
  if (subtotal > 0 && subtotal < minimum) {
    minimumApplied = minimum - subtotal;
    lineItems.push({
      type: 'fee',
      label: 'Minimum job adjustment',
      detail: `Brings total to $${minimum} minimum`,
      qty: 1, rate: minimumApplied, amount: minimumApplied,
    });
    subtotal = minimum;
  }

  // Tax
  let tax = 0;
  if (taxPct > 0 && subtotal > 0) {
    tax = subtotal * taxPct;
  }

  const total = subtotal + tax;

  return {
    lineItems,
    subtotal: Math.round(subtotal * 100) / 100,
    tax: Math.round(tax * 100) / 100,
    total: Math.round(total * 100) / 100,
    rushApplied: rushAmount > 0,
    minimumApplied: minimumApplied > 0,
  };
}

function fmtMoney(n) {
  if (n == null || isNaN(n)) return '$0';
  return '$' + Math.round(n).toLocaleString();
}

Object.assign(window, { DEFAULT_PRICING, MATERIAL_KEY_MAP, cabinetLinearFt, computeEstimate, fmtMoney, toInches });
