import React, { useState } from 'react';

const fmtHKD = (n: number) =>
    'HK$' + Math.round(n).toLocaleString('en-HK');

/* ---------- Cashflow chart ---------- */
type CashflowPoint = { m: string; income: number; expense: number };
export const CashflowChart = ({ data, height = 240 }: { data: CashflowPoint[]; height?: number }) => {
    const W = 720, H = height, padL = 8, padR = 8, padT = 18, padB = 28;
    const max = Math.max(...data.map(d => Math.max(d.income, d.expense)), 1);
    const mag = Math.pow(10, Math.max(0, Math.floor(Math.log10(max)) - 1));
    const niceMax = Math.ceil(max / mag) * mag;
    const x = (i: number) => padL + (i / (data.length - 1)) * (W - padL - padR);
    const y = (v: number) => padT + (1 - v / niceMax) * (H - padT - padB);
    const line = (key: 'income' | 'expense') =>
        data.map((d, i) => `${i ? 'L' : 'M'}${x(i).toFixed(1)} ${y(d[key]).toFixed(1)}`).join(' ');
    const area = (key: 'income' | 'expense') =>
        `${line(key)} L${x(data.length - 1)} ${H - padB} L${x(0)} ${H - padB} Z`;
    const grid = [0, 0.25, 0.5, 0.75, 1].map(t => niceMax * t);
    const [hover, setHover] = useState<number | null>(null);

    return (
        <div className="chartwrap">
            <svg viewBox={`0 0 ${W} ${H}`} className="chart" preserveAspectRatio="none"
                onMouseLeave={() => setHover(null)}
                onMouseMove={e => {
                    const r = (e.currentTarget as SVGSVGElement).getBoundingClientRect();
                    const px = (e.clientX - r.left) / r.width * W;
                    let idx = Math.round((px - padL) / ((W - padL - padR) / (data.length - 1)));
                    idx = Math.max(0, Math.min(data.length - 1, idx));
                    setHover(idx);
                }}>
                <defs>
                    <linearGradient id="incFill" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stopColor="var(--green)" stopOpacity="0.26" />
                        <stop offset="100%" stopColor="var(--green)" stopOpacity="0" />
                    </linearGradient>
                </defs>
                {grid.map((g, i) => (
                    <line key={i} x1={padL} x2={W - padR} y1={y(g)} y2={y(g)} className="chart__grid" />
                ))}
                <path d={area('income')} fill="url(#incFill)" />
                <path d={line('income')} fill="none" stroke="var(--green)" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />
                <path d={line('expense')} fill="none" stroke="var(--flame)" strokeWidth="2.2" strokeDasharray="2 5" strokeLinecap="round" strokeLinejoin="round" />
                {data.map((d, i) => (
                    <text key={i} x={x(i)} y={H - 8} className="chart__xlab" textAnchor="middle">{d.m}</text>
                ))}
                {hover != null && (
                    <g>
                        <line x1={x(hover)} x2={x(hover)} y1={padT} y2={H - padB} className="chart__cursor" />
                        <circle cx={x(hover)} cy={y(data[hover].income)} r="4" fill="var(--green)" stroke="#fff" strokeWidth="1.5" />
                        <circle cx={x(hover)} cy={y(data[hover].expense)} r="4" fill="var(--flame)" stroke="#fff" strokeWidth="1.5" />
                    </g>
                )}
            </svg>
            {hover != null && (
                <div className="chart__tip" style={{ left: `${x(hover) / W * 100}%` }}>
                    <div className="chart__tipm">{data[hover].m}</div>
                    <div className="chart__tipr"><span className="dot dot--green" />Income<b className="mono">{fmtHKD(data[hover].income)}</b></div>
                    <div className="chart__tipr"><span className="dot dot--flame" />Expense<b className="mono">{fmtHKD(data[hover].expense)}</b></div>
                </div>
            )}
        </div>
    );
};

/* ---------- Donut chart ---------- */
type DonutDatum = { name: string; value: number };
export const Donut = ({
    data, size = 168, thickness = 26, centerLabel, centerValue,
}: { data: DonutDatum[]; size?: number; thickness?: number; centerLabel?: string; centerValue?: string }) => {
    const total = data.reduce((s, d) => s + d.value, 0);
    const r = (size - thickness) / 2;
    const C = 2 * Math.PI * r;
    const palette = ['var(--green)', 'var(--flame)', 'var(--blue)', 'var(--violet)', 'var(--teal)', 'var(--mute2)'];
    let acc = 0;
    return (
        <div className="donutwrap">
            <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} className="donut">
                <g transform={`rotate(-90 ${size / 2} ${size / 2})`}>
                    {data.map((d, i) => {
                        const frac = d.value / total;
                        const dash = `${(frac * C).toFixed(2)} ${(C - frac * C).toFixed(2)}`;
                        const off = -acc * C;
                        acc += frac;
                        return <circle key={i} cx={size / 2} cy={size / 2} r={r} fill="none"
                            stroke={palette[i % palette.length]} strokeWidth={thickness}
                            strokeDasharray={dash} strokeDashoffset={off} />;
                    })}
                </g>
                {centerValue && (
                    <>
                        <text x="50%" y="46%" textAnchor="middle" className="donut__val mono">{centerValue}</text>
                        <text x="50%" y="60%" textAnchor="middle" className="donut__lab">{centerLabel}</text>
                    </>
                )}
            </svg>
            <ul className="legend">
                {data.map((d, i) => (
                    <li key={i}>
                        <span className="legend__dot" style={{ background: palette[i % palette.length] }} />
                        <span className="legend__name">{d.name}</span>
                        <span className="legend__val mono">{Math.round(d.value / total * 100)}%</span>
                    </li>
                ))}
            </ul>
        </div>
    );
};

/* ---------- Horizontal bar list ---------- */
type BarListDatum = { name: string; value: number };
export const BarList = ({
    data, format = (v: number) => String(v),
}: { data: BarListDatum[]; format?: (v: number) => string }) => {
    const max = Math.max(...data.map(d => d.value));
    return (
        <ul className="barlist">
            {data.map((d, i) => (
                <li key={i}>
                    <span className="barlist__name">{d.name}</span>
                    <span className="barlist__track">
                        <span className="barlist__fill" style={{ width: `${d.value / max * 100}%` }} />
                    </span>
                    <span className="barlist__val mono">{format(d.value)}</span>
                </li>
            ))}
        </ul>
    );
};
