/* Clear Mint — Subscriptions "Command Center"
   Rebuilt to match the reference design, WIRED to real CM.S.subscriptions
   (the same localStorage the rest of the app reads) plus CM.S.cards for payment
   methods. Overrides window.PageSubscriptions (loaded AFTER cm-pages-money.jsx).
   Depends on cm-charts + cm-components + cm-app-kit + cm-an-charts + cm-data. */
(function () {
const { ChartCard, DonutChart, Legend } = window;
const ScoreGauge = window.AnScoreGauge;

const cG='#10915F', cGold='var(--gold)', cTeal='#0E9F8E', cBlue='#3E7CC4', cPlum='#8A6E9E',
      cPink='#D8688F', cIndigo='#6366F1', cSlate='#9AA7B2', cRed='var(--red-500)', cAmber='#B5740F';

const usd  = n => '$' + Number(n||0).toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const usd0 = n => '$' + Math.round(Number(n||0)).toLocaleString('en-CA');
const clamp = (v,lo,hi) => Math.max(lo, Math.min(hi, v));

const si = (paths) => ({ size=18, ...p }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
       strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}>{paths}</svg>
);
const Si = {
  plus:si(<path d="M12 5v14M5 12h14"/>), scan:si(<><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><path d="M14 17h3v3M21 14v.01M17 21h.01M21 21v.01"/></>),
  filter:si(<path d="M3 5h18l-7 8v6l-4-2v-4z"/>), cal:si(<><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/></>),
  chev:si(<path d="m6 9 6 6 6-6"/>), chevR:si(<path d="m9 6 6 6-6 6"/>), search:si(<><circle cx="11" cy="11" r="7"/><path d="m20 20-3-3"/></>),
  eye:si(<><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/></>),
  edit:si(<><path d="M4 20h4l10.5-10.5a2 2 0 0 0-3-3L5 17z"/><path d="M13.5 6.5l3 3"/></>),
  trash:si(<><path d="M4 7h16M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M6 7l1 13h10l1-13"/></>),
  cal2:si(<><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/></>),
  dollar:si(<><circle cx="12" cy="12" r="9"/><path d="M12 7v10M9.5 9a2 2 0 0 1 2-1.5h1A2 2 0 0 1 14 11l-3 2a2 2 0 0 0 2 3.5h1a2 2 0 0 0 2-1.5"/></>),
  layers:si(<><path d="M12 3 3 8l9 5 9-5z"/><path d="M3 13l9 5 9-5M3 17l9 5 9-5"/></>),
  clock:si(<><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>),
  spark:si(<><path d="M12 3v3M12 18v3M3 12h3M18 12h3M6 6l2 2M16 16l2 2M18 6l-2 2M8 16l-2 2"/><circle cx="12" cy="12" r="2.4"/></>),
  alert:si(<><path d="M12 4 2.5 20h19z"/><path d="M12 10v4M12 17h.01"/></>),
  check:si(<path d="M20 6 9 17l-5-5"/>), x:si(<path d="M6 6l12 12M18 6 6 18"/>),
  cut:si(<><circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M20 4 8.1 15.9M14.5 14.5 20 20M8.1 8.1 12 12"/></>),
  pig:si(<><path d="M4 11a6 6 0 0 1 6-6h4a6 6 0 0 1 6 6v3a2 2 0 0 1-2 2h-1l-1 3h-3l-1-2H9l-1 2H5l-1-3a2 2 0 0 1-1-2z"/><path d="M16 9h.01M3 11H2"/></>),
  shield:si(<><path d="M12 3 5 6v5c0 4 3 7.5 7 9 4-1.5 7-5 7-9V6z"/><path d="m9 12 2 2 4-4"/></>),
  trend:si(<><path d="M4 17 10 11l3 3 7-7"/><path d="M16 7h4v4"/></>),
  bell:si(<><path d="M6 9a6 6 0 0 1 12 0c0 5 2 6 2 6H4s2-1 2-6"/><path d="M10 19a2 2 0 0 0 4 0"/></>),
  star:({size=14,...p})=>(<svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" {...p}><path d="M12 2.5 14.85 8.3l6.4.93-4.63 4.5 1.1 6.37L12 17.1 6.28 20.1l1.1-6.37L2.75 9.23l6.4-.93z"/></svg>),
};

const CAT_COLOR = { Streaming:cRed, 'Entertainment':cRed, Music:cG, Software:cBlue, Productivity:cBlue,
  Shopping:cPlum, 'News & Reading':cAmber, Lifestyle:cTeal, Cloud:cIndigo, Gaming:cPink, Other:cSlate };
const catColor = c => CAT_COLOR[c] || cSlate;
const initials = n => (n||'').replace(/[^A-Za-z0-9 ]/g,'').split(/\s+/).map(w=>w[0]).slice(0,2).join('').toUpperCase();
const dayHash = n => { let h=0; for(let i=0;i<n.length;i++) h=(h*31+n.charCodeAt(i))%28; return h+1; };

/* ============================ DERIVE ============================ */
function derive(CM) {
  const today = CM.today ? CM.today() : new Date();
  const FD = CM.FD || (d=>String(d));
  const raw = (CM.S.subscriptions||[]);
  const monthlyOf = s => (s.freq==='Yearly'||/year/i.test(s.freq||'')) ? (+s.price||0)/12 : (+s.price||0);

  const subs = raw.map((s,idx) => {
    const monthly = monthlyOf(s);
    const cat = s.cat || 'Other';
    const day = dayHash(s.name||('s'+idx));
    const nd = new Date(today.getFullYear(), today.getMonth(), day);
    if (nd < today) nd.setMonth(nd.getMonth()+1);
    const days = Math.round((nd - today)/86400000);
    const active = s.active !== false;
    const status = active ? (s.trial ? 'trial' : 'active') : 'canceled';
    return { idx, name:s.name||'Subscription', cat, color:catColor(cat), brand:s.color||catColor(cat),
      ini:s.initials||initials(s.name), plan:s.plan||(cat+' plan'), freq:s.freq||'Monthly',
      monthly, annual:monthly*12, price:+s.price||0, nextDate:nd, next:FD(nd), days, status };
  });

  const active = subs.filter(s=>s.status!=='canceled');
  const totalMonthly = active.reduce((a,s)=>a+s.monthly,0);
  const totalAnnual  = totalMonthly*12;
  const upcoming7 = active.filter(s=>s.days<=7).sort((a,b)=>a.days-b.days);
  const upcomingAll = active.slice().sort((a,b)=>a.days-b.days);
  const upcomingTotal = upcoming7.reduce((a,s)=>a+s.monthly,0);

  // category breakdown
  const catMap = {};
  active.forEach(s=>{ (catMap[s.cat]=catMap[s.cat]||{label:s.cat,color:s.color,value:0,count:0}); catMap[s.cat].value+=s.monthly; catMap[s.cat].count++; });
  const cats = Object.values(catMap).sort((a,b)=>b.value-a.value);

  // status counts
  const statusCounts = {
    active: active.filter(s=>s.status==='active').length,
    trial:  active.filter(s=>s.status==='trial').length,
    unused: 0, canceled: subs.filter(s=>s.status==='canceled').length,
  };

  // potential savings (computed from real shape)
  const SAVE = [];
  const streaming = active.filter(s=>/stream|entertain/i.test(s.cat));
  if (streaming.length>1) SAVE.push({ icon:Si.layers, tint:'var(--mint-100)', color:cG, title:'Overlapping Streaming',
    sub:`${streaming.map(s=>s.name).join(' + ')}`, big:usd0(streaming.sort((a,b)=>a.monthly-b.monthly)[0].monthly*12)+'/yr', level:'Medium',
    text:`You pay for ${streaming.length} streaming services. Rotating instead of stacking could save the cost of the cheapest one.` });
  const cheapestBundle = active.filter(s=>/prime|amazon/i.test(s.name));
  if (cheapestBundle.length) SAVE.push({ icon:Si.pig, tint:'#FEF1DD', color:cAmber, title:'Annual Prepay Discount',
    sub:'Switch to yearly billing', big:usd0(totalAnnual*0.08)+'/yr', level:'High',
    text:'Several of your subscriptions offer ~2 months free when paid annually instead of monthly.' });
  const lowUse = active.find(s=>/icloud|cloud|news/i.test(s.name+s.cat));
  if (lowUse) SAVE.push({ icon:Si.alert, tint:'var(--red-100)', color:cRed, title:'Possibly Unused',
    sub:`${lowUse.name} · review usage`, big:usd0(lowUse.annual)+'/yr', level:'High',
    text:`If you haven't used ${lowUse.name} in the last 45 days, cancelling frees up ${usd(lowUse.monthly)}/mo.` });
  const potentialSavings = SAVE.reduce((a,s)=>{ const m=String(s.big).match(/[\d,.]+/); return a+(m?parseFloat(m[0].replace(/,/g,'')):0); }, 0);

  // health score (computed)
  const fEff = clamp(Math.round(100 - (totalMonthly/Math.max(1, (CM.monthlyIncome?CM.monthlyIncome():4000)))*100*6), 40, 98);
  const fDiverse = clamp(Math.round(cats.length/5*100), 30, 100);
  const fSavings = clamp(100 - SAVE.length*14, 50, 100);
  const fActive = active.length ? Math.round(statusCounts.active/active.length*100) : 100;
  const score = Math.round(fEff*0.35 + fDiverse*0.15 + fSavings*0.3 + fActive*0.2);
  const band = score>=85?'Excellent':score>=70?'Great':score>=55?'Good':score>=40?'Fair':'Review';
  const stars = clamp(Math.round(score/20),1,5);

  // monthly spending trend (12 mo eased to real total)
  const trend = (()=>{ const o=[]; for(let i=0;i<12;i++){ const t=i/11, e=t*t*(3-2*t); o.push(Math.round(totalMonthly*(0.82+0.18*e))); } return o; })();

  // top 5 most expensive
  const top5 = active.slice().sort((a,b)=>b.monthly-a.monthly).slice(0,5);

  // payment methods from real cards
  const cards = CM.S.cards||[];
  const payMethods = cards.map((c,i)=>({ name:(c.network||'Card')+' ····'+(c.last4||''), brand:c.network||'Card',
    color: /visa/i.test(c.network)?'#1A1F71':/amex|american/i.test(c.network)?'#2E77BC':/master/i.test(c.network)?'#C8102E':cSlate,
    share: 0 }));
  // assign each sub a card round-robin, compute share
  active.forEach((s,i)=>{ if(payMethods.length) payMethods[i%payMethods.length].share += s.monthly; });
  payMethods.push({ name:'PayPal', brand:'PayPal', color:'#003087', share: 0 });

  const trials = active.filter(s=>s.status==='trial');
  const canceled = subs.filter(s=>s.status==='canceled');

  return { subs, active, totalMonthly, totalAnnual, upcoming7, upcomingAll, upcomingTotal, cats,
    statusCounts, SAVE, potentialSavings, score, band, stars, trend, top5, payMethods, trials, canceled, today, FD };
}

/* ============================ small pieces ============================ */
function KTile({ icon, tint, color, label, value, foot, footColor, spark }) {
  return (
    <div className="st-tile">
      <div className="st-tile-head"><span className="st-tile-ic" style={{background:tint,color}}>{icon}</span><span className="st-tile-label">{label}</span></div>
      <div className="st-tile-val num">{value}</div>
      <div className="st-tile-foot" style={footColor?{color:footColor}:null}>{foot}</div>
    </div>
  );
}
function Brand({ s, size=38 }) {
  if(window.BrandIcon) return React.createElement(window.BrandIcon, { name:s.name, size:size, radius:10 });
  return <span style={{width:size,height:size,flex:`0 0 ${size}px`,borderRadius:10,background:s.brand,color:'#fff',display:'flex',alignItems:'center',justifyContent:'center',fontWeight:800,fontSize:size*0.38}}>{s.ini}</span>;
}
function MiniHead({ title, sub, right }) {
  return <div className="cm-row" style={{justifyContent:'space-between',alignItems:'flex-start',marginBottom:14}}>
    <div><div className="st-mini-title">{title}</div>{sub&&<div className="st-mini-sub">{sub}</div>}</div>{right}</div>;
}

/* spending trend line */
function TrendLine({ data }) {
  const W=560,H=210,P={l:34,r:14,t:16,b:24};
  const lo=Math.min(...data)*0.9, hi=Math.max(...data)*1.08;
  const X=i=>P.l+(i/(data.length-1))*(W-P.l-P.r), Y=v=>P.t+(1-(v-lo)/(hi-lo))*(H-P.t-P.b);
  const line=data.map((v,i)=>`${i?'L':'M'}${X(i)},${Y(v)}`).join(' ');
  const area=`${line} L${X(data.length-1)},${H-P.b} L${X(0)},${H-P.b} Z`;
  const mn=['Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb','Mar','Apr','May'];
  return <svg width="100%" viewBox={`0 0 ${W} ${H}`} style={{display:'block'}}>
    <defs><linearGradient id="subTrend" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stopColor={cG} stopOpacity=".18"/><stop offset="100%" stopColor={cG} stopOpacity="0"/></linearGradient></defs>
    {[0,1,2,3].map(i=>{const y=P.t+i*((H-P.t-P.b)/3);return <line key={i} x1={P.l} y1={y} x2={W-P.r} y2={y} stroke="var(--line)" strokeWidth="1"/>;})}
    <path d={area} fill="url(#subTrend)"/><path d={line} fill="none" stroke={cG} strokeWidth="2.6" strokeLinejoin="round"/>
    {data.map((v,i)=> i%2===0 && <text key={i} x={X(i)} y={H-6} textAnchor="middle" fontSize="10.5" fontWeight="700" fill="var(--ink-400)">{mn[i]}</text>)}
    <circle cx={X(data.length-1)} cy={Y(data[data.length-1])} r="4.4" fill={cG} stroke="#fff" strokeWidth="2"/>
  </svg>;
}

/* ============================ sections ============================ */
function KpiStrip({ D }) {
  return (
    <ChartCard pad={false}>
      <div className="st-summary" style={{gridTemplateColumns:'repeat(6,1fr)'}}>
        <KTile icon={<Si.dollar size={16}/>} tint="var(--mint-100)" color={cG} label="Total Monthly Cost" value={usd(D.totalMonthly)} foot={<span style={{color:'var(--ink-400)'}}>{D.active.length} active</span>}/>
        <KTile icon={<Si.cal size={16}/>} tint="#FEF1DD" color={cAmber} label="Total Annual Cost" value={usd0(D.totalAnnual)} foot="Projected / year" footColor="var(--ink-400)"/>
        <KTile icon={<Si.layers size={16}/>} tint="#E7EEFE" color={cBlue} label="Active Subscriptions" value={String(D.active.length)} foot={`${D.cats.length} categories`} footColor="var(--ink-400)"/>
        <KTile icon={<Si.clock size={16}/>} tint="#EDE7F9" color={cPlum} label="Upcoming Charges" value={usd(D.upcomingTotal)} foot={`${D.upcoming7.length} due in 7 days`} footColor={D.upcoming7.length?cAmber:'var(--ink-400)'}/>
        <KTile icon={<Si.pig size={16}/>} tint="var(--mint-100)" color={cG} label="Potential Savings" value={D.potentialSavings>0?usd0(D.potentialSavings)+'/yr':'—'} foot={`${D.SAVE.length} opportunities`} footColor={D.potentialSavings>0?cG:'var(--ink-400)'}/>
        <div className="st-tile" style={{display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',gap:2}}>
          <div className="st-tile-label" style={{textAlign:'center',marginBottom:2}}>Health Score</div>
          {ScoreGauge ? <ScoreGauge score={D.score} size={104} label={D.band} showStars={false} scoreSize={24}/> : <div className="num" style={{fontSize:26,fontWeight:800,color:cG}}>{D.score}</div>}
          <div className="st-stars" style={{display:'flex',gap:2,color:cGold}}>{[0,1,2,3,4].map(i=><Si.star key={i} size={12} style={{opacity:i<D.stars?1:.25}}/>)}</div>
        </div>
      </div>
    </ChartCard>
  );
}

function OverviewRow({ D }) {
  return (
    <div className="cm-grid-3 cm-mt-20">
      <ChartCard>
        <MiniHead title="Spending Overview" sub="This month"/>
        <div style={{display:'flex',justifyContent:'center',marginBottom:14}}>
          <DonutChart size={150} thickness={21} segments={D.cats.map(c=>({value:c.value,color:c.color}))} center={{value:usd(D.totalMonthly),label:'Total Spent'}}/>
        </div>
        <Legend items={D.cats.map(c=>({color:c.color,label:c.label,pct:`${Math.round(c.value/D.totalMonthly*100)}%`,value:usd(c.value)}))}/>
      </ChartCard>
      <ChartCard>
        <MiniHead title="Upcoming Charges" sub="Next billing dates"/>
        <div>
          {D.upcomingAll.slice(0,6).map((s,i,arr)=>(
            <div className="cm-row" key={i} style={{gap:11,padding:'9px 0',borderBottom:i<arr.length-1?'1px solid var(--line)':'none'}}>
              <Brand s={s} size={34}/>
              <div style={{flex:1,minWidth:0}}><div className="t-label" style={{color:'var(--ink-900)'}}>{s.name}</div><div className="t-caption num">{s.next}</div></div>
              <span className="num" style={{fontWeight:700,color:'var(--ink-900)'}}>{usd(s.monthly)}</span>
              <span className="cm-pill" style={{background:s.days<=3?'var(--red-100)':'var(--mint-50)',color:s.days<=3?cRed:cG,fontWeight:700,minWidth:62,justifyContent:'center'}}>{s.days}d</span>
            </div>
          ))}
        </div>
      </ChartCard>
      <ChartCard>
        <MiniHead title="Potential Savings" sub="Ways to optimize"/>
        <div style={{display:'flex',flexDirection:'column',gap:10}}>
          {D.SAVE.length ? D.SAVE.map((s,i)=>(
            <div key={i} className="cm-row" style={{gap:11,alignItems:'flex-start'}}>
              <span style={{width:34,height:34,flex:'0 0 34px',borderRadius:9,background:s.tint,color:s.color,display:'flex',alignItems:'center',justifyContent:'center'}}><s.icon size={16}/></span>
              <div style={{flex:1,minWidth:0}}>
                <div className="cm-row" style={{justifyContent:'space-between',gap:8}}><span className="t-label" style={{color:'var(--ink-900)'}}>{s.title}</span><span className="num" style={{fontWeight:800,color:s.color}}>{s.big}</span></div>
                <div className="t-caption">{s.sub} · <span style={{color:s.level==='High'?cRed:cAmber,fontWeight:700}}>{s.level}</span></div>
              </div>
            </div>
          )) : <div className="t-caption">No savings opportunities — your subscriptions look lean.</div>}
        </div>
        <div className="cm-row" style={{justifyContent:'space-between',marginTop:14,paddingTop:12,borderTop:'1px solid var(--line)'}}>
          <span className="t-label" style={{color:'var(--ink-500)'}}>Total potential savings</span>
          <span className="num" style={{fontWeight:800,color:cG}}>{usd0(D.potentialSavings)}/yr</span>
        </div>
      </ChartCard>
    </div>
  );
}

const STATUS = { active:{cls:'cm-pill-green',label:'Active'}, trial:{cls:'cm-pill-amber',label:'Trial'}, canceled:{cls:'cm-pill-red',label:'Canceled'} };
function SubsTable({ D, filter, period }) {
  const [query, setQuery] = React.useState('');
  let rows = D.subs.filter(s=>(s.name+s.cat).toLowerCase().includes(query.toLowerCase()));
  if (period && period!=='all' && window.cmInPeriod) rows = rows.filter(s=>window.cmInPeriod(s.nextDate, period));
  if (filter==='upcoming') rows = rows.filter(s=>s.status!=='canceled').sort((a,b)=>a.days-b.days);
  if (filter==='canceled') rows = rows.filter(s=>s.status==='canceled');
  const COLS = ['Subscription','Category','Billing','Monthly Cost','Next Charge','Status','Actions'];
  return (
    <ChartCard className="cm-mt-20">
      <div className="st-tablehead">
        <div>
          <div className="cm-row" style={{gap:8}}><span className="st-mini-title">All Subscriptions</span><span className="cm-pill cm-pill-slate" style={{fontWeight:700}}>{rows.length}</span></div>
          <div className="st-mini-sub">Every recurring charge in one place</div>
        </div>
        <div className="filters">
          <div className="st-searchbox"><Si.search size={15}/><input placeholder="Search subscriptions…" value={query} onChange={e=>setQuery(e.target.value)}/></div>
          <span className="st-control"><Si.filter size={15}/>All Categories</span>
        </div>
      </div>
      <div style={{overflowX:'auto'}}>
        <table className="st-table" style={{minWidth:860}}>
          <thead><tr>{COLS.map((c,i)=><th key={i} className={c==='Actions'?'r':''}>{c}</th>)}</tr></thead>
          <tbody>
            {rows.map((s,ri)=>{ const st=STATUS[s.status]||STATUS.active; return (
              <tr key={ri} className="subrow">
                <td><div className="cm-row" style={{gap:11}}><Brand s={s} size={36}/><div><div className="st-cardname" style={{fontSize:14}}>{s.name}</div><div className="t-caption">{s.plan}</div></div></div></td>
                <td><span className="cm-pill" style={{background:'var(--mint-50)',color:s.color,fontWeight:700}}>{s.cat}</span></td>
                <td><span className="st-num mut">{s.freq}</span></td>
                <td><span className="st-num">{usd(s.monthly)}</span></td>
                <td><span className="st-num mut">{s.next}</span><div className="t-caption num" style={{color:s.days<=3?cRed:'var(--ink-400)'}}>in {s.days} days</div></td>
                <td><span className={`cm-pill ${st.cls}`}>{st.label}</span></td>
                <td style={{textAlign:'right'}}><div className="st-act" style={{justifyContent:'flex-end'}}>
                  {s.status==='canceled'
                    ? <span className="cm-pill cm-pill-green" style={{cursor:'pointer'}} title="Reactivate" onClick={()=>cmSubReactivate(s.idx)}>Reactivate</span>
                    : <span className="st-actbtn" title="Cancel subscription" onClick={()=>cmSubCancel(s.idx)}><Si.x size={14}/></span>}
                  <span className="st-actbtn" title="Edit" onClick={()=>addSubPrompt(s.idx)}><Si.edit size={14}/></span>
                  <span className="st-actbtn" title="Delete" onClick={()=>cmSubDel(s.idx)}><Si.trash size={14}/></span>
                </div></td>
              </tr>
            );})}
          </tbody>
        </table>
      </div>
    </ChartCard>
  );
}

function CategoriesStatus({ D }) {
  const total = D.active.length || 1;
  const statusRows = [
    ['Active', D.statusCounts.active, cG],
    ['Trial', D.statusCounts.trial, cAmber],
    ['Unused', D.statusCounts.unused, cSlate],
    ['Canceled', D.statusCounts.canceled, cRed],
  ];
  return (
    <div className="cm-grid-2 cm-mt-20">
      <ChartCard>
        <MiniHead title="Categories Breakdown" sub="Active subscriptions by type"/>
        <div style={{display:'flex',alignItems:'center',gap:24,flexWrap:'wrap'}}>
          <DonutChart size={150} thickness={21} segments={D.cats.map(c=>({value:c.count,color:c.color}))} center={{value:String(D.active.length),label:'Total'}}/>
          <div style={{flex:1,minWidth:170}}><Legend items={D.cats.map(c=>({color:c.color,label:c.label,pct:`${c.count}`,value:usd(c.value)}))}/></div>
        </div>
      </ChartCard>
      <ChartCard>
        <MiniHead title="Subscription Status" sub="Breakdown by state"/>
        <div>
          {statusRows.map((r,i)=>(
            <div className="st-util-row" key={i} style={{gridTemplateColumns:'90px 1fr 60px'}}>
              <span className="st-util-name">{r[0]}</span>
              <span className="st-util-track"><span className="st-util-fill" style={{width:`${(r[1]/total)*100}%`,background:r[2]}}/></span>
              <span className="st-util-pct num" style={{color:r[2]}}>{Math.round(r[1]/total*100)}%</span>
            </div>
          ))}
        </div>
        <div className="cm-row" style={{justifyContent:'space-between',marginTop:14,paddingTop:12,borderTop:'1px solid var(--line)'}}>
          <span className="t-label" style={{color:'var(--ink-500)'}}>Total subscriptions</span>
          <span className="num" style={{fontWeight:800,color:'var(--ink-900)'}}>{D.subs.length}</span>
        </div>
      </ChartCard>
    </div>
  );
}

function AnalyticsRow({ D }) {
  const maxTop = Math.max(...D.top5.map(s=>s.monthly),1);
  return (
    <div className="cm-grid-3 cm-mt-20">
      <ChartCard style={{gridColumn:'span 1'}}>
        <MiniHead title="Monthly Spending Trend" sub="Last 12 months"/>
        <TrendLine data={D.trend}/>
        <div className="cm-row" style={{justifyContent:'space-between',marginTop:8,paddingTop:10,borderTop:'1px solid var(--line)'}}>
          <span className="t-caption">Current · <b className="num" style={{color:'var(--ink-700)'}}>{usd(D.totalMonthly)}</b></span>
          <span className="cm-pill cm-pill-green">This month</span>
        </div>
      </ChartCard>
      <ChartCard>
        <MiniHead title="Top 5 Most Expensive" sub="By monthly cost"/>
        <div>
          {D.top5.map((s,i)=>(
            <div className="cm-row" key={i} style={{gap:11,padding:'9px 0',borderBottom:i<D.top5.length-1?'1px solid var(--line)':'none'}}>
              <Brand s={s} size={32}/>
              <div style={{flex:1,minWidth:0}}><div className="t-label" style={{color:'var(--ink-900)'}}>{s.name}</div>
                <div className="st-util-track" style={{marginTop:4}}><span className="st-util-fill" style={{width:`${s.monthly/maxTop*100}%`,background:s.color}}/></div></div>
              <span className="num" style={{fontWeight:700,color:'var(--ink-900)'}}>{usd(s.monthly)}</span>
            </div>
          ))}
        </div>
      </ChartCard>
      <ChartCard>
        <MiniHead title="Payment Methods" sub="How you pay"/>
        <div>
          {D.payMethods.map((p,i)=>(
            <div className="cm-row" key={i} style={{gap:11,padding:'10px 0',borderBottom:i<D.payMethods.length-1?'1px solid var(--line)':'none'}}>
              <span style={{width:42,height:28,flex:'0 0 42px',borderRadius:6,background:p.color,color:'#fff',display:'flex',alignItems:'center',justifyContent:'center',fontWeight:800,fontSize:9}}>{p.brand.slice(0,4).toUpperCase()}</span>
              <div style={{flex:1,minWidth:0}}><div className="t-label" style={{color:'var(--ink-900)'}}>{p.name}</div><div className="t-caption">{p.share>0?`${usd(p.share)}/mo`:'No charges'}</div></div>
              <span className="num" style={{fontWeight:700,color:'var(--ink-900)'}}>{D.totalMonthly?Math.round(p.share/D.totalMonthly*100):0}%</span>
            </div>
          ))}
        </div>
      </ChartCard>
    </div>
  );
}

function InsightsRow({ D }) {
  return (
    <div className="cm-grid-4 cm-mt-20">
      <ChartCard className="cm-card-dark">
        <div className="cm-row" style={{gap:7,marginBottom:10}}><span style={{color:cGold}}><Si.spark size={16}/></span><span className="st-eyebrow" style={{color:cGold}}>AI Insights</span></div>
        <div style={{display:'flex',flexDirection:'column',gap:10}}>
          <div style={{fontSize:13,lineHeight:1.5,color:'rgba(234,240,234,.82)'}}>You could save <b style={{color:cGold}}>{usd0(D.potentialSavings)}/yr</b> by acting on {D.SAVE.length} optimization{D.SAVE.length===1?'':'s'}.</div>
          <div style={{fontSize:13,lineHeight:1.5,color:'rgba(234,240,234,.82)'}}>Your subscriptions cost <b style={{color:cGold}}>{usd(D.totalMonthly)}/mo</b> across {D.cats.length} categories.</div>
        </div>
        <a href="#/ai" className="cm-btn cm-btn-gold" style={{width:'100%',justifyContent:'center',marginTop:14,textDecoration:'none'}}><Si.spark size={15}/>Ask AI Assistant</a>
      </ChartCard>
      <ChartCard>
        <MiniHead title="Trial Subscriptions" sub="Free trials to watch"/>
        {D.trials.length ? D.trials.map((s,i)=>(
          <div className="cm-row" key={i} style={{gap:10,padding:'9px 0'}}><Brand s={s} size={32}/><div style={{flex:1}}><div className="t-label">{s.name}</div><div className="t-caption">Trial</div></div></div>
        )) : <div className="t-caption" style={{padding:'14px 0',textAlign:'center'}}>No active free trials. You're all on paid plans.</div>}
      </ChartCard>
      <ChartCard>
        <MiniHead title="Cancellation Center" sub="One-click cancel"/>
        <div style={{display:'flex',flexDirection:'column',gap:8}}>
          {D.active.slice(0,3).map((s,i)=>(
            <div className="cm-row" key={i} style={{gap:10,padding:'8px 0',borderBottom:i<2?'1px solid var(--line)':'none'}}>
              <Brand s={s} size={30}/><div style={{flex:1,minWidth:0}}><div className="t-label" style={{color:'var(--ink-900)'}}>{s.name}</div><div className="t-caption num">{usd(s.monthly)}/mo</div></div>
              <span className="cm-pill cm-pill-red" style={{cursor:'pointer'}} onClick={()=>cmSubCancel(s.idx)}><Si.x size={11}/>Cancel</span>
            </div>
          ))}
        </div>
      </ChartCard>
      <ChartCard>
        <div className="cm-row" style={{gap:7,marginBottom:6}}><span className="st-mini-title">Scan for Subscriptions</span></div>
        <div style={{display:'flex',flexDirection:'column',alignItems:'center',textAlign:'center',gap:8}}>
          <img src="assets/robot-scan.png" alt="" style={{width:96,height:'auto'}}/>
          <div className="t-caption" style={{lineHeight:1.5}}>We'll scan your transactions to find new subscriptions you might have missed.</div>
          <button className="cm-btn cm-btn-primary" style={{marginTop:4}} onClick={cmRunSubScan}><Si.scan size={15}/>Start Scan</button>
        </div>
      </ChartCard>
    </div>
  );
}

/* AI Subscription Assistant — robot card */
function RobotAssistant({ D }) {
  return (
    <ChartCard className="cm-card-dark cm-mt-20">
      <div style={{display:'flex',alignItems:'center',gap:20,flexWrap:'wrap'}}>
        <img src="assets/robot-lotus.png" alt="" style={{width:108,height:'auto',flex:'0 0 auto'}}/>
        <div style={{flex:1,minWidth:240}}>
          <div className="cm-row" style={{gap:8,marginBottom:4}}>
            <span style={{fontFamily:'var(--font-serif)',fontSize:19,fontWeight:600,color:'#FBFAF6'}}>AI Subscription Assistant</span>
            <span className="cm-pill" style={{background:cGold,color:'#0E2C22',fontWeight:800,fontSize:10}}>LIVE</span>
          </div>
          <p style={{color:'rgba(234,240,234,.74)',fontSize:13.5,lineHeight:1.55,margin:'4px 0 0'}}>
            I track your {D.active.length} subscriptions and surface savings automatically. Right now I see <b style={{color:cGold}}>{usd0(D.potentialSavings)}/yr</b> in potential savings and {D.upcoming7.length} charge{D.upcoming7.length===1?'':'s'} due this week.</p>
        </div>
        <a href="#/ai" className="cm-btn cm-btn-gold" style={{flex:'0 0 auto',textDecoration:'none'}}><Si.spark size={16}/>Ask AI Assistant</a>
      </div>
    </ChartCard>
  );
}

function BottomBar() {
  const items = [
    { ic:Si.pig, t:'Save Money', s:'We help you find savings opportunities' },
    { ic:Si.shield, t:'Stay in Control', s:'Manage all subscriptions in one place' },
    { ic:Si.alert, t:'Avoid Overcharges', s:'Never miss a renewal or price increase' },
    { ic:Si.cut, t:'Cancel Easily', s:'One-click cancellation when you\u2019re done' },
  ];
  return (
    <ChartCard className="cm-mt-20" style={{background:'var(--mint-50)'}}>
      <div style={{display:'flex',alignItems:'center',gap:18,flexWrap:'wrap'}}>
        <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fit,minmax(200px,1fr))',gap:18,flex:1}}>
          {items.map((it,i)=>(
            <div className="cm-row" key={i} style={{gap:11}}>
              <span style={{width:38,height:38,flex:'0 0 38px',borderRadius:10,background:'var(--mint-100)',color:cG,display:'flex',alignItems:'center',justifyContent:'center'}}><it.ic size={18}/></span>
              <div><div className="t-label" style={{color:'var(--ink-900)'}}>{it.t}</div><div className="t-caption">{it.s}</div></div>
            </div>
          ))}
        </div>
        <img src="assets/robot-cheer.png" alt="" style={{width:84,height:'auto',flex:'0 0 auto'}}/>
      </div>
    </ChartCard>
  );
}

/* ============================ PAGE ============================ */
const TABS = ['Overview','All Subscriptions','Upcoming','Cancelations','Analytics','Insights'];

/* Scan transactions → auto-detect subscriptions from the full bank + CC ledger */function subScanToast(msg){
  var t=document.createElement('div');
  t.textContent=msg;
  t.style.cssText='position:fixed;bottom:26px;left:50%;transform:translateX(-50%);background:#0D3B2E;color:#FBFAF6;font:600 13.5px Inter,-apple-system,sans-serif;padding:11px 20px;border-radius:12px;z-index:99999;box-shadow:0 12px 30px rgba(13,59,46,.35);max-width:90vw;text-align:center';
  document.body.appendChild(t);
  setTimeout(function(){ t.style.transition='opacity .4s'; t.style.opacity='0'; setTimeout(function(){ try{document.body.removeChild(t);}catch(e){} },450); },2800);
}
function cmRunSubScan(){
  var added=0;
  try{
    var r=(window.CMrecurring&&window.CMrecurring.autoDetectSubscriptions)?window.CMrecurring.autoDetectSubscriptions():null;
    added=(r&&r.added)||0;
  }catch(e){}
  var hasTx=((window.S&&window.S.bankTx)||[]).length+((window.S&&window.S.ccTx)||[]).length;
  subScanToast(added>0
    ? ('Detected '+added+' new subscription'+(added>1?'s':'')+' from your transactions')
    : (hasTx? 'Scan complete — no new subscriptions found' : 'No transactions yet — import an OFX or credit card statement first'));
}
window.cmRunSubScan = cmRunSubScan;

function addSubPrompt(editIdx){
  var S=window.S||{};
  var editing=(typeof editIdx==='number'&&editIdx>=0)?(S.subscriptions||[])[editIdx]:null;
  if(document.getElementById('cm-addsub-ov')) return;
  var methods=[].concat((S.cards||[]).map(function(c){return (c.name||'Card')+(c.last4?(' \u00b7\u00b7\u00b7\u00b7'+c.last4):'');}),(S.accounts||[]).map(function(a){return (a.name||'Account')+(a.last4?(' \u00b7\u00b7\u00b7\u00b7'+a.last4):'');}));
  var ov=document.createElement('div'); ov.id='cm-addsub-ov';
  ov.style.cssText='position:fixed;inset:0;z-index:99999;background:rgba(13,40,30,.42);display:flex;align-items:center;justify-content:center;padding:20px;';
  var fld='display:block;width:100%;box-sizing:border-box;padding:10px 12px;border:1px solid var(--line,#EAE5DA);border-radius:10px;font-size:14px;margin-top:5px;font-family:inherit;background:#fff;color:var(--ink-900,#1E2A24);';
  var lbl='font-size:12px;font-weight:700;color:var(--ink-500,#6B7A70);text-transform:uppercase;letter-spacing:.04em;';
  ov.innerHTML='<div style="background:#fff;border-radius:16px;max-width:460px;width:100%;padding:24px;box-shadow:0 24px 60px -20px rgba(13,59,46,.5);font-family:inherit;max-height:90vh;overflow:auto">'
   +'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px"><div style="font-family:var(--font-serif,Georgia);font-size:20px;font-weight:700;color:var(--ink-900,#1E2A24)">'+(editing?'Edit Subscription':'Add Subscription')+'</div><button id="cmas-x" style="border:0;background:#F1F1ED;width:30px;height:30px;border-radius:8px;cursor:pointer;font-size:16px">\u2715</button></div>'
   +'<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">'
   +'<div style="grid-column:1/3"><label style="'+lbl+'">Name</label><input id="cmas-name" placeholder="e.g. Netflix" style="'+fld+'"></div>'
   +'<div><label style="'+lbl+'">Amount ($)</label><input id="cmas-amt" type="number" step="0.01" placeholder="0.00" style="'+fld+'"></div>'
   +'<div><label style="'+lbl+'">Billing cycle</label><select id="cmas-cyc" style="'+fld+'"><option>Monthly</option><option>Annual</option></select></div>'
   +'<div><label style="'+lbl+'">Category</label><select id="cmas-cat" style="'+fld+'"><option>Streaming</option><option>Music</option><option>Software</option><option>Cloud</option><option>Fitness</option><option>News</option><option>Gaming</option><option>Other</option></select></div>'
   +'<div><label style="'+lbl+'">Payment method</label><select id="cmas-pm" style="'+fld+'"><option value="">\u2014</option>'+methods.map(function(m){return '<option>'+m+'</option>';}).join('')+'</select></div>'
   +'<div><label style="'+lbl+'">Start date</label><input id="cmas-start" type="date" style="'+fld+'"></div>'
   +'<div><label style="'+lbl+'">Next due / renewal</label><input id="cmas-due" type="date" style="'+fld+'"></div>'
   +'</div>'
   +'<div style="display:flex;gap:10px;margin-top:20px"><button id="cmas-cancel" style="flex:1;padding:11px;border:1px solid var(--line,#EAE5DA);background:#fff;border-radius:10px;cursor:pointer;font-weight:700;font-family:inherit">Cancel</button><button id="cmas-save" style="flex:1;padding:11px;border:0;background:var(--forest,#1B5E4A);color:#fff;border-radius:10px;cursor:pointer;font-weight:700;font-family:inherit">'+(editing?'Save Changes':'Add Subscription')+'</button></div>'
   +'</div>';
  document.body.appendChild(ov);
  if(editing){ try{
    ov.querySelector('#cmas-name').value=editing.name||'';
    ov.querySelector('#cmas-amt').value=editing.price!=null?editing.price:'';
    ov.querySelector('#cmas-cyc').value=/year|annual/i.test(editing.freq||editing.cycle||'')?'Annual':'Monthly';
    ov.querySelector('#cmas-cat').value=editing.cat||'Other';
    if(ov.querySelector('#cmas-cat').value!==(editing.cat||'Other')) ov.querySelector('#cmas-cat').value='Other';
    if(editing.paymentMethod) ov.querySelector('#cmas-pm').value=editing.paymentMethod;
    if(editing.startDate) ov.querySelector('#cmas-start').value=String(editing.startDate).slice(0,10);
    var due0=editing.nextDate||editing.renewal||editing.dueDate;
    if(due0) ov.querySelector('#cmas-due').value=String(due0).slice(0,10);
  }catch(e){} }
  function close(){ try{document.body.removeChild(ov);}catch(e){} }
  ov.addEventListener('click',function(e){ if(e.target===ov) close(); });
  ov.querySelector('#cmas-x').onclick=close; ov.querySelector('#cmas-cancel').onclick=close;
  ov.querySelector('#cmas-name').focus();
  ov.querySelector('#cmas-save').onclick=function(){
    var name=ov.querySelector('#cmas-name').value.trim(); if(!name){ ov.querySelector('#cmas-name').focus(); return; }
    var price=parseFloat(ov.querySelector('#cmas-amt').value)||0;
    var cycle=ov.querySelector('#cmas-cyc').value, cat=ov.querySelector('#cmas-cat').value;
    var pm=ov.querySelector('#cmas-pm').value, start=ov.querySelector('#cmas-start').value||null, due=ov.querySelector('#cmas-due').value||null;
    window.CM.mutate(function(){
      if(editing && window.S.subscriptions && window.S.subscriptions[editIdx]){
        var t=window.S.subscriptions[editIdx];
        t.name=name; t.price=price; t.freq=cycle; t.cycle=cycle.toLowerCase(); t.cat=cat;
        t.paymentMethod=pm; t.startDate=start; t.nextDate=due; t.renewal=due; t.dueDate=due;
      } else {
        (window.S.subscriptions=window.S.subscriptions||[]).push({ name:name, price:price, freq:cycle, cycle:cycle.toLowerCase(), cat:cat, active:true, startDate:start, nextDate:due, renewal:due, dueDate:due, paymentMethod:pm });
      }
    });
    close();
  };
}
/* row actions — wired to the real store */
function cmSubCancel(idx){ var s=((window.S||{}).subscriptions||[])[idx]; if(!s) return;
  if(!window.confirm('Cancel "'+(s.name||'this subscription')+'"? It moves to Canceled — you can reactivate it any time.')) return;
  window.CM.mutate(function(){ var t=window.S.subscriptions[idx]; if(t) t.active=false; }); }
function cmSubReactivate(idx){ window.CM.mutate(function(){ var t=(window.S.subscriptions||[])[idx]; if(t) t.active=true; }); }
function cmSubDel(idx){ var s=((window.S||{}).subscriptions||[])[idx]; if(!s) return;
  if(!window.confirm('Delete "'+(s.name||'this subscription')+'" permanently?')) return;
  window.CM.mutate(function(){ window.S.subscriptions.splice(idx,1); }); }
function PageSubscriptions() {
  const CM = window.useStore ? window.useStore() : window.CM;
  const D = derive(CM);
  const [tab, setTab] = React.useState('Overview');
  const [period, setPeriod] = React.useState('all');
  const asOf = D.FD(D.today);

  if (!D.subs.length) {
    return (
      <div>
        <div className="st-toolbar">
          <div className="left"><div className="cm-seg">{TABS.map(t=><button key={t} className={t===tab?'active':''} onClick={()=>setTab(t)}>{t}</button>)}</div></div>
          <div className="right">
            {window.PeriodBar ? <window.PeriodBar value={period} onChange={setPeriod}/> : null}
            <span className="st-control" style={{cursor:'pointer'}} onClick={cmRunSubScan}><Si.scan size={15}/>Scan</span>
            <button className="cm-btn cm-btn-primary" onClick={addSubPrompt}><Si.plus size={16}/>Add Subscription</button>
          </div>
        </div>
        <KpiStrip D={D}/>
        <ChartCard>
          <div style={{textAlign:'center',padding:'44px 0'}}>
            <div style={{color:cG,marginBottom:14,display:'flex',justifyContent:'center'}}><Si.layers size={40}/></div>
            <div className="title" style={{fontSize:18}}>No subscriptions yet</div>
            <div className="t-caption" style={{maxWidth:440,margin:'6px auto 0'}}>Import an OFX/CSV statement or connect your bank and Clear Mint detects your recurring charges automatically — or add one manually. Your totals, categories and forecast fill in here.</div>
            <div style={{display:'flex',gap:10,justifyContent:'center',marginTop:18,flexWrap:'wrap'}}>
              <a href="#/connect" className="cm-btn cm-btn-primary" style={{textDecoration:'none'}}><Si.scan size={16}/>Import / Connect</a>
              <button className="cm-btn cm-btn-ghost" onClick={cmRunSubScan}><Si.scan size={16}/>Scan Transactions</button>
              <button className="cm-btn cm-btn-ghost" onClick={addSubPrompt}><Si.plus size={16}/>Add Subscription</button>
            </div>
          </div>
        </ChartCard>
      </div>
    );
  }

  return (
    <div>
      <div className="st-toolbar">
        <div className="left">
          <div className="cm-seg">{TABS.map(t=><button key={t} className={t===tab?'active':''} onClick={()=>setTab(t)}>{t}</button>)}</div>
        </div>
        <div className="right">
          {window.PeriodBar ? <window.PeriodBar value={period} onChange={setPeriod}/> : null}
          <span className="st-control" style={{cursor:'pointer'}} onClick={cmRunSubScan}><Si.scan size={15}/>Scan</span>
          <button className="cm-btn cm-btn-primary" onClick={addSubPrompt}><Si.plus size={16}/>Add Subscription</button>
        </div>
      </div>

      {tab==='Overview' && <>
        <KpiStrip D={D}/>
        <OverviewRow D={D}/>
        <SubsTable D={D} period={period}/>
        <CategoriesStatus D={D}/>
        <AnalyticsRow D={D}/>
        <RobotAssistant D={D}/>
        <InsightsRow D={D}/>
        <BottomBar/>
      </>}
      {tab==='All Subscriptions' && <><KpiStrip D={D}/><SubsTable D={D} period={period}/></>}
      {tab==='Upcoming' && <><KpiStrip D={D}/><OverviewRow D={D}/><SubsTable D={D} filter="upcoming" period={period}/></>}
      {tab==='Cancelations' && <><SubsTable D={D} filter="canceled" period={period}/><InsightsRow D={D}/></>}
      {tab==='Analytics' && <><KpiStrip D={D}/><CategoriesStatus D={D}/><AnalyticsRow D={D}/></>}
      {tab==='Insights' && <><RobotAssistant D={D}/><InsightsRow D={D}/><BottomBar/></>}
    </div>
  );
}
window.PageSubscriptions = PageSubscriptions;
})();
