import { useEffect, useMemo, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import {
  type AllDecisionRow,
  fetchAllDecisions,
  postGenerateAllDecisions,
} from '../../api/grading'
import { fetchGradingOverview } from '../../api/session'
import {
  GRADING_BELOW_SIXTY_DECISIONS_PATH,
  GRADING_PATH,
} from './gradingPaths'

type SourceKey = 'auto' | 'manual' | 'pending'
type GenderKey = 'boys' | 'girls' | 'other'

function displayScore(value: unknown): string {
  if (value === null || value === undefined || value === '') return '—'
  if (typeof value === 'number' && Number.isFinite(value)) return value.toFixed(2)
  const numeric = Number(value)
  return Number.isFinite(numeric) ? numeric.toFixed(2) : String(value)
}

function numericScore(value: unknown): number | null {
  if (value === null || value === undefined || value === '') return null
  const numeric = typeof value === 'number' ? value : Number(value)
  return Number.isFinite(numeric) ? numeric : null
}

function fieldText(value: unknown): string {
  return String(value ?? '').trim()
}

function decisionBadgeClass(decision: string): string {
  switch (decision) {
    case 'Pass':
      return 'text-bg-success'
    case 'Repeat Class':
    case 'Expel':
      return 'text-bg-danger'
    case 'Make-up exam in fall':
    case 'Deferred decision':
      return 'text-bg-info'
    case 'Withdrawn':
      return 'text-bg-secondary'
    default:
      return 'text-bg-secondary'
  }
}

function sourceMeta(source: string): { className: string; label: string } {
  switch ((source || 'pending') as SourceKey) {
    case 'auto':
      return { className: 'text-bg-success', label: 'Auto' }
    case 'manual':
      return { className: 'text-bg-primary', label: 'Manual' }
    default:
      return { className: 'text-bg-warning', label: 'Pending' }
  }
}

function genderBucket(value: unknown): GenderKey {
  const normalized = fieldText(value).toLowerCase()
  if (['male', 'm', 'boy', 'boys'].includes(normalized)) return 'boys'
  if (['female', 'f', 'girl', 'girls'].includes(normalized)) return 'girls'
  return 'other'
}

function pct(count: number, total: number): string {
  if (total <= 0) return '0.0%'
  return `${((count / total) * 100).toFixed(1)}%`
}

function normalizePayload(payload: unknown): {
  rows: AllDecisionRow[]
  generated: boolean
  schoolYear: string
} {
  if (!payload || typeof payload !== 'object') {
    return { rows: [], generated: false, schoolYear: '' }
  }

  const body = payload as {
    rows?: unknown
    generated?: unknown
    school_year?: unknown
  }

  return {
    rows: Array.isArray(body.rows) ? (body.rows as AllDecisionRow[]) : [],
    generated: Boolean(body.generated),
    schoolYear: fieldText(body.school_year),
  }
}

export function GradingDecisionsPage() {
  const [searchParams, setSearchParams] = useSearchParams()
  const schoolYear = searchParams.get('school_year') ?? ''

  const [filterYear, setFilterYear] = useState(schoolYear)
  const [rows, setRows] = useState<AllDecisionRow[]>([])
  const [generated, setGenerated] = useState(false)
  const [loading, setLoading] = useState(true)
  const [generating, setGenerating] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [success, setSuccess] = useState<string | null>(null)

  useEffect(() => {
    if (schoolYear) {
      setFilterYear(schoolYear)
      return
    }
    let cancelled = false
    ;(async () => {
      try {
        const overview = await fetchGradingOverview()
        if (cancelled) return
        const next = new URLSearchParams(searchParams)
        if ((overview.school_year ?? '').trim() !== '') {
          next.set('school_year', String(overview.school_year))
          setSearchParams(next, { replace: true })
        }
      } catch (e) {
        if (!cancelled) {
          setError(e instanceof ApiHttpError ? e.message : 'Unable to determine the current school year.')
          setLoading(false)
        }
      }
    })()
    return () => {
      cancelled = true
    }
  }, [schoolYear, searchParams, setSearchParams])

  async function loadRows(params: URLSearchParams, activeSchoolYear: string) {
    if (!activeSchoolYear) {
      setRows([])
      setGenerated(false)
      setLoading(false)
      return
    }

    setLoading(true)
    try {
      const payload = normalizePayload(await fetchAllDecisions(params))
      setRows(payload.rows)
      setGenerated(payload.generated)
      setError(null)
    } catch (e: unknown) {
      setError(e instanceof ApiHttpError ? e.message : 'Unable to load all decisions.')
      setRows([])
      setGenerated(false)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    void loadRows(searchParams, schoolYear)
  }, [schoolYear, searchParams])

  const stats = useMemo(() => {
    const totals = { Pass: 0, Other: 0, Pending: 0, Total: rows.length, Trophy: 0 }
    const gender = {
      all: { boys: 0, girls: 0, other: 0 },
      pass: { boys: 0, girls: 0, other: 0 },
      trophy: { boys: 0, girls: 0, other: 0 },
    }

    for (const row of rows) {
      const decision = fieldText(row.decision)
      const bucket = genderBucket(row.gender)

      gender.all[bucket] += 1
      if (decision === 'Pass') {
        totals.Pass += 1
        gender.pass[bucket] += 1
      } else if (decision === '' || fieldText(row.source) === 'pending') {
        totals.Pending += 1
      } else {
        totals.Other += 1
      }

      if (Boolean(row.is_trophy)) {
        totals.Trophy += 1
        gender.trophy[bucket] += 1
      }
    }

    return { totals, gender }
  }, [rows])

  async function onGenerate() {
    if (!schoolYear) return

    setGenerating(true)
    setError(null)
    setSuccess(null)
    try {
      const payload = await postGenerateAllDecisions({ school_year: schoolYear })
      await loadRows(searchParams, schoolYear)
      setSuccess(`Decisions generated for ${payload.saved_count ?? 0} students.`)
    } catch (e: unknown) {
      setError(e instanceof ApiHttpError ? e.message : 'Unable to generate decisions.')
    } finally {
      setGenerating(false)
    }
  }

  return (
    <div className="container-fluid py-3">
      <div className="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
        <div>
          <h2 className="mb-1">Student Decisions — All Students</h2>
          <div className="text-muted">
            {schoolYear || 'Current school year'}
            <span className={`badge ms-2 ${generated ? 'text-bg-success' : 'text-bg-warning'}`}>
              {generated ? 'Saved' : 'Not yet generated'}
            </span>
          </div>
        </div>
        <div className="d-flex gap-2 flex-wrap d-print-none">
          <button type="button" className="btn btn-outline-secondary btn-sm" onClick={() => window.print()}>
            Print Stats
          </button>
          <Link className="btn btn-outline-primary btn-sm" to={`${GRADING_BELOW_SIXTY_DECISIONS_PATH}?school_year=${encodeURIComponent(schoolYear)}`}>
            Below-60 Decisions
          </Link>
          <Link className="btn btn-outline-secondary btn-sm" to={`${GRADING_PATH}${schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''}`}>
            Grading
          </Link>
        </div>
      </div>

      <div className="card shadow-sm mb-3 d-print-none">
        <div className="card-body py-3">
          <form
            className="row g-2 align-items-end justify-content-center"
            onSubmit={(event) => {
              event.preventDefault()
              const next = new URLSearchParams()
              if (filterYear.trim() !== '') next.set('school_year', filterYear.trim())
              setSearchParams(next)
            }}
          >
            <div className="col-12 col-sm-auto">
              <label className="form-label mb-1 small fw-semibold">School Year</label>
              <input
                className="form-control form-control-sm"
                style={{ minWidth: 180 }}
                value={filterYear}
                onChange={(event) => setFilterYear(event.target.value)}
                placeholder="2025-2026"
              />
            </div>
            <div className="col-12 col-sm-auto">
              <button type="submit" className="btn btn-sm btn-secondary">
                Apply
              </button>
            </div>
            <div className="col-12 col-sm-auto">
              <button
                type="button"
                className="btn btn-sm btn-primary"
                disabled={!schoolYear || generating}
                onClick={() => void onGenerate()}
              >
                {generating ? 'Generating…' : generated ? 'Regenerate Decisions' : 'Generate Decisions'}
              </button>
            </div>
          </form>
          <div className="text-muted small mt-2">
            Year score ≥ 60 → <strong>Pass</strong> (auto) | Year score &lt; 60 → pulled from below-60 decisions
          </div>
        </div>
      </div>

      <div className="row g-3 mb-3 d-print-none">
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-success shadow-sm h-100">
            <div className="card-body text-center">
              <div className="fs-4 fw-bold text-success">{stats.totals.Pass}</div>
              <div className="text-muted small">Pass</div>
            </div>
          </div>
        </div>
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-primary shadow-sm h-100">
            <div className="card-body text-center">
              <div className="fs-4 fw-bold text-primary">{stats.totals.Other}</div>
              <div className="text-muted small">Other Decision</div>
            </div>
          </div>
        </div>
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-warning shadow-sm h-100">
            <div className="card-body text-center">
              <div className="fs-4 fw-bold text-warning">{stats.totals.Pending}</div>
              <div className="text-muted small">Pending</div>
            </div>
          </div>
        </div>
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card shadow-sm h-100">
            <div className="card-body text-center">
              <div className="fs-4 fw-bold">{stats.totals.Total}</div>
              <div className="text-muted small">Total</div>
            </div>
          </div>
        </div>
      </div>

      {success ? <div className="alert alert-success d-print-none">{success}</div> : null}
      {error ? <div className="alert alert-danger">{error}</div> : null}
      {loading ? <p className="text-muted">Loading decisions…</p> : null}

      {!loading && rows.length === 0 ? (
        <div className="alert alert-info">No semester scores found for this school year.</div>
      ) : null}

      {!loading && rows.length > 0 ? (
        <>
          <div className="d-none d-print-block mb-3">
            <div className="text-center border-bottom pb-2 mb-3">
              <h2 className="mb-1">Student Decisions Summary — {schoolYear}</h2>
              <p className="small text-muted mb-0">
                Trophy counts use the same year-score rule as the trophy final page.
              </p>
            </div>
            <h3 className="h5 mb-2">Print Stats</h3>
            <div className="table-responsive">
              <table className="table table-bordered align-middle mb-0">
                <thead>
                  <tr>
                    <th>Metric</th>
                    <th className="text-center">Count</th>
                    <th className="text-center">Percent</th>
                    <th className="text-center">Boys</th>
                    <th className="text-center">Boys %</th>
                    <th className="text-center">Girls</th>
                    <th className="text-center">Girls %</th>
                  </tr>
                </thead>
                <tbody>
                  <tr>
                    <td>Total Students</td>
                    <td className="text-center">{stats.totals.Total}</td>
                    <td className="text-center">100.0%</td>
                    <td className="text-center">{stats.gender.all.boys}</td>
                    <td className="text-center">{pct(stats.gender.all.boys, stats.totals.Total)}</td>
                    <td className="text-center">{stats.gender.all.girls}</td>
                    <td className="text-center">{pct(stats.gender.all.girls, stats.totals.Total)}</td>
                  </tr>
                  <tr>
                    <td>Pass</td>
                    <td className="text-center">{stats.totals.Pass}</td>
                    <td className="text-center">{pct(stats.totals.Pass, stats.totals.Total)}</td>
                    <td className="text-center">{stats.gender.pass.boys}</td>
                    <td className="text-center">{pct(stats.gender.pass.boys, stats.totals.Pass)}</td>
                    <td className="text-center">{stats.gender.pass.girls}</td>
                    <td className="text-center">{pct(stats.gender.pass.girls, stats.totals.Pass)}</td>
                  </tr>
                  <tr>
                    <td>Trophies</td>
                    <td className="text-center">{stats.totals.Trophy}</td>
                    <td className="text-center">{pct(stats.totals.Trophy, stats.totals.Total)}</td>
                    <td className="text-center">{stats.gender.trophy.boys}</td>
                    <td className="text-center">{pct(stats.gender.trophy.boys, stats.totals.Trophy)}</td>
                    <td className="text-center">{stats.gender.trophy.girls}</td>
                    <td className="text-center">{pct(stats.gender.trophy.girls, stats.totals.Trophy)}</td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>

          <div className="table-responsive">
            <table className="table table-bordered table-striped align-middle">
              <thead className="table-light">
                <tr>
                  <th>Student Name</th>
                  <th>Section</th>
                  <th className="text-center">Fall Score</th>
                  <th className="text-center">Spring Score</th>
                  <th className="text-center">Year Score</th>
                  <th className="text-center">Decision</th>
                  <th className="text-center">Source</th>
                  <th>Notes</th>
                </tr>
              </thead>
              <tbody>
                {rows.map((row) => {
                  const studentId = Number(row.student_id ?? 0)
                  const studentName = `${fieldText(row.firstname)} ${fieldText(row.lastname)}`.trim() || 'N/A'
                  const yearScore = numericScore(row.year_score)
                  const rowClass = yearScore !== null && yearScore < 60
                    ? (yearScore < 50 ? 'table-danger' : 'table-warning')
                    : ''
                  const decision = fieldText(row.decision)
                  const source = sourceMeta(fieldText(row.source))

                  return (
                    <tr key={studentId || studentName} className={rowClass}>
                      <td>{studentName}</td>
                      <td>{fieldText(row.class_section_name) || '—'}</td>
                      <td className="text-center">{displayScore(row.fall_score)}</td>
                      <td className="text-center">{displayScore(row.spring_score)}</td>
                      <td className="text-center fw-semibold">{displayScore(row.year_score)}</td>
                      <td className="text-center">
                        {decision ? (
                          <div className="d-inline-flex flex-wrap gap-1 justify-content-center">
                            <span className={`badge ${decisionBadgeClass(decision)}`}>{decision}</span>
                            {row.is_trophy ? <span className="badge text-bg-dark">Trophy</span> : null}
                          </div>
                        ) : (
                          <span className="text-muted small">—</span>
                        )}
                      </td>
                      <td className="text-center">
                        <span className={`badge ${source.className}`}>{source.label}</span>
                      </td>
                      <td className="text-muted small" style={{ whiteSpace: 'pre-line' }}>
                        {fieldText(row.notes) || '—'}
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        </>
      ) : null}
    </div>
  )
}
