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

function fmt(d: Date): string { return d.toISOString().slice(0, 10) }
function addDays(d: Date, n: number): Date { const r = new Date(d); r.setDate(r.getDate() + n); return r }
function daysInMonth(y: number, m: number): number { return new Date(y, m, 0).getDate() }
function fmtMoney(n: number): string { return `£${Math.round(n).toLocaleString('en-GB')}` }
function pctClass(pct: number): string { return pct <= 100 ? 'pct-green' : pct <= 110 ? 'pct-amber' : 'pct-red' }

const DEPT_COLORS = ['#065f46','#059669','#0891b2','#7c3aed','#c2410c','#b45309','#0f766e','#4338ca','#be185d','#15803d']

export default function Monthly() {
  const today = new Date()
  const [year,  setYear]  = useState(today.getFullYear())
  const [month, setMonth] = useState(today.getMonth() + 1)  // 1-based

  const [depts,     setDepts]     = useState<DeptActuals[]>([])
  const [scheduled, setScheduled] = useState<Record<string, Record<string, number>>>({})  // dept_id → date → cost
  const [netSales,  setNetSales]  = useState(0)
  const [budget,    setBudget]    = useState<number | null>(null)
  const [showOncosts, setShowOncosts] = useState(true)
  const [loading, setLoading] = useState(true)
  const [error,   setError]   = useState<string | null>(null)

  const dim      = daysInMonth(year, month)
  const monthStr = `${year}-${String(month).padStart(2, '0')}`
  const fromStr  = `${monthStr}-01`
  const toStr    = `${monthStr}-${String(dim).padStart(2, '0')}`
  const todayStr = fmt(today)
  const isCurrentMonth = year === today.getFullYear() && month === today.getMonth() + 1

  const load = useCallback(async () => {
    setLoading(true); setError(null)
    try {
      const [actRes, schRes, salesRes, budRes] = await Promise.all([
        getActuals(fromStr, toStr),
        getScheduled(todayStr, toStr),
        getNetSales(fromStr, todayStr),
        getBudgets(),
      ])
      setDepts(actRes.departments)
      setShowOncosts(actRes.show_oncosts)

      // Build scheduled map
      const schMap: Record<string, Record<string, number>> = {}
      for (const dep of schRes.departments) {
        schMap[dep.department_id] = {}
        for (const [date, val] of Object.entries(dep.days)) {
          schMap[dep.department_id][date] = val.cost
        }
      }
      setScheduled(schMap)

      setNetSales(salesRes.days.reduce((s, d) => s + d.net_sales, 0))

      const bRow = budRes.budgets.find(b => b.month === `${fromStr}`)
      setBudget(bRow ? bRow.budget_amount : null)
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : 'Failed to load')
    } finally {
      setLoading(false)
    }
  }, [fromStr, toStr, todayStr])

  useEffect(() => { load() }, [load])

  const prev = () => { if (month === 1) { setYear(y => y - 1); setMonth(12) } else { setMonth(m => m - 1) } }
  const next = () => { if (month === 12) { setYear(y => y + 1); setMonth(1) } else { setMonth(m => m + 1) } }

  // Build dept summary: actual MTD + forecast EOM
  const deptSummary = depts.map((dep, idx) => {
    const actualMTD = Object.entries(dep.days)
      .filter(([d]) => d <= todayStr)
      .reduce((s, [, v]) => s + v.cost, 0)

    // Forecast remaining days
    let forecastRem = 0
    for (let day = 1; day <= dim; day++) {
      const dateStr = `${monthStr}-${String(day).padStart(2, '0')}`
      if (dateStr <= todayStr) continue

      // Priority: rota → prior week same DoW actual
      const rotaCost = schMap(dep.department_id, dateStr)
      if (rotaCost != null) {
        forecastRem += rotaCost
        continue
      }
      const priorDate = addDays(new Date(dateStr + 'T00:00:00'), -7)
      const priorStr  = fmt(priorDate)
      const priorCost = dep.days[priorStr]?.cost
      if (priorCost != null) forecastRem += priorCost
    }

    return {
      department_id:   dep.department_id,
      department_name: dep.department_name,
      actual_mtd:      actualMTD,
      forecast_eom:    actualMTD + forecastRem,
      color:           DEPT_COLORS[idx % DEPT_COLORS.length],
    }
  }).sort((a, b) => b.forecast_eom - a.forecast_eom)

  function schMap(deptId: string, date: string): number | null {
    return scheduled[deptId]?.[date] ?? null
  }

  const totalActual   = deptSummary.reduce((s, d) => s + d.actual_mtd, 0)
  const totalForecast = deptSummary.reduce((s, d) => s + d.forecast_eom, 0)
  const pctBudget     = budget != null && budget > 0 ? (totalForecast / budget) * 100 : null
  const pctSales      = netSales > 0 ? (totalActual / netSales) * 100 : null
  const variance      = budget != null ? totalForecast - budget : null

  // Build chart data: group by week
  const weeks: { label: string; actual: number; forecast: number; isPast: boolean }[] = []
  for (let w = 0; w * 7 < dim; w++) {
    const wStart = w * 7 + 1
    const wEnd   = Math.min(wStart + 6, dim)
    const wEndDate = new Date(`${monthStr}-${String(wEnd).padStart(2, '0')}T00:00:00`)
    const isPast = wEndDate < today

    let actual = 0, forecast = 0
    for (let day = wStart; day <= wEnd; day++) {
      const dateStr = `${monthStr}-${String(day).padStart(2, '0')}`
      const isActual = dateStr <= todayStr
      const total = deptSummary.reduce((s, dep) => {
        if (isActual) return s + (depts.find(d => d.department_id === dep.department_id)?.days[dateStr]?.cost ?? 0)
        const rota = schMap(dep.department_id, dateStr)
        if (rota != null) return s + rota
        const prior = depts.find(d => d.department_id === dep.department_id)?.days[fmt(addDays(new Date(dateStr + 'T00:00:00'), -7))]?.cost ?? 0
        return s + prior
      }, 0)
      if (isActual) actual += total; else forecast += total
    }

    weeks.push({ label: `W${w + 1}`, actual, forecast, isPast })
  }

  const monthLabel = new Date(year, month - 1, 1).toLocaleDateString('en-GB', { month: 'long', year: 'numeric' })

  return (
    <div>
      <div className="page-header">
        <h1 className="page-title">Monthly View</h1>
        <button className="btn btn-secondary" onClick={() => downloadExport('monthly', fromStr, toStr)}>
          <Download size={14} strokeWidth={1.75} /> CSV
        </button>
      </div>

      <div className="period-nav" style={{ marginBottom: 20 }}>
        <button className="btn btn-secondary" onClick={prev}><ChevronLeft size={16} strokeWidth={1.75} /></button>
        <span className="period-label">{monthLabel}</span>
        <button className="btn btn-secondary" onClick={next} disabled={isCurrentMonth}><ChevronRight size={16} strokeWidth={1.75} /></button>
      </div>

      <div className="summary-grid">
        <div className="summary-card">
          <div className="label">Actual MTD</div>
          <div className="value">{fmtMoney(totalActual)}</div>
        </div>
        <div className="summary-card">
          <div className="label">Forecast EOM</div>
          <div className="value">{fmtMoney(totalForecast)}</div>
          <div className="sub">rota + prior-week actual</div>
        </div>
        <div className="summary-card">
          <div className="label">Monthly Budget</div>
          <div className="value">{budget != null ? fmtMoney(budget) : '—'}</div>
        </div>
        <div className="summary-card">
          <div className="label">% Budget (Forecast)</div>
          <div className="value">
            {pctBudget != null
              ? <span className={`pct-badge ${pctClass(pctBudget)}`}>{pctBudget.toFixed(1)}%</span>
              : '—'}
          </div>
          {variance != null && (
            <div className={`sub ${variance > 0 ? 'variance-over' : 'variance-under'}`}>
              {variance > 0 ? `+${fmtMoney(variance)} over` : `${fmtMoney(Math.abs(variance))} under`}
            </div>
          )}
        </div>
        <div className="summary-card">
          <div className="label">Net Sales MTD</div>
          <div className="value">{fmtMoney(netSales)}</div>
        </div>
        <div className="summary-card">
          <div className="label">% Net Sales</div>
          <div className="value">{pctSales != null ? `${pctSales.toFixed(1)}%` : '—'}</div>
        </div>
      </div>

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

      {!loading && !error && (
        <>
          {/* Stacked bar chart */}
          <div className="card">
            <div className="card-title">Weekly Breakdown</div>
            <ResponsiveContainer width="100%" height={260}>
              <BarChart data={weeks} margin={{ top: 4, right: 16, left: 16, bottom: 0 }}>
                <XAxis dataKey="label" tick={{ fontSize: 12 }} />
                <YAxis tickFormatter={v => `£${Math.round(v / 1000)}k`} tick={{ fontSize: 11 }} width={55} />
                <Tooltip formatter={(v: number) => fmtMoney(v)} />
                <Legend />
                {deptSummary.map(dep => (
                  <Bar key={dep.department_id} dataKey={dep.department_name} stackId="a" fill={dep.color}>
                    {weeks.map((w, i) => (
                      <Cell key={i} fill={dep.color} opacity={w.isPast ? 1 : 0.4} />
                    ))}
                  </Bar>
                ))}
              </BarChart>
            </ResponsiveContainer>
          </div>

          {/* Dept breakdown table */}
          <div className="card">
            <table className="data-table">
              <thead>
                <tr>
                  <th>Department</th>
                  <th className="right">Actual MTD</th>
                  <th className="right">Forecast → EOM</th>
                  <th className="right">Budget</th>
                  <th className="right">% Budget</th>
                  <th className="right">Variance</th>
                </tr>
              </thead>
              <tbody>
                {deptSummary.map(dep => {
                  const dp = budget != null && budget > 0 ? (dep.forecast_eom / budget) * 100 : null
                  const dv = budget != null ? dep.forecast_eom - budget : null
                  return (
                    <tr key={dep.department_id}>
                      <td><span style={{ display: 'inline-block', width: 10, height: 10, borderRadius: '50%', background: dep.color, marginRight: 8 }} />{dep.department_name}</td>
                      <td className="right">{fmtMoney(dep.actual_mtd)}</td>
                      <td className="right">{fmtMoney(dep.forecast_eom)}</td>
                      <td className="right">—</td>
                      <td className="right">
                        {dp != null ? <span className={`pct-badge ${pctClass(dp)}`}>{dp.toFixed(1)}%</span> : '—'}
                      </td>
                      <td className="right">
                        {dv != null && <span className={dv > 0 ? 'variance-over' : 'variance-under'}>{dv > 0 ? '+' : ''}{fmtMoney(dv)}</span>}
                      </td>
                    </tr>
                  )
                })}
                <tr className="total-row">
                  <td>Total</td>
                  <td className="right">{fmtMoney(totalActual)}</td>
                  <td className="right">{fmtMoney(totalForecast)}</td>
                  <td className="right">{budget != null ? fmtMoney(budget) : '—'}</td>
                  <td className="right">
                    {pctBudget != null ? <span className={`pct-badge ${pctClass(pctBudget)}`}>{pctBudget.toFixed(1)}%</span> : '—'}
                  </td>
                  <td className="right">
                    {variance != null && <span className={variance > 0 ? 'variance-over' : 'variance-under'}>{variance > 0 ? '+' : ''}{fmtMoney(variance)}</span>}
                  </td>
                </tr>
              </tbody>
            </table>
            {showOncosts && <p className="footnote">Includes estimated employer on-costs. Final payroll figures are in Sage.</p>}
          </div>
        </>
      )}
    </div>
  )
}
