import { useState, useEffect } from 'react'
import { Download } from 'lucide-react'
import {
  BarChart, Bar, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer,
} from 'recharts'
import { getActuals, getNetSales, getBudgets, downloadExport } from '../api'
import type { WageBudget } from '../types'

function fmt(d: Date): string {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}
function fmtMoney(n: number): string { return `£${Math.round(n).toLocaleString('en-GB')}` }
function pctClass(p: number): string { return p <= 100 ? 'pct-green' : p <= 110 ? 'pct-amber' : 'pct-red' }
function fmtDelta(p: number): string { const d = p - 100; return `${d >= 0 ? '+' : ''}${d.toFixed(1)}%` }
function daysInMonth(y: number, m: number): number { return new Date(y, m, 0).getDate() }

const DEPT_COLORS = ['#065f46','#059669','#0891b2','#7c3aed','#c2410c','#b45309','#0f766e','#4338ca','#be185d','#15803d']
const MONTH_LABELS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

export default function Rolling12Months() {
  const [rows,     setRows]     = useState<{ label: string; wages: number; budget: number | null; sales: number; pySales: number; partial: boolean }[]>([])
  const [deptCols, setDeptCols] = useState<{ id: string; name: string; color: string }[]>([])
  const [chartData, setChartData] = useState<Record<string, number | string>[]>([])
  const [loading, setLoading] = useState(true)
  const [error,   setError]   = useState<string | null>(null)

  useEffect(() => {
    ;(async () => {
      setLoading(true); setError(null)
      try {
        const today = new Date()
        const curY  = today.getFullYear()
        const curM  = today.getMonth() + 1  // 1-based

        // 13 months: 12 complete + current partial
        const months: { year: number; month: number }[] = []
        for (let i = 12; i >= 0; i--) {
          let m = curM - i
          let y = curY
          while (m <= 0) { m += 12; y-- }
          months.push({ year: y, month: m })
        }

        const rangeFrom = `${months[0].year}-${String(months[0].month).padStart(2, '0')}-01`
        const lastMon   = months[months.length - 1]
        const lastDim   = daysInMonth(lastMon.year, lastMon.month)
        const rangeTo   = `${lastMon.year}-${String(lastMon.month).padStart(2, '0')}-${String(lastDim).padStart(2, '0')}`

        const [actRes, salesRes, budRes] = await Promise.all([
          getActuals(rangeFrom, rangeTo),
          getNetSales(rangeFrom, rangeTo),
          getBudgets(),
        ])

        const salesByDate: Record<string, { sales: number; py: number }> = {}
        for (const d of salesRes.days) salesByDate[d.date] = { sales: d.net_sales, py: d.py_sales }

        const budgetMap: Record<string, number> = {}
        for (const b of budRes.budgets as WageBudget[]) budgetMap[b.month] = b.budget_amount

        const depts = actRes.departments
        const cols  = depts.map((d, i) => ({ id: d.department_id, name: d.department_name, color: DEPT_COLORS[i % DEPT_COLORS.length] }))
        setDeptCols(cols)

        const tableRows: typeof rows = []
        const cData: Record<string, number | string>[] = []
        const todayStr = fmt(today)

        for (const { year, month } of months) {
          const dim       = daysInMonth(year, month)
          const monthStr  = `${year}-${String(month).padStart(2, '0')}`
          const monthFrom = `${monthStr}-01`
          const monthTo   = `${monthStr}-${String(dim).padStart(2, '0')}`
          const isCurrentMonth = year === curY && month === curM
          const effectiveTo = isCurrentMonth ? todayStr : monthTo

          let wages = 0
          const deptWages: Record<string, number> = {}
          for (const dep of depts) {
            let dCost = 0
            for (const [date, val] of Object.entries(dep.days)) {
              if (date >= monthFrom && date <= effectiveTo) dCost += val.cost
            }
            wages += dCost
            deptWages[dep.department_id] = dCost
          }

          let sales = 0, pySales = 0
          for (const [date, val] of Object.entries(salesByDate)) {
            if (date >= monthFrom && date <= effectiveTo) { sales += val.sales; pySales += val.py }
          }

          // Budget: prorated to elapsed-to-date by each day's share of the month's PY (DOW-matched)
          // sales — falls back to flat day-count when PY data is missing. For complete past months
          // effectiveTo === monthTo, so this always resolves to the full budget (fraction = 1).
          let monthPyTotal = 0
          for (const [date, val] of Object.entries(salesByDate)) {
            if (date >= monthFrom && date <= monthTo) monthPyTotal += val.py
          }
          const monKey    = `${monthFrom}`
          const budgetRaw = budgetMap[monKey] ?? null
          const mtdFrac   = monthPyTotal > 0
            ? pySales / monthPyTotal
            : parseInt(effectiveTo.slice(8), 10) / dim
          const budget = budgetRaw != null ? budgetRaw * mtdFrac : null
          const label  = `${MONTH_LABELS[month - 1]}-${String(year).slice(2)}`

          tableRows.push({ label, wages, budget, sales, pySales, partial: isCurrentMonth })

          const cdRow: Record<string, number | string> = { label }
          for (const dep of depts) cdRow[dep.department_name] = deptWages[dep.department_id] ?? 0
          cData.push(cdRow)
        }

        setRows(tableRows)
        setChartData(cData)
      } catch (e: unknown) {
        setError(e instanceof Error ? e.message : 'Failed to load')
      } finally {
        setLoading(false)
      }
    })()
  }, [])

  const today = new Date()
  const curY  = today.getFullYear()
  const curM  = today.getMonth() + 1
  let fromY = curY, fromM = curM - 12
  while (fromM <= 0) { fromM += 12; fromY-- }
  const rangeFrom = `${fromY}-${String(fromM).padStart(2, '0')}-01`
  const rangeTo   = `${curY}-${String(curM).padStart(2, '0')}-${String(daysInMonth(curY, curM)).padStart(2, '0')}`

  return (
    <div>
      <div className="page-header">
        <h1 className="page-title">Rolling 12 Months</h1>
        <button className="btn btn-secondary" onClick={() => downloadExport('rolling-months', rangeFrom, rangeTo)}>
          <Download size={14} strokeWidth={1.75} /> CSV
        </button>
      </div>

      {loading && <div className="state-center">Loading…</div>}
      {error   && <div className="state-center" style={{ color: '#dc2626' }}>{error}</div>}

      {!loading && !error && (
        <>
          <div className="card">
            <div className="card-title">Wages by Department (monthly)</div>
            <ResponsiveContainer width="100%" height={280}>
              <BarChart data={chartData} margin={{ top: 4, right: 16, left: 16, bottom: 0 }}>
                <XAxis dataKey="label" tick={{ fontSize: 10 }} />
                <YAxis tickFormatter={v => `£${Math.round(v / 1000)}k`} tick={{ fontSize: 11 }} width={55} />
                <Tooltip formatter={(v: unknown) => fmtMoney(Number(v))} />
                <Legend itemSorter={item => -deptCols.findIndex(dep => dep.name === item.dataKey)} />
                {deptCols.map(dep => (
                  <Bar key={dep.id} dataKey={dep.name} stackId="a" fill={dep.color} />
                ))}
              </BarChart>
            </ResponsiveContainer>
          </div>

          <div className="card">
            <table className="data-table">
              <thead>
                <tr>
                  <th>Month</th>
                  <th className="right">Total Wages</th>
                  <th className="right">Budget</th>
                  <th className="right">Var vs Budget</th>
                  <th className="right">% Budget</th>
                  <th className="right">Net Sales</th>
                  <th className="right">% Net Sales</th>
                  <th className="right">PY Net Sales</th>
                </tr>
              </thead>
              <tbody>
                {[...rows].reverse().map((r, i) => {
                  const pctB = r.budget != null && r.budget > 0 ? (r.wages / r.budget) * 100 : null
                  const pctS = r.sales > 0 ? (r.wages / r.sales) * 100 : null
                  const vari = r.budget != null ? r.wages - r.budget : null
                  return (
                    <tr key={i} style={r.partial ? { opacity: 0.7 } : {}}>
                      <td>
                        {r.label}
                        {r.partial && <span className="partial-badge">current</span>}
                      </td>
                      <td className="right">{fmtMoney(r.wages)}</td>
                      <td className="right">{r.budget != null ? fmtMoney(r.budget) : '—'}</td>
                      <td className="right">
                        {vari != null && (
                          <span className={vari > 0 ? 'variance-over' : 'variance-under'}>
                            {vari > 0 ? '+' : ''}{fmtMoney(vari)}
                          </span>
                        )}
                      </td>
                      <td className="right">
                        {pctB != null ? <span className={`pct-badge ${pctClass(pctB)}`}>{fmtDelta(pctB)}</span> : '—'}
                      </td>
                      <td className="right">{r.sales > 0 ? fmtMoney(r.sales) : '—'}</td>
                      <td className="right">{pctS != null ? `${pctS.toFixed(1)}%` : '—'}</td>
                      <td className="right">{r.pySales > 0 ? fmtMoney(r.pySales) : '—'}</td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        </>
      )}
    </div>
  )
}
