import { type FormEvent, useEffect, useMemo, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { useSchoolYearOptions } from '../../hooks/useSchoolYearOptions'
import { fetchCombinedReport } from '../../api/reportsCombined'
import { REPORT_COMBINED_PATH } from './reportPaths'

type ScorePredictorStudent = {
  student_id?: number
  school_id?: string | null
  firstname?: string | null
  lastname?: string | null
  class_section_id?: number | string | null
  fall_score?: string | number | null
  spring_score?: string | number | null
  final_average?: string | number | null
  required_spring_score?: string | number | null
  winning_risk?: string | null
  required_spring_to_pass?: string | number | null
  failure_risk?: string | null
  status?: string | null
  trophy_awarded?: boolean
  trophy_reason?: string | null
}

type ScorePredictorSection = {
  class_section_id?: number | string | null
  class_section_name?: string | null
}

type ScorePredictorPayload = {
  ok?: boolean
  students?: ScorePredictorStudent[]
  school_year?: string | null
  class_sections?: ScorePredictorSection[]
  selected_class_section_id?: number | string | null
  semester?: string | null
  message?: string | null
}

type SortKey =
  | 'school_id'
  | 'firstname'
  | 'lastname'
  | 'class_name'
  | 'fall_score'
  | 'spring_score'
  | 'final_average'
  | 'required_spring_score'
  | 'required_spring_to_pass'

function asNumber(value: unknown): number | null {
  if (typeof value === 'number' && Number.isFinite(value)) return value
  if (typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Number(value))) return Number(value)
  return null
}

function displayValue(value: unknown, fallback = 'N/A') {
  if (value == null || value === '') return fallback
  return String(value)
}

function sortArrow(active: boolean, direction: 'asc' | 'desc') {
  if (!active) return '↕'
  return direction === 'asc' ? '↑' : '↓'
}

function trophyChanceBadge(risk?: string | null) {
  switch (risk) {
    case 'Achieved Trophy':
      return <span className="text-success fw-bold">Trophy Achieved</span>
    case 'Top 3 Trophy':
      return <span className="text-primary fw-bold">Top 3 Trophy</span>
    case 'Low':
      return <span className="text-success fw-bold">Trophy within Reach</span>
    case 'Medium':
      return <span className="text-warning fw-bold">Needs Strong Effort</span>
    case 'High':
      return <span className="text-danger fw-bold">Unlikely to Win Trophy</span>
    case 'Unreachable':
      return <span className="badge text-bg-warning">Not Possible</span>
    case 'New student':
      return <span className="text-muted fst-italic">No Data Yet</span>
    default:
      return <span className="text-body-secondary">Unknown</span>
  }
}

function failRiskBadge(risk?: string | null) {
  switch (risk) {
    case 'Low':
      return <span className="text-success fw-bold">Safe</span>
    case 'Medium':
      return <span className="text-warning fw-bold">Some Risk</span>
    case 'High':
      return <span className="text-danger fw-bold">At Risk</span>
    case 'Unlikely to pass':
      return <span className="badge text-bg-danger">Cannot Pass</span>
    case 'New student':
      return <span className="text-muted fst-italic">No Data Yet</span>
    default:
      return <span className="text-body-secondary">Unknown</span>
  }
}

function statusBadge(status?: string | null) {
  switch (status) {
    case 'Passed':
      return <span className="badge text-bg-success">Passed</span>
    case 'Failed':
      return <span className="badge text-bg-danger">Failed</span>
    case 'Can pass':
      return <span className="badge text-bg-primary">Can pass</span>
    case 'May fail':
      return <span className="badge text-bg-warning">May fail</span>
    case 'Undetermined':
      return <span className="badge text-bg-secondary">Undetermined</span>
    default:
      return <span className="badge text-bg-light">N/A</span>
  }
}

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

  const [raw, setRaw] = useState<ScorePredictorPayload | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [sortConfig, setSortConfig] = useState<{ key: SortKey; direction: 'asc' | 'desc' }>({
    key: 'lastname',
    direction: 'asc',
  })

  useEffect(() => {
    let cancelled = false
    ;(async () => {
      setLoading(true)
      setError(null)
      try {
        const res = (await fetchCombinedReport({
          school_year: schoolYear || null,
          class_section_id: classSectionId || null,
        })) as ScorePredictorPayload
        if (!cancelled) setRaw(res)
      } catch (e) {
        if (!cancelled) {
          setError(e instanceof ApiHttpError ? e.message : 'Unable to load score analysis.')
          setRaw(null)
        }
      } finally {
        if (!cancelled) setLoading(false)
      }
    })()
    return () => {
      cancelled = true
    }
  }, [schoolYear, classSectionId])

  const students = Array.isArray(raw?.students) ? raw.students : []
  const classSections = Array.isArray(raw?.class_sections) ? raw.class_sections : []
  const selectedYear = schoolYear || raw?.school_year || ''
  const selectedSemester = raw?.semester || ''

  const sectionMap = useMemo(() => {
    return Object.fromEntries(
      classSections.map((section) => [
        String(section.class_section_id ?? ''),
        section.class_section_name || `Section ${String(section.class_section_id ?? '')}`,
      ]),
    )
  }, [classSections])

  const sortedStudents = useMemo(() => {
    const rows = [...students]
    rows.sort((left, right) => {
      const direction = sortConfig.direction === 'asc' ? 1 : -1
      const leftClass = sectionMap[String(left.class_section_id ?? '')] ?? `Section ${String(left.class_section_id ?? '')}`
      const rightClass = sectionMap[String(right.class_section_id ?? '')] ?? `Section ${String(right.class_section_id ?? '')}`

      if (
        sortConfig.key === 'fall_score' ||
        sortConfig.key === 'spring_score' ||
        sortConfig.key === 'final_average' ||
        sortConfig.key === 'required_spring_score' ||
        sortConfig.key === 'required_spring_to_pass'
      ) {
        const a = asNumber(left[sortConfig.key])
        const b = asNumber(right[sortConfig.key])
        if (a == null && b == null) return 0
        if (a == null) return 1
        if (b == null) return -1
        return (a - b) * direction
      }

      const a =
        sortConfig.key === 'class_name'
          ? leftClass
          : String(left[sortConfig.key] ?? '')
      const b =
        sortConfig.key === 'class_name'
          ? rightClass
          : String(right[sortConfig.key] ?? '')
      return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }) * direction
    })
    return rows
  }, [students, sortConfig, sectionMap])

  const summary = useMemo(() => {
    const trophyCounts: Record<string, number> = {}
    const statusCounts = { Passed: 0, Failed: 0, 'Can pass': 0, 'May fail': 0, Undetermined: 0 }
    const riskCounts = { Low: 0, Medium: 0, High: 0, 'Unlikely to pass': 0, 'New student': 0 }

    for (const student of students) {
      const sectionId = String(student.class_section_id ?? '')
      if (student.trophy_awarded) {
        trophyCounts[sectionId] = (trophyCounts[sectionId] ?? 0) + 1
      }

      const status = String(student.status ?? 'Undetermined') as keyof typeof statusCounts
      statusCounts[status] = (statusCounts[status] ?? 0) + 1

      const risk = String(student.failure_risk ?? 'New student') as keyof typeof riskCounts
      riskCounts[risk] = (riskCounts[risk] ?? 0) + 1
    }

    const totalStudents = students.length
    const totalTrophies = Object.values(trophyCounts).reduce((sum, value) => sum + value, 0)
    const passRate = totalStudents > 0 ? ((statusCounts.Passed / totalStudents) * 100).toFixed(1) : '0.0'
    const failRate = totalStudents > 0 ? ((statusCounts.Failed / totalStudents) * 100).toFixed(1) : '0.0'
    const pendingCount = statusCounts.Undetermined + statusCounts['Can pass'] + statusCounts['May fail']
    const pendingRate = totalStudents > 0 ? ((pendingCount / totalStudents) * 100).toFixed(1) : '0.0'

    return {
      trophyCounts,
      statusCounts,
      riskCounts,
      totalStudents,
      totalTrophies,
      passRate,
      failRate,
      pendingCount,
      pendingRate,
    }
  }, [students])

  function applyFilter(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    const formData = new FormData(event.currentTarget)
    const next = new URLSearchParams()
    const nextYear = String(formData.get('school_year') ?? '').trim()
    const nextClassSectionId = String(formData.get('class_section_id') ?? '').trim()
    if (nextYear) next.set('school_year', nextYear)
    if (nextClassSectionId) next.set('class_section_id', nextClassSectionId)
    setSearchParams(next)
  }

  function requestSort(key: SortKey) {
    setSortConfig((prev) =>
      prev.key === key
        ? { key, direction: prev.direction === 'asc' ? 'desc' : 'asc' }
        : { key, direction: 'asc' },
    )
  }

  const trophySummaryIds = Object.keys(summary.trophyCounts).sort((left, right) => {
    const a = sectionMap[left] ?? left
    const b = sectionMap[right] ?? right
    return a.localeCompare(b, undefined, { sensitivity: 'base' })
  })

  const sortableHeaderCellStyle = {
    color: '#0f172a',
    fontWeight: 600,
    cursor: 'pointer',
    userSelect: 'none' as const,
  }
  const { options, selectedYear: defaultYear } = useSchoolYearOptions({
    preferredYear: selectedYear,
  })
  const schoolYearOptions = options.length > 0 ? options : [{ value: defaultYear, label: defaultYear }]

  return (
    <div className="container-fluid py-4">
      <h2 className="text-center mt-2 mb-3">Student Success &amp; Risk Report</h2>

      <div className="mb-4 text-center">
        <p className="text-muted small mb-1">Active Students</p>
        <div className="display-4 fw-semibold">{summary.totalStudents}</div>
        <p className="text-muted small mb-0">Reflects only currently active students.</p>
      </div>

      <form className="row g-3 mb-4 align-items-end" onSubmit={applyFilter}>
        <div className="col-md-6 col-lg-4">
          <label htmlFor="school_year" className="form-label">School Year</label>
          <select id="school_year" name="school_year" className="form-select" defaultValue={selectedYear || defaultYear}>
            {schoolYearOptions.map((option) => (
              <option key={option.value} value={option.value}>
                {option.label}
              </option>
            ))}
          </select>
        </div>

        <div className="col-md-6 col-lg-4">
          <label htmlFor="class_section_id" className="form-label">Class Section</label>
          <div className="input-group">
            <select
              id="class_section_id"
              name="class_section_id"
              className="form-select"
              defaultValue={classSectionId}
            >
              <option value="">-- All Sections --</option>
              {classSections.map((section) => (
                <option key={String(section.class_section_id ?? '')} value={String(section.class_section_id ?? '')}>
                  {section.class_section_name ?? `Section ${String(section.class_section_id ?? '')}`}
                </option>
              ))}
            </select>
            <button type="submit" className="btn btn-primary">Filter</button>
          </div>
        </div>

        <div className="col-md-12 col-lg-4 d-flex justify-content-lg-end gap-2">
          <div className="text-muted small align-self-center">
            Current semester: <strong>{selectedSemester || 'N/A'}</strong>
          </div>
          <Link className="btn btn-outline-secondary btn-sm align-self-center" to={REPORT_COMBINED_PATH}>
            Reset
          </Link>
        </div>
      </form>

      {error ? <div className="alert alert-danger">{error}</div> : null}
      {raw?.message ? <div className="alert alert-info">{raw.message}</div> : null}
      {loading ? <p className="text-muted">Loading score analysis…</p> : null}

      {!loading && !error ? (
        <>
          <div className="row g-3 mb-4">
            <div className="col-lg-4">
              <div className="card shadow-sm h-100">
                <div className="card-header py-2 d-flex justify-content-between align-items-center">
                  <strong>Active Student Snapshot</strong>
                  <span className="badge bg-primary">{summary.totalStudents} active</span>
                </div>
                <div className="card-body">
                  <div className="d-flex flex-wrap gap-3">
                    <div className="flex-fill">
                      <div className="small text-muted">Pass rate</div>
                      <div className="fs-3 text-success fw-semibold">{summary.passRate}%</div>
                      <div className="text-muted small">{summary.statusCounts.Passed} students</div>
                    </div>
                    <div className="flex-fill">
                      <div className="small text-muted">Failing</div>
                      <div className="fs-4 text-danger fw-semibold">{summary.statusCounts.Failed}</div>
                      <div className="text-muted small">{summary.failRate}% of roster</div>
                    </div>
                    <div className="flex-fill">
                      <div className="small text-muted">Pending / no data</div>
                      <div className="fs-4 text-secondary fw-semibold">{summary.pendingCount}</div>
                      <div className="text-muted small">{summary.pendingRate}% of roster</div>
                    </div>
                  </div>
                  <hr />
                  <p className="mb-1 small text-muted">Analyst notes</p>
                  <ul className="mb-0 small">
                    <li>Focus on {summary.riskCounts.High} high-risk students first.</li>
                    <li>{summary.statusCounts.Failed} students are currently failing.</li>
                    <li>{summary.totalTrophies} trophy-eligible students right now.</li>
                  </ul>
                </div>
              </div>
            </div>

            <div className="col-lg-4">
              <div className="card shadow-sm h-100">
                <div className="card-header py-2"><strong>Pass vs Fail</strong></div>
                <div className="card-body">
                  <div className="small text-muted mb-2">Current status mix</div>
                  {Object.entries(summary.statusCounts).map(([label, count]) => {
                    const percent = summary.totalStudents > 0 ? (count / summary.totalStudents) * 100 : 0
                    const barClass =
                      label === 'Passed'
                        ? 'bg-success'
                        : label === 'Failed'
                          ? 'bg-danger'
                          : label === 'Can pass'
                            ? 'bg-primary'
                            : label === 'May fail'
                              ? 'bg-warning'
                              : 'bg-secondary'
                    return (
                      <div key={label} className="mb-2">
                        <div className="d-flex justify-content-between small mb-1">
                          <span>{label}</span>
                          <span>{count}</span>
                        </div>
                        <div className="progress" role="progressbar" aria-valuenow={percent} aria-valuemin={0} aria-valuemax={100}>
                          <div className={`progress-bar ${barClass}`} style={{ width: `${percent}%` }} />
                        </div>
                      </div>
                    )
                  })}
                </div>
              </div>
            </div>

            <div className="col-lg-4">
              <div className="card shadow-sm h-100">
                <div className="card-header py-2"><strong>Fail Risk Mix</strong></div>
                <div className="card-body">
                  <div className="small text-muted mb-2">Risk distribution</div>
                  {Object.entries(summary.riskCounts).map(([label, count]) => {
                    const percent = summary.totalStudents > 0 ? (count / summary.totalStudents) * 100 : 0
                    const barClass =
                      label === 'Low'
                        ? 'bg-success'
                        : label === 'Medium'
                          ? 'bg-warning'
                          : label === 'High'
                            ? 'bg-danger'
                            : label === 'Unlikely to pass'
                              ? 'bg-dark'
                              : 'bg-secondary'
                    return (
                      <div key={label} className="mb-2">
                        <div className="d-flex justify-content-between small mb-1">
                          <span>{label}</span>
                          <span>{count}</span>
                        </div>
                        <div className="progress" role="progressbar" aria-valuenow={percent} aria-valuemin={0} aria-valuemax={100}>
                          <div className={`progress-bar ${barClass}`} style={{ width: `${percent}%` }} />
                        </div>
                      </div>
                    )
                  })}
                </div>
              </div>
            </div>
          </div>

          <div className="row mb-3">
            <div className="col-12">
              <div className="card shadow-sm">
                <div className="card-header py-2">
                  <strong>Trophies Summary</strong>
                </div>
                <div className="card-body p-2">
                  <div className="small text-muted mb-2">
                    If a class section has no students meeting the trophy threshold, the top ranked students in that section receive trophies.
                  </div>
                  <div className="table-responsive">
                    <table className="table table-sm table-bordered table-striped mb-2 text-center align-middle">
                      <thead className="table-light">
                        <tr>
                          <th className="text-start">Class Section</th>
                          {trophySummaryIds.length > 0 ? (
                            trophySummaryIds.map((sectionId) => (
                              <th key={sectionId}>{sectionMap[sectionId] ?? `Section ${sectionId}`}</th>
                            ))
                          ) : (
                            <th className="text-muted fst-italic">No trophies yet.</th>
                          )}
                        </tr>
                      </thead>
                      <tbody>
                        {trophySummaryIds.length > 0 ? (
                          <>
                            <tr>
                              <th className="text-start">Trophy Counts</th>
                              {trophySummaryIds.map((sectionId) => (
                                <td key={sectionId}>{summary.trophyCounts[sectionId]}</td>
                              ))}
                            </tr>
                            <tr className="fw-bold table-light">
                              <th className="text-start">Total Trophies</th>
                              <td colSpan={trophySummaryIds.length} className="text-center">{summary.totalTrophies}</td>
                            </tr>
                          </>
                        ) : (
                          <tr>
                            <td colSpan={2} className="text-muted fst-italic">No data available</td>
                          </tr>
                        )}
                      </tbody>
                    </table>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div className="table-responsive">
            <table className="table table-bordered table-striped align-middle w-100">
              <thead style={{ backgroundColor: '#dcefe8', color: '#0f172a' }}>
                <tr>
                  <th style={{ width: 60 }}>#</th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('school_id')}>
                    School ID {sortArrow(sortConfig.key === 'school_id', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('firstname')}>
                    First Name {sortArrow(sortConfig.key === 'firstname', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('lastname')}>
                    Last Name {sortArrow(sortConfig.key === 'lastname', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('class_name')}>
                    Class {sortArrow(sortConfig.key === 'class_name', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('fall_score')}>
                    Fall Score {sortArrow(sortConfig.key === 'fall_score', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('spring_score')}>
                    Spring Score {sortArrow(sortConfig.key === 'spring_score', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('final_average')}>
                    Final Average {sortArrow(sortConfig.key === 'final_average', sortConfig.direction)}
                  </th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('required_spring_score')}>
                    Needed for Trophy {sortArrow(sortConfig.key === 'required_spring_score', sortConfig.direction)}
                  </th>
                  <th>Chance to Win Trophy</th>
                  <th style={sortableHeaderCellStyle} onClick={() => requestSort('required_spring_to_pass')}>
                    Needed to Pass (60+) {sortArrow(sortConfig.key === 'required_spring_to_pass', sortConfig.direction)}
                  </th>
                  <th>Risk of Failing</th>
                  <th>Status</th>
                </tr>
              </thead>
              <tbody>
                {sortedStudents.map((student, index) => {
                  const className = sectionMap[String(student.class_section_id ?? '')] ?? (student.class_section_id ? `Section ${String(student.class_section_id)}` : '—')
                  return (
                    <tr key={String(student.student_id ?? `${student.school_id ?? 'row'}-${index}`)}>
                      <td>{index + 1}</td>
                      <td>{displayValue(student.school_id, '—')}</td>
                      <td>{displayValue(student.firstname, '—')}</td>
                      <td>{displayValue(student.lastname, '—')}</td>
                      <td>{className}</td>
                      <td>{displayValue(student.fall_score)}</td>
                      <td>{displayValue(student.spring_score)}</td>
                      <td>{displayValue(student.final_average)}</td>
                      <td>{displayValue(student.required_spring_score)}</td>
                      <td>{trophyChanceBadge(student.winning_risk)}</td>
                      <td>{displayValue(student.required_spring_to_pass)}</td>
                      <td>{failRiskBadge(student.failure_risk)}</td>
                      <td>{statusBadge(student.status)}</td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        </>
      ) : null}
    </div>
  )
}
