'use client';
import {SectionStepHeader} from '@/components/section-step-header';
import {useMemo,useState} from 'react';
import {debtNames,comparePlans,emptyFinancialGoals,plannerErrors,strategies,financialPurpose,makePlannerInput,openingMonth,planMonthLabel as monthLabel,type GoalInputs} from '@/lib/financial-goals';
import {readWish,type WishDraft} from '@/lib/goal-wishes';
const money=(v:number)=>new Intl.NumberFormat('en-ZA',{style:'currency',currency:'ZAR',maximumFractionDigits:0}).format(v);
function Input({label,value,onChange,max,prefix='R',step='1'}:{label:string;value:number|null;onChange:(n:number|null)=>void;max?:number;prefix?:string;step?:string}){return <label className="field"><span>{label}</span><div className="number"><span>{prefix}</span><input aria-label={label} type="number" min={0} max={max} step={step} value={value??''} onChange={e=>{if(e.target.value===''){onChange(null);return;}const n=Number(e.target.value);if(Number.isFinite(n)&&n>=0&&(max===undefined||n<=max))onChange(n);}}/></div></label>}
export function FinancialGoals({p,change,navigate,scenario,onScenarioChange,compact=false}:any){const input=makePlannerInput(p),g=input.goals,names=debtNames(g);const [draft,setDraft]=useState<WishDraft|null>(null),[notice,setNotice]=useState(''),[scheduleYear,setScheduleYear]=useState(0);const selected=scenario.index,funded=scenario.funded;const start=g.start||openingMonth();const errors=plannerErrors(input);const debtBudget=p.budget[0]?.amount||0;const debtPayments=input.homePay+input.carPay+input.cardsPay;if(Math.abs(debtBudget-debtPayments)>1)errors.push('The debt repayment budget must equal all entered debt monthly payments. Reconcile these figures below.');const plans=useMemo(()=>plannerErrors(makePlannerInput(p)).length?[]:comparePlans(makePlannerInput(p)),[p]);const plan=plans[Math.min(selected,plans.length-1)];const active=plan&&(funded?plan.requiredPlan:plan);const setG=(key:keyof GoalInputs,value:string|number|null)=>change((x:any)=>{x.financialGoals={...emptyFinancialGoals,...x.financialGoals,[key]:value};});const setA=(key:number,value:number|null)=>change((x:any)=>x.assumptions[key]=value??0);
const wishNames:Record<keyof WishDraft,string>={homeYears:'Home payoff years',home:names[0]+' Balance',homeRate:'Home annual interest',target:'Savings target',targetAge:'Target age',car:'Car settlement / balance',carPay:'Car monthly payment'};
return <>{!compact&&<section className="panel financepurpose"><p className="eyebrow">FINANCIAL GOALS</p><h2>Your Dreams Deserve A Starting Point.</h2><p>See where you are today, what needs attention, and the steps that could bring your goals within reach.</p><p className="note">{financialPurpose}</p></section>}<section id="finance-goals" tabIndex={-1} className="panel">{compact?<SectionStepHeader step={2} title="Your Wishes And Goals">Tell us what you want to achieve. Then complete the goal amounts and timing below so we can calculate your plan. Only enter loans you actually have.</SectionStepHeader>:<h2>What Would You Like Your Money To Make Possible?</h2>}<label className="field"><span>Your financial wishes</span><textarea maxLength={2000} rows={4} value={g.wish} placeholder="e.g. Save for a holiday, launch my business, study, build an emergency fund or clear a debt. Add an amount and when you would like to achieve it." onChange={e=>setG('wish',e.target.value)}/></label><label className="field"><span>Plan starts in</span><input type="month" value={g.start||openingMonth()} onChange={e=>setG('start',e.target.value)}/></label><button className="secondary" onClick={()=>{const extracted=readWish(g.wish);setDraft(Object.keys(extracted).length?extracted:null);setNotice(Object.keys(extracted).length?'Review the recognised amounts before using them.':'Add your wishes in the fields below. The text helper recognises common home, car and savings goals, not every sentence.');}}>Find goals in my wishes</button>{notice&&<p role="status">{notice}</p>}{draft&&<div className="reserve"><h3>Recognised Details</h3>{Object.entries(draft).map(([key,value])=><p key={key}>{wishNames[key as keyof WishDraft]}: <b>{key==='homeRate'?(value!*100).toFixed(2)+'%':key==='homeYears'||key==='targetAge'?value:money(value!)}</b></p>)}<button className="primarybutton" onClick={()=>{change((x:any)=>{x.financialGoals={...emptyFinancialGoals,...x.financialGoals};for(const [key,value] of Object.entries(draft)){const mapping:Record<string,number>={home:17,homeRate:18,car:20,carPay:21};if(key in mapping)x.assumptions[mapping[key]]=value;else x.financialGoals[key]=value;}});setDraft(null);setNotice('Recognised details applied. Check all inputs below; your budget repayment amount may need reconciliation.');}}>Use reviewed details</button></div>}</section>
<section className="panel"><h2>Turn Your Wishes Into Measurable Goals</h2><div className="goalinputgrid"><div><h3>My Goal</h3><label className="field"><span>What would you like to achieve?</span><input className="textinput" maxLength={120} value={g.goalName} placeholder="e.g. Travel, study, start a business or build emergency savings" onChange={e=>setG('goalName',e.target.value)}/></label><Input label="My current age" prefix="Age" max={120} value={g.age} onChange={v=>setG('age',v)}/><Input label="Reach my savings goal by age" prefix="Age" max={120} value={g.targetAge||null} onChange={v=>setG('targetAge',v??0)}/><Input label="Savings target" value={g.target} onChange={v=>setG('target',v??0)}/><Input label="Already invested towards this goal" value={g.invested} onChange={v=>setG('invested',v??0)}/><details><summary>Optional savings growth estimate</summary><p className="note">Leave at 0% to plan using contributions alone. A higher rate is only an estimate, after fees and taxes.</p><Input label="Estimated yearly savings growth (%)" prefix="%" max={50} step="0.1" value={Math.round(g.returnRate*10000)/100} onChange={v=>setG('returnRate',(v??0)/100)}/></details></div><div><h3>Free Up Cash Flow</h3><label className="field"><span>How would you like to create more room?</span><textarea rows={3} maxLength={2000} value={g.cashflowWish} placeholder="e.g. Reduce subscriptions, spend less on groceries, earn extra income or clear a debt" onChange={e=>setG('cashflowWish',e.target.value)}/></label><Input label="Monthly cash flow I want to free up" value={g.cashflowTarget||null} onChange={v=>setG('cashflowTarget',v??0)}/><Input label="Monthly amount already freed up" value={g.cashflowCurrent||null} onChange={v=>setG('cashflowCurrent',v??0)}/>{g.cashflowTarget>0&&<p className="note">{money(Math.max(0,g.cashflowTarget-g.cashflowCurrent))} / month still to free up. Update your income or budget when changes happen so your financial plan reflects them.</p>}</div></div><details><summary>Debts I Want To Settle (Optional)</summary><p className="note">Name each debt you want to work on, then enter its balance, interest, monthly payment and payoff period. Examples are suggestions only. Leave unused debts at zero. Debt 1 keeps its scheduled payment; extra money goes to the other debts according to your chosen plan.</p><div className="debtgrid">{(['home','car','card'] as const).map((key,i)=>{const slots=[[17,18,19],[20,22,21],[23,25,24]][i],balances=[input.home,input.car,input.cards],rates=[input.homeRate,input.carRate,input.cardsRate],payments=[input.homePay,input.carPay,input.cardsPay];return <div className="debt" key={key}><h3>{names[i]}</h3><label className="field"><span>What Debt Would You Like To Settle?</span><input className="textinput" aria-label={'Debt '+(i+1)+' name'} maxLength={120} value={g[`${key}Name`]||''} placeholder={['e.g. Home loan, student loan or personal loan','e.g. Vehicle loan, medical bill or business loan','e.g. Credit card, store account or another loan'][i]} onChange={e=>setG(`${key}Name`,e.target.value)}/></label><Input label={names[i]+' Outstanding Balance'} value={balances[i]} onChange={v=>setA(slots[0],v)}/><Input label={names[i]+' Annual Interest (%)'} prefix="%" max={50} step="0.01" value={Math.round(rates[i]*10000)/100} onChange={v=>setA(slots[1],(v??0)/100)}/><Input label={names[i]+' Current Monthly Payment'} value={payments[i]} onChange={v=>setA(slots[2],v)}/><Input label={'Settle '+names[i]+' Within (Years)'} prefix="Years" max={60} step="0.5" value={g[`${key}Years`]||null} onChange={v=>setG(`${key}Years`,v??0)}/></div>})}</div><p className="note">Use confirmed balances and rates. Include any settlement charges or balloon payments in the balance. Each entry uses one interest rate; enter separate debts separately.</p></details><details><summary>Emergency Cash And Starting Resources (Optional)</summary><div className="fields"><Input label="Accessible cash (separate from invested savings)" value={g.cash} onChange={v=>setA(8,v)}/><Input label="Protected emergency reserve" value={g.reserve} onChange={v=>setA(9,v)}/></div><p className="note">The first payment is at the end of the month after the opening date. Whole-year ages set the savings horizon. Accessible cash and invested savings must not include the same money.</p></details></section>
<section className="panel"><h2>What Your Budget Makes Available</h2><div className="mini"><div><span>Monthly net income</span><b>{money(input.income)}</b></div><div><span>All budget expenses</span><b>{money(input.expenses)}</b></div><div><span>Lifestyle fund allocations</span><b>{money(input.funds)}</b></div><div><span>Surplus after current repayments</span><b>{money(input.income-input.expenses-input.funds)}</b></div></div><button className="secondary" onClick={()=>navigate('budget')}>Edit or import my budget</button>{Math.abs(debtBudget-debtPayments)>1&&<div className="error"><p>The budget has {money(debtBudget)} of debt payments; the entered loan payments total {money(debtPayments)}. They must match to avoid counting payments twice.</p><button className="secondary" onClick={()=>change((x:any)=>x.budget[0].amount=debtPayments)}>Set debt repayment budget to {money(debtPayments)}</button></div>}</section>
{!!errors.length?<section className="panel financeconcerns"><p className="eyebrow">YOUR NEXT STEPS</p><h2>Before We Calculate Your Route</h2><ul>{errors.map(e=><li key={e}>{e}</li>)}</ul></section>:active&&<><section className="panel"><p className="eyebrow">{compact?"YOUR PLAN":"YOUR ROUTE TOWARDS YOUR GOALS"}</p><h2>{plan.additional===0?'Your goals fit the entered budget':'Your goals need more monthly room'}</h2><p>Best fit among {plans.length} compared plans: <b>{strategies.find(s=>s.id===plans[0].strategy)?.name}{plans[0].settleCar?' + settle '+names[1]+' from spare cash':''}</b>. Ranked by the smallest additional monthly amount needed, then lower estimated debt interest. This compares these strategies only.</p><label className="field"><span>Explore a plan</span><select value={Math.min(selected,plans.length-1)} onChange={e=>{onScenarioChange({index:Number(e.target.value),funded:false});setScheduleYear(0);}}>{plans.map((v,i)=><option key={i} value={i}>{strategies.find(s=>s.id===v.strategy)?.name}{v.settleCar?' · settle '+names[1]+' from cash':''} · extra {money(v.additional)}/month</option>)}</select></label><p>{strategies.find(s=>s.id===plan.strategy)?.description}</p>{plan.lump>0&&<p>At the start: settle {names[1]} with {money(plan.lump)} of cash above your protected reserve. The {money(input.carPay)} monthly payment is redirected from month one.</p>}{plan.additional>0&&<div className="reserve"><b>Additional income or expense reduction needed: {money(plan.additional)} per month</b><p>Your current budget does not meet all deadlines. The schedule below uses only available money unless you choose the funded scenario.</p><label><input type="checkbox" checked={funded} onChange={e=>onScenarioChange({index:selected,funded:e.target.checked})}/> Show the scenario with this extra monthly amount</label></div>}
<div className="mini"><div><span>{names[0]+' Payment For Your Deadline'}</span><b>{money(plan.homePay)} / month</b></div><div><span>{names[0]+' Extra Above Current Payment'}</span><b>{money(Math.max(0,plan.homePay-input.homePay))} / month</b></div><div><span>Standalone savings contribution</span><b>{money(plan.monthlySaving)} / month</b></div><div><span>{names[1]+' Payment Released After Payoff'}</span><b>{money(input.carPay)} / month</b></div></div><p className="note">Standalone savings assumes contributions from month one. The chosen strategy may save later and redirect cleared debt payments; its actual contributions appear in the schedule.</p><h3>{funded?'With the extra monthly amount':'With your current budget'}: first month allocation</h3><div className="mini">{[[names[0],active.firstAllocation.home],[names[1],active.firstAllocation.car],[names[2],active.firstAllocation.cards],['Reserve top-up',active.firstAllocation.reserve],['Towards savings',active.firstAllocation.saving]].map(([label,value])=><div key={label}><span>{label}</span><b>{money(Number(value))}</b></div>)}</div><h3>Your Goal Dates</h3><div className="mini">{input.home>0&&<div><span>{names[0]+' Paid Off By'}</span><b>{monthLabel(start,Math.round(g.homeYears*12))}</b></div>}{input.car>0&&<div><span>{names[1]+' Paid Off By'}</span><b>{monthLabel(start,Math.round(g.carYears*12))}</b></div>}{g.target>0&&<div><span>Savings target at age {g.targetAge}</span><b>{monthLabel(start,Math.round((g.targetAge-(g.age??g.targetAge))*12))}</b></div>}</div><aside className="financeconcerns"><p className="eyebrow">A LITTLE CLARITY</p><h3>What Needs Your Attention</h3><p>Use these points to strengthen your plan, one step at a time.</p><ul>{active.shortfall>0&&<li>Required loan payments exceed the available budget by up to {money(active.shortfall)} per month. Unfunded repayments are not assumed to have been made.</li>}{!active.homeMet&&<li>{names[0]} Balance At Your Payoff Deadline: {money(active.homeAtTarget)}.</li>}{!active.carMet&&<li>{names[1]} Balance At Its Deadline: {money(active.carAtTarget)}.</li>}{!active.cardsMet&&<li>{names[2]} Balance At Its Deadline: {money(active.cardsAtTarget)}.</li>}{!active.savingsMet&&<li>Savings shortfall at your target age: {money(Math.max(0,g.target-active.savingsAtTarget))}.</li>}{g.cash<g.reserve&&<li>Your cash is {money(g.reserve-g.cash)} below the protected reserve; spare monthly money first rebuilds it.</li>}{input.cards>0&&input.cardsPay<=input.cards*input.cardsRate/12&&<li>Your current payment for {names[2]} does not cover the first month's interest. Extra payments are needed to reduce that balance.</li>}{g.returnRate>0&&<li>The assumed investment return may not be achieved. Compare a lower rate or 0% before deciding what is affordable.</li>}{g.returnRate===0&&<li>This scenario assumes no investment growth; it relies on contributions alone.</li>}{active.feasible&&<li>The entered goals fit this scenario. Review income, spending, lender terms and savings progress regularly.</li>}<li>Amounts are in future rand, with no inflation adjustment. Income, living costs and interest rates stay constant. Fees, taxes and insurance are included only through your budget and net return assumption.</li></ul></aside><section className="financestart"><div className="financestartheading"><p className="eyebrow">YOUR NEXT SMALL STEPS</p><h3>Steps To Start</h3><p>Build your plan with confidence, one step at a time.</p></div><ol className="financesteps"><li><strong>Check your starting point</strong><p>Confirm your budget, loan balances, interest rates and settlement figures.</p></li><li><strong>Protect your reserve</strong><p>Keep or rebuild {money(g.reserve)} as your protected reserve.</p></li><li><strong>Make the monthly amount work</strong><p>{plan.additional>0?`Find ${money(plan.additional)} of additional monthly income or spending reductions before relying on the funded scenario.`:'Use the monthly allocations above without exceeding your available cash flow.'}</p></li><li><strong>Keep your progress moving</strong><p>Redirect repayments towards the next goal when a debt is cleared; check the schedule for when that happens.</p></li><li><strong>Review as life changes</strong><p>Review the plan when your income, expenses, goals or rates change.</p></li></ol></section><p className="note">{financialPurpose}</p></section>
<section className="panel"><h2>Your Progress Over Time</h2><div className="mini"><div><span>{names[0]+' Payoff'}</span><b>{monthLabel(start,active.payoff[2])}</b></div><div><span>{names[1]+' Payoff'}</span><b>{monthLabel(start,active.payoff[0])}</b></div><div><span>Savings at your target age</span><b>{money(active.savingsAtTarget)}</b></div><div><span>Estimated debt interest across the plan</span><b>{money(active.interest)}</b></div></div><GoalChart rows={active.rows}/><p className="note">Plum: invested savings · Gold: remaining debt. Accessible emergency cash is separate.</p>{!compact&&<details><summary>See the monthly amounts and repayments</summary><label className="field"><span>Plan year</span><select value={scheduleYear} onChange={e=>setScheduleYear(Number(e.target.value))}>{Array.from({length:Math.ceil(active.horizon/12)},(_,i)=><option key={i} value={i}>Year {i+1}</option>)}</select></label><div className="tablewrap"><table><thead><tr>{['Month',names[0]+' Paid',names[1]+' Paid',names[2]+' Paid','Reserve added','Savings added',names[0]+' Balance','Total debt','Investments','Unfunded payments'].map(h=><th key={h}>{h}</th>)}</tr></thead><tbody>{active.rows.filter(r=>Math.floor((r.month-1)/12)===scheduleYear).map(r=><tr key={r.month}><td>{monthLabel(start,r.month)}</td>{[r.homePaid,r.carPaid,r.cardsPaid,r.reservePaid,r.contribution,r.home,r.debts,r.investment,r.shortfall].map((v,i)=><td key={i}>{money(v)}</td>)}</tr>)}</tbody></table></div></details>}</section></>}
</>;
}
function GoalChart({rows}: {rows:ReturnType<typeof comparePlans>[number]['rows']}){const max=Math.max(1,...rows.map(r=>Math.max(r.investment,r.debts)));const path=(field:'investment'|'debts')=>rows.map((r,i)=>`${i?'L':'M'}${i/Math.max(1,rows.length-1)*700},${170-r[field]/max*150}`).join(' ');return <svg className="chart" viewBox="0 0 700 200" role="img" aria-label="Projected savings growth and remaining debt across the chosen plan"><line x1="0" x2="700" y1="170" y2="170" stroke="#dfe8ee"/><path d={path('investment')} fill="none" stroke="#7b3058" strokeWidth="4"/><path d={path('debts')} fill="none" stroke="#b48a52" strokeWidth="3"/><text x="0" y="195">Month 1</text><text x="590" y="195">Month {rows.length}</text></svg>}
