/* Step: Rates & Campaign Order (media-order builder).
 * The client picks a length (:30/:60) and, per daypart, spots per day-of-week (Mon-Sun).
 * Line cost = (spots-per-week x occurrences of that weekday across the FLIGHT dates) x unit rate.
 * Grand total sums every line, live. NO reach / frequency / Nielsen — only dayparts, length, spots,
 * unit rate, total cost. Rates come from window.RATE_CARDS (rate-cards.json); stations without a
 * card show "Rates coming soon" (never invented prices). Dayparts are English labels from the JSON.
 */
const { useState: useStateO, useEffect: useEffectO } = React;

// --- pure calc helpers (uniquely named to avoid cross-file global collisions) ---
function rcParseISO(s){ const [y,m,d]=s.split('-').map(Number); return new Date(y,m-1,d); }
const RC_DOW = ['sun','mon','tue','wed','thu','fri','sat'];          // index by Date.getDay()
const RC_DAYCOLS = [['mon','Mo'],['tue','Tu'],['wed','We'],['thu','Th'],['fri','Fr'],['sat','Sa'],['sun','Su']];
const RC_APPLIC = { weekday:['mon','tue','wed','thu','fri'], weekend:['sat','sun'] };

// How many of each weekday fall inside the flight window (drives the auto-calc off the chosen dates).
function rcCountDows(startISO, endISO){
  const res = {mon:0,tue:0,wed:0,thu:0,fri:0,sat:0,sun:0};
  if(!startISO || !endISO) return res;
  const s = rcParseISO(startISO), e = rcParseISO(endISO);
  if(e < s) return res;
  for(let t = new Date(s); t <= e; t.setDate(t.getDate()+1)) res[RC_DOW[t.getDay()]]++;
  return res;
}

// Added Value: for every 25 PAID spots the client buys, they get 5 FREE spots.
//   freeSpots = floor(totalPaidSpots / 25) * 5   (NOT per-week, NOT × weeks — that old $500 rule is gone)
// The free spots air in the SAME dayparts the client bought, split proportionally to each daypart's paid
// spots using the largest-remainder method (integers that sum exactly to freeSpots). Cost is always $0.
function rcAddedValue(stations){
  const byDp = {}; let totalPaid = 0;
  stations.forEach(function(st){ st.lines.forEach(function(l){
    if(!byDp[l.id]) byDp[l.id] = { id:l.id, label:l.label, paid:0 };
    byDp[l.id].paid += l.totalSpots; totalPaid += l.totalSpots;
  }); });
  const free = Math.floor(totalPaid / 25) * 5;
  let lines = [];
  if(free > 0 && totalPaid > 0){
    const dps = Object.keys(byDp).map(function(k){ return byDp[k]; });
    lines = dps.map(function(d){ const exact = (d.paid / totalPaid) * free;
      return { id:d.id, label:d.label, spots:Math.floor(exact), rate:0, cost:0, _rem:exact - Math.floor(exact) }; });
    let left = free - lines.reduce(function(a,l){ return a + l.spots; }, 0);   // remainder to hand out
    lines.slice().sort(function(a,b){ return b._rem - a._rem; }).forEach(function(l){ if(left > 0){ l.spots++; left--; } });
    lines = lines.filter(function(l){ return l.spots > 0; }).map(function(l){ return { id:l.id, label:l.label, spots:l.spots, rate:0, cost:0 }; });
  }
  return { totalPaidSpots: totalPaid, freeSpots: free, qualifies: free > 0, lines: lines };
}

// Build the full order: per-station lines + subtotals + grand total. Returns numbers only.
function rcComputeOrder(order, selIds){
  const rc = window.RATE_CARDS; const out = { stations:[], grandTotal:0, totalSpots:0 };
  if(!rc) return out;
  const length = (order && order.length) || ':30';
  const dows = rcCountDows(order && order.startDate, order && order.endDate);
  selIds.forEach(function(sid){
    const card = rc.cards[sid]; if(!card) return;                    // uncarded handled separately
    const rateRow = card.rates[length] || {};
    const spotsForStation = (order.spots && order.spots[sid]) || {};
    const lines = []; let subtotal = 0, subSpots = 0;
    rc.dayparts.forEach(function(dp){
      const line = spotsForStation[dp.id] || {};
      const applic = RC_APPLIC[dp.days] || [];
      let perWeek = 0, totalSpots = 0;
      applic.forEach(function(day){ const n = +line[day] || 0; perWeek += n; totalSpots += n * dows[day]; });
      if(perWeek === 0) return;                                       // skip empty lines
      const rate = +rateRow[dp.id] || 0;
      const cost = totalSpots * rate;
      lines.push({ id:dp.id, label:dp.label, days:dp.days, perWeek:perWeek, totalSpots:totalSpots, rate:rate, cost:cost });
      subtotal += cost; subSpots += totalSpots;
    });
    // ROTATION (ROS): a flat number of spots that run anytime in the range, at one lower rate. Not per-day.
    const rot = card.rotation;
    const rotSpots = Math.max(0, parseInt((order.rotation && order.rotation[sid]) || 0, 10) || 0);
    if(rot && rotSpots > 0){
      const rate = +(rot.rates[length]) || 0;
      const cost = rotSpots * rate;
      lines.push({ id:'rotation', label:rot.label, days:'ros', perWeek:0, totalSpots:rotSpots, rate:rate, cost:cost, isRotation:true });
      subtotal += cost; subSpots += rotSpots;
    }
    out.stations.push({ id:sid, name:card.station, call:card.call, lines:lines, subtotal:subtotal, totalSpots:subSpots });
    out.grandTotal += subtotal; out.totalSpots += subSpots;
  });
  // Added value is derived from total PAID spots (cost $0, not added to grandTotal).
  out.addedValue = rcAddedValue(out.stations);
  out.bonusSpots = out.addedValue.freeSpots;
  return out;
}
window.rcComputeOrder = rcComputeOrder;   // reused by app.jsx (archive) so Mis Campañas/Facturación get the total

function StepOrder({ data, set }){
  const I = window.Icons; const T = window.T; const M = window.fmtMoney;
  const [, bump] = useStateO(0);
  useEffectO(function(){ if(!window.RATE_CARDS) window.loadRateCards().then(function(){ bump(function(n){return n+1;}); });
                         if(!window.STATIONS_BY_ID) window.loadStations().then(function(){ bump(function(n){return n+1;}); }); }, []);
  const rc = window.RATE_CARDS;

  const selIds = Object.keys(data.stations||{}).filter(function(id){ return data.stations[id]; });
  const byId = window.STATIONS_BY_ID || {};

  // Order state lives on the campaign object; flight dates are mirrored in so the calc reacts to them.
  const order = Object.assign({ length:':30', spots:{}, rotation:{} }, data.order || {},
                              { startDate:data.startDate, endDate:data.endDate });
  const length = order.length;
  const setOrder = function(patch){ set({ order: Object.assign({}, order, patch) }); };
  const setLength = function(l){ setOrder({ length:l }); };
  const setSpot = function(sid, dpId, day, val){
    const v = Math.max(0, parseInt(val,10) || 0);
    const spots = Object.assign({}, order.spots);
    const st = Object.assign({}, spots[sid]);
    const line = Object.assign({}, st[dpId]);
    line[day] = v; st[dpId] = line; spots[sid] = st;
    setOrder({ spots: spots });
  };
  const setRot = function(sid, val){
    const v = Math.max(0, parseInt(val,10) || 0);
    const rotation = Object.assign({}, order.rotation); rotation[sid] = v;
    setOrder({ rotation: rotation });
  };

  // VENDEDOR: sin acceso a tarifas de costo/márgenes por emisora — solo precios de paquete.
  if(window.RAauth && window.RAauth.isSeller){
    const es = window.i18n && window.i18n.lang==='es';
    return <div className="card step-fade"><div className="step-head">
      <h2>{T('camp.order.title')}</h2>
      <p>{es?'Los paquetes tienen precio fijo ($750 / $1,500). Las tarifas por emisora las maneja el administrador.':'Packages are fixed-price ($750 / $1,500). Per-station rates are managed by the administrator.'}</p>
    </div></div>;
  }
  // ─────────────────────────────────────────────────────────────────────────────────────────────
  // REGLA ABSOLUTA: paquetes y dayparts NO se mezclan. El flujo de PAQUETE nunca ve el constructor de
  // dayparts ni tarifas por franja — su pauta es FIJA por contrato (ROS L-D 7a-10p, 30 días, precio fijo).
  // Se decide por el MODO EXPLÍCITO del wizard (data.mode), no por inferencia. El constructor de dayparts
  // es exclusivo de PAUTA A MEDIDA (StepCustomQuote, paso 3, que termina ahí y no llega aquí).
  if(data.mode !== 'custom'){
    const es2 = window.i18n && window.i18n.lang==='es';
    const spec = (window.getPackages()||[]).find(function(p){ return p.id===data.pkg; });
    const spots = spec ? spec.spots : 0;
    const paid = spec ? spec.spotsPaid : 0;
    const free = spec ? spec.spotsFree : 0;
    const price = spec ? spec.price : 0;
    const names = selIds.map(function(id){ return (byId[id] && (byId[id].name||byId[id].call)) || id; });
    const row = function(label, val){ return (
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'10px 0',borderTop:'1px solid var(--border,#e8eaec)'}}>
        <span className="tiny" style={{fontWeight:700,color:'var(--muted,#5b626f)'}}>{label}</span>
        <b style={{fontSize:14}}>{val}</b></div>); };
    return (
      <div className="card step-fade">
        <div className="step-head">
          <div className="eyebrow">{T('camp.order.eyebrow')}</div>
          <h2>{es2?'Tu paquete':'Your package'}</h2>
          <p>{es2?'Los paquetes tienen una pauta fija por contrato. La emisora distribuye los spots en rotación (ROS) — no eliges franjas.':'Packages have a fixed contracted schedule. The station distributes the spots in rotation (ROS) — you don’t pick dayparts.'}</p>
        </div>
        <div style={{maxWidth:560,margin:'0 auto'}}>
          {/* Resumen destacado */}
          <div style={{background:'var(--green-tint,#f0fdf4)',border:'1px solid #bbf7d0',borderRadius:14,padding:'16px 18px',marginBottom:14,textAlign:'center'}}>
            <div style={{fontSize:26,fontWeight:800,color:'var(--green-3,#15803d)'}}>{spots} {es2?'spots':'spots'} · :30</div>
            <div className="tiny" style={{marginTop:4,fontWeight:700}}>{es2?'Rotación Lun–Dom 7am–10pm · 30 días':'Rotation Mon–Sun 7am–10pm · 30 days'}</div>
          </div>
          <div style={{background:'#fafbfa',border:'1px solid var(--border,#e8eaec)',borderRadius:12,padding:'4px 16px 12px'}}>
            {row(es2?'Paquete':'Package', spec?spec.name:'—')}
            {row(es2?'Spots':'Spots', paid+' '+(es2?'pagados':'paid')+' + '+free+' '+(es2?'gratis':'free')+' = '+spots)}
            {row(es2?'Duración (:30)':'Length (:30)', ':30 '+(es2?'segundos':'seconds'))}
            {row(es2?'Rotación':'Rotation', es2?'ROS · Lun–Dom 7:00a–10:00p':'ROS · Mon–Sun 7:00a–10:00p')}
            {row(es2?'Vigencia':'Flight', '30 '+(es2?'días':'days'))}
            {row(es2?'Emisora(s)':'Station(s)', names.length?names.join(', '):(es2?'—':'—'))}
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'12px 0 4px',borderTop:'2px solid var(--border,#e8eaec)',marginTop:2}}>
              <b style={{color:'var(--green-3,#15803d)'}}>{es2?'Precio del paquete':'Package price'}</b>
              <b style={{fontSize:22,color:'var(--green-3,#15803d)'}}>{'$'+Number(price).toLocaleString('en-US')}</b>
            </div>
          </div>
          <div className="tiny" style={{marginTop:12,color:'var(--muted-2,#8b919c)',display:'flex',alignItems:'center',gap:7,justifyContent:'center'}}>
            <I.lock w={13}/> {es2?'Pauta fija — no editable. El pago se realiza en el siguiente paso.':'Fixed schedule — not editable. Payment happens in the next step.'}
          </div>
        </div>
      </div>
    );
  }

  if(!rc) return <div className="card step-fade"><div className="step-head"><h2>{T('camp.order.title')}</h2><p>{T('camp.order.loading')}</p></div></div>;

  const carded = selIds.filter(function(id){ return rc.cards[id]; });
  const uncarded = selIds.filter(function(id){ return !rc.cards[id]; });
  const computed = rcComputeOrder(order, selIds);
  const flight = (data.startDate && data.endDate)
    ? (window.fmtDateISO ? window.fmtDateISO(data.startDate)+' – '+window.fmtDateISO(data.endDate) : data.startDate+' – '+data.endDate)
    : '—';

  const rateOf = function(sid, dpId){ const c=rc.cards[sid]; return (c && c.rates[length] && c.rates[length][dpId]) || 0; };

  return (
    <div className="card step-fade">
      <div className="step-head">
        <div className="eyebrow">{T('camp.order.eyebrow')}</div>
        <h2>{T('camp.order.title')}</h2>
        <p>{T('camp.order.sub')}</p>
      </div>

      {/* order header */}
      <div className="rc-orderhead">
        <div><span className="tiny">{T('camp.order.campaign')}</span><b>{data.name || T('camp.review.untitled')}</b></div>
        <div><span className="tiny">{T('camp.order.flight')}</span><b>{flight}</b></div>
        <div><span className="tiny">{T('camp.order.stations')}</span><b>{selIds.length}</b></div>
      </div>

      {/* length selector */}
      <div className="rc-lenrow">
        <span className="tiny" style={{fontWeight:700}}>{T('camp.order.length')}</span>
        {rc.lengths.map(function(l){
          return <button key={l} className={"rc-lenbtn"+(length===l?' on':'')} onClick={function(){ setLength(l); }}>{l} {T('camp.order.sec')}</button>;
        })}
      </div>

      {carded.length===0 && (
        <div className="rc-empty tiny">{T('camp.order.noCard')}</div>
      )}

      {/* per-station schedule grid */}
      {carded.map(function(sid){
        const card = rc.cards[sid];
        const stComp = computed.stations.find(function(s){ return s.id===sid; }) || { subtotal:0, totalSpots:0 };
        return (
          <div key={sid} className="rc-station">
            <div className="rc-sthead">
              <div><b>{card.station}</b> <span className="tiny">· {card.call} · {(byId[sid]&&byId[sid].dial)||''} FM</span></div>
              {/* Tarifas ESTIMADAS (regla PM): visibles como estimadas hasta negociar con cada emisora. */}
              {card.estimated
                ? <div className="rc-badge" style={{background:'#fef3c7',color:'#92400e'}}>{(window.i18n&&window.i18n.lang==='es')?'Tarifas estimadas':'Estimated rates'}</div>
                : <div className="rc-badge">{T('camp.order.hasCard')}</div>}
            </div>
            <div className="rc-tablewrap">
              <table className="rc-table">
                <thead>
                  <tr>
                    <th className="l">{T('camp.order.daypart')}</th>
                    {RC_DAYCOLS.map(function(d){ return <th key={d[0]}>{d[1]}</th>; })}
                    <th>{T('camp.order.rate')}</th>
                    <th>{T('camp.order.spots')}</th>
                    <th className="r">{T('camp.order.total')}</th>
                  </tr>
                </thead>
                <tbody>
                  {rc.dayparts.map(function(dp){
                    const applic = RC_APPLIC[dp.days] || [];
                    const spotsLine = ((order.spots[sid]||{})[dp.id]) || {};
                    const compLine = (stComp.lines||[]).find(function(x){ return x.id===dp.id; });
                    const rate = rateOf(sid, dp.id);
                    return (
                      <tr key={dp.id}>
                        <td className="l"><b>{dp.label}</b> <span className="rc-ratechip">{M(rate)}<span className="rc-per">/{T('camp.order.perSpot')}</span></span></td>
                        {RC_DAYCOLS.map(function(d){
                          const on = applic.indexOf(d[0])>=0;
                          return (
                            <td key={d[0]}>
                              {on
                                ? <input type="number" min="0" className="rc-inp" value={spotsLine[d[0]]!=null?spotsLine[d[0]]:''}
                                    placeholder="0" onChange={function(e){ setSpot(sid, dp.id, d[0], e.target.value); }}/>
                                : <span className="rc-na">·</span>}
                            </td>
                          );
                        })}
                        <td>{M(rate)}</td>
                        <td>{compLine?compLine.totalSpots:0}</td>
                        <td className="r"><b>{M(compLine?compLine.cost:0)}</b></td>
                      </tr>
                    );
                  })}
                </tbody>
                <tfoot>
                  <tr>
                    <td className="l" colSpan={8}>{T('camp.order.subtotal')} — {card.station}</td>
                    <td>{stComp.totalSpots}</td>
                    <td className="r"><b>{M(stComp.subtotal)}</b></td>
                  </tr>
                </tfoot>
              </table>
            </div>
            {card.rotation && (
              <div className="rc-rotrow">
                <div className="rc-rot-l">
                  <span className="rc-rosbadge">{T('camp.order.ros')}</span>
                  <div>
                    <b>{card.rotation.label}</b>
                    <div className="tiny">{T('camp.order.rotationSub')}</div>
                  </div>
                </div>
                <div className="rc-rot-r">
                  <span className="rc-ratechip">{M(card.rotation.rates[length]||0)}<span className="rc-per">/{T('camp.order.perSpot')}</span></span>
                  <input type="number" min="0" className="rc-inp rc-inp-lg" placeholder="0"
                    value={order.rotation[sid]!=null?order.rotation[sid]:''}
                    onChange={function(e){ setRot(sid, e.target.value); }}/>
                  <div className="rc-rot-total"><span className="tiny">{T('camp.order.total')}</span> <b>{M((parseInt(order.rotation[sid]||0,10)||0) * (card.rotation.rates[length]||0))}</b></div>
                </div>
              </div>
            )}
          </div>
        );
      })}

      {/* uncarded stations */}
      {uncarded.map(function(sid){
        const s = byId[sid] || {};
        return (
          <div key={sid} className="rc-station rc-soon">
            <div className="rc-sthead">
              <div><b>{s.name||sid}</b> <span className="tiny">· {s.call||sid}{s.dial?(' · '+s.dial+' FM'):''}</span></div>
              <div className="rc-badge soon">{T('camp.order.soon')}</div>
            </div>
          </div>
        );
      })}

      {/* Added Value — free bonus spots, auto-calculated from spend + flight weeks. Cost $0, never in the money total. */}
      {carded.length>0 && (
        <div className={"rc-added"+(computed.addedValue.qualifies?'':' locked')}>
          <div className="rc-added-l">
            <span className="rc-avbadge"><I.sparkle w={13}/> {T('camp.order.addedValue')}</span>
            <div>
              {computed.addedValue.qualifies
                ? <><b>{computed.addedValue.freeSpots} {T('camp.order.bonusSpots')}</b>
                    <div className="tiny">{computed.addedValue.lines.map(function(l){ return l.label+' ×'+l.spots; }).join(' · ')}</div></>
                : <><b>{T('camp.order.avEarn')}</b><div className="tiny">{T('camp.order.avLocked')}</div></>}
            </div>
          </div>
          <div className="rc-added-r">
            <div className="rc-free">{T('camp.order.free')}</div>
            <div className="tiny">{M(0)}</div>
          </div>
        </div>
      )}

      {/* grand total */}
      <div className="rc-grand">
        <div>
          <div className="tiny">{T('camp.order.grandTotalNote')}</div>
          <div className="rc-glabel">{T('camp.order.grandTotal')}</div>
        </div>
        <div className="rc-gval">{M(computed.grandTotal)}</div>
      </div>
    </div>
  );
}

Object.assign(window, { StepOrder });
