import { type FormEvent, useEffect, useMemo, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import {
  fetchBelowSixtyDecisionDetails,
  fetchBelowSixtyDecisions,
  postBelowSixtyDecision,
} from '../../api/grading'
import { fetchGradingOverview } from '../../api/session'
import {
  GRADING_BELOW_SIXTY_DECISION_EMAIL_EDITOR_PATH,
  GRADING_BELOW_SIXTY_PATH,
  GRADING_DECISIONS_PATH,
  GRADING_PATH,
} from './gradingPaths'

type DecisionOption = '' | 'Pass' | 'Repeat Class' | 'Make-up exam in fall' | 'Deferred decision' | 'Expel' | 'Withdrawn'

type DecisionRow = {
  student_id: number
  school_id?: string | null
  firstname?: string | null
  lastname?: string | null
  age?: number | string | null
  class_section_name?: string | null
  fall_score?: number | string | null
  spring_score?: number | string | null
  year_score?: number | string | null
  decision?: string | null
  decision_notes?: string | null
  certificate_number?: string | null
}

type SemesterDetails = {
  semester?: string
  class_section_name?: string | null
  homework_avg?: number | string | null
  project_avg?: number | string | null
  participation_score?: number | string | null
  test_avg?: number | string | null
  ptap_score?: number | string | null
  attendance_score?: number | string | null
  midterm_exam_score?: number | string | null
  final_exam_score?: number | string | null
  semester_score?: number | string | null
  comments?: Record<string, string>
}

const DECISION_OPTIONS: Array<{ value: DecisionOption; label: string }> = [
  { value: '', label: '— No decision yet —' },
  { value: 'Pass', label: 'Pass' },
  { value: 'Repeat Class', label: 'Repeat Class' },
  { value: 'Make-up exam in fall', label: 'Make-up exam in fall' },
  { value: 'Deferred decision', label: 'Deferred decision' },
  { value: 'Expel', label: 'Expel' },
  { value: 'Withdrawn', label: 'Withdrawn' },
]

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 normalizeRows(payload: unknown): DecisionRow[] {
  if (Array.isArray(payload)) return payload as DecisionRow[]
  if (payload && typeof payload === 'object' && 'rows' in payload) {
    const rows = (payload as { rows?: unknown }).rows
    if (Array.isArray(rows)) return rows as DecisionRow[]
  }
  return []
}

function decisionBadgeClass(decision: string): string | null {
  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 null
  }
}

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

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

  const [filterYear, setFilterYear] = useState(schoolYear)
  const [rows, setRows] = useState<DecisionRow[]>([])
  const [loading, setLoading] = useState(true)
  const [savingStudentId, setSavingStudentId] = useState<number | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [success, setSuccess] = useState<string | null>(null)
  const [modalStudentName, setModalStudentName] = useState('')
  const [modalSemesters, setModalSemesters] = useState<SemesterDetails[]>([])
  const [modalLoading, setModalLoading] = useState(false)
  const [modalError, setModalError] = useState<string | null>(null)
  const [detailsOpen, setDetailsOpen] = useState(false)

  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])

  useEffect(() => {
    if (!schoolYear) {
      setLoading(false)
      return
    }

    let cancelled = false
    setLoading(true)
    fetchBelowSixtyDecisions(searchParams)
      .then((payload) => {
        if (cancelled) return
        setRows(normalizeRows(payload))
        setError(null)
      })
      .catch((e: unknown) => {
        if (!cancelled) {
          setError(e instanceof ApiHttpError ? e.message : 'Unable to load school year decisions.')
        }
      })
      .finally(() => {
        if (!cancelled) setLoading(false)
      })

    return () => {
      cancelled = true
    }
  }, [schoolYear, searchParams])

  const metrics = useMemo(() => {
    let pending = 0
    let decided = 0
    let urgent = 0

    for (const row of rows) {
      const decision = fieldText(row.decision)
      const score = numericScore(row.year_score)
      if (decision === '') pending += 1
      else decided += 1
      if (score !== null && score < 50) urgent += 1
    }

    return { total: rows.length, pending, decided, urgent }
  }, [rows])

  async function onSaveDecision(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    const formData = new FormData(event.currentTarget)
    const studentId = Number(formData.get('student_id') ?? 0)
    setSavingStudentId(studentId)
    setError(null)
    setSuccess(null)
    try {
      await postBelowSixtyDecision({
        student_id: studentId,
        school_year: formData.get('school_year'),
        semester: 'year',
        decision: formData.get('decision'),
        notes: formData.get('notes'),
      })
      const refreshed = await fetchBelowSixtyDecisions(searchParams)
      setRows(normalizeRows(refreshed))
      setSuccess('Decision saved.')
    } catch (e: unknown) {
      setError(e instanceof ApiHttpError ? e.message : 'Unable to save the decision.')
    } finally {
      setSavingStudentId(null)
    }
  }

  async function openDetails(row: DecisionRow) {
    const studentId = Number(row.student_id ?? 0)
    if (!studentId || !schoolYear) return

    setModalStudentName(`${fieldText(row.firstname)} ${fieldText(row.lastname)}`.trim() || 'Student')
    setModalSemesters([])
    setModalError(null)
    setModalLoading(true)
    setDetailsOpen(true)

    const params = new URLSearchParams({
      student_id: String(studentId),
      school_year: schoolYear,
    })

    try {
      const payload = await fetchBelowSixtyDecisionDetails(params)
      const semesters =
        payload && typeof payload === 'object' && 'semesters' in payload && Array.isArray((payload as { semesters?: unknown }).semesters)
          ? ((payload as { semesters: SemesterDetails[] }).semesters ?? [])
          : []
      setModalSemesters(semesters)
    } catch (e: unknown) {
      setModalError(e instanceof ApiHttpError ? e.message : 'Unable to load the student details.')
    } finally {
      setModalLoading(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">School Year Decisions</h2>
          <div className="text-muted">Whole Year • {schoolYear || 'Current school year'}</div>
        </div>
        <div className="d-flex gap-2 flex-wrap">
          <Link className="btn btn-outline-secondary btn-sm" to={`${GRADING_BELOW_SIXTY_PATH}?school_year=${encodeURIComponent(schoolYear)}&semester=fall`}>
            Back to Below 60
          </Link>
          <Link className="btn btn-outline-primary btn-sm" to={`${GRADING_DECISIONS_PATH}?school_year=${encodeURIComponent(schoolYear)}`}>
            All 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">
        <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: 160 }}
                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-primary">
                Apply
              </button>
            </div>
          </form>
        </div>
      </div>

      <div className="row g-3 mb-3">
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-0 shadow-sm h-100">
            <div className="card-body">
              <div className="text-muted small text-uppercase">Students</div>
              <div className="display-6">{metrics.total}</div>
            </div>
          </div>
        </div>
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-0 shadow-sm h-100">
            <div className="card-body">
              <div className="text-muted small text-uppercase">Pending</div>
              <div className="display-6 text-warning">{metrics.pending}</div>
            </div>
          </div>
        </div>
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-0 shadow-sm h-100">
            <div className="card-body">
              <div className="text-muted small text-uppercase">Decided</div>
              <div className="display-6 text-success">{metrics.decided}</div>
            </div>
          </div>
        </div>
        <div className="col-12 col-md-6 col-xl-3">
          <div className="card border-0 shadow-sm h-100">
            <div className="card-body">
              <div className="text-muted small text-uppercase">Year Score Under 50</div>
              <div className="display-6 text-danger">{metrics.urgent}</div>
            </div>
          </div>
        </div>
      </div>

      {success ? <div className="alert alert-success">{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-success">No students below 60 for the whole year in {schoolYear}.</div>
      ) : null}

      {!loading && rows.length > 0 ? (
        <>
          <div className="table-responsive">
            <table className="table table-bordered table-striped align-middle">
              <thead className="table-light">
                <tr>
                  <th style={{ minWidth: 160 }}>Student Name</th>
                  <th className="text-center">Age</th>
                  <th>Class-Section</th>
                  <th className="text-center">Year Score</th>
                  <th style={{ minWidth: 300 }}>Comments / Rationale &amp; Decision</th>
                  <th style={{ minWidth: 170 }} className="text-center">Below-60 Decision</th>
                </tr>
              </thead>
              <tbody>
                {rows.map((row) => {
                  const studentId = Number(row.student_id ?? 0)
                  const yearScore = numericScore(row.year_score)
                  const rowClass = yearScore !== null ? (yearScore < 50 ? 'table-danger' : 'table-warning') : ''
                  const studentName = `${fieldText(row.firstname)} ${fieldText(row.lastname)}`.trim() || 'N/A'
                  const decision = fieldText(row.decision)
                  const notes = fieldText(row.decision_notes)
                  const badgeClass = decisionBadgeClass(decision)
                  const isSaving = savingStudentId === studentId
                  const emailHref = `${GRADING_BELOW_SIXTY_DECISION_EMAIL_EDITOR_PATH}?student_id=${studentId}&school_year=${encodeURIComponent(schoolYear)}`

                  return (
                    <tr key={studentId || studentName} className={rowClass}>
                      <td>{studentName}</td>
                      <td className="text-center">{fieldText(row.age) || '—'}</td>
                      <td>{fieldText(row.class_section_name) || '—'}</td>
                      <td className="text-center">
                        <div className="fw-semibold">{displayScore(row.year_score)}</div>
                        <button
                          type="button"
                          className="btn btn-outline-secondary btn-sm mt-1"
                          onClick={() => void openDetails(row)}
                        >
                          Details
                        </button>
                      </td>
                      <td>
                        <form onSubmit={(event) => void onSaveDecision(event)}>
                          <input type="hidden" name="student_id" value={studentId} />
                          <input type="hidden" name="school_year" value={schoolYear} />
                          <textarea
                            name="notes"
                            className="form-control form-control-sm"
                            rows={3}
                            defaultValue={notes}
                            placeholder="Add comments or rationale…"
                          />
                          <div className="d-flex gap-2 mt-2 align-items-center">
                            <select
                              name="decision"
                              className="form-select form-select-sm"
                              defaultValue={decision}
                            >
                              {DECISION_OPTIONS.map((option) => (
                                <option key={option.value || 'none'} value={option.value}>
                                  {option.label}
                                </option>
                              ))}
                            </select>
                            <button type="submit" className="btn btn-sm btn-primary" disabled={isSaving}>
                              {isSaving ? 'Saving…' : 'Save'}
                            </button>
                          </div>
                        </form>
                      </td>
                      <td className="text-center align-middle">
                        {decision && badgeClass ? (
                          <>
                            <span className={`badge ${badgeClass} fs-6 px-3 py-2 d-block mb-2`}>{decision}</span>
                            <Link className="btn btn-sm btn-outline-primary" to={emailHref}>
                              Send Email
                            </Link>
                          </>
                        ) : (
                          <span className="text-muted small">Pending</span>
                        )}
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>

          {detailsOpen ? (
            <div
              className="modal fade show d-block"
              tabIndex={-1}
              role="dialog"
              style={{ backgroundColor: 'rgba(0,0,0,0.45)' }}
              onClick={() => setDetailsOpen(false)}
            >
              <div className="modal-dialog modal-lg modal-dialog-scrollable" onClick={(event) => event.stopPropagation()}>
                <div className="modal-content">
                  <div className="modal-header">
                    <div>
                      <h5 className="modal-title mb-0">Whole-Year Details</h5>
                      <div className="text-muted small">{modalStudentName}</div>
                    </div>
                    <button type="button" className="btn-close" onClick={() => setDetailsOpen(false)} aria-label="Close" />
                  </div>
                  <div className="modal-body">
                    {modalError ? <div className="alert alert-danger">{modalError}</div> : null}
                    {modalLoading ? <p className="text-muted mb-0">Loading…</p> : null}
                    {!modalLoading && !modalError && modalSemesters.length === 0 ? (
                      <p className="text-muted mb-0">No semester details found.</p>
                    ) : null}
                    {!modalLoading && modalSemesters.length > 0 ? (
                      <div className="d-grid gap-3">
                        {modalSemesters.map((semester, index) => (
                          <div key={`${semester.semester ?? 'semester'}-${index}`} className="card border-0 shadow-sm">
                            <div className="card-body">
                              <div className="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-2">
                                <div className="fw-semibold text-capitalize">{fieldText(semester.semester) || 'Semester'}</div>
                                <div className="text-muted small">{fieldText(semester.class_section_name) || '—'}</div>
                              </div>
                              <div className="row g-2 small">
                                <div className="col-6 col-md-3">Homework: {displayScore(semester.homework_avg)}</div>
                                <div className="col-6 col-md-3">Project: {displayScore(semester.project_avg)}</div>
                                <div className="col-6 col-md-3">Participation: {displayScore(semester.participation_score)}</div>
                                <div className="col-6 col-md-3">Test: {displayScore(semester.test_avg)}</div>
                                <div className="col-6 col-md-3">PTAP: {displayScore(semester.ptap_score)}</div>
                                <div className="col-6 col-md-3">Attendance: {displayScore(semester.attendance_score)}</div>
                                <div className="col-6 col-md-3">Midterm: {displayScore(semester.midterm_exam_score)}</div>
                                <div className="col-6 col-md-3">Final: {displayScore(semester.final_exam_score)}</div>
                                <div className="col-6 col-md-3 fw-semibold">Semester Score: {displayScore(semester.semester_score)}</div>
                              </div>
                              {semester.comments && Object.keys(semester.comments).length > 0 ? (
                                <div className="mt-3">
                                  <div className="fw-semibold small mb-1">Comments</div>
                                  <ul className="mb-0 small">
                                    {Object.entries(semester.comments).map(([key, value]) => (
                                      <li key={key}>
                                        <span className="text-capitalize">{key.replace(/_/g, ' ')}:</span> {fieldText(value) || '—'}
                                      </li>
                                    ))}
                                  </ul>
                                </div>
                              ) : null}
                            </div>
                          </div>
                        ))}
                      </div>
                    ) : null}
                  </div>
                </div>
              </div>
            </div>
          ) : null}
        </>
      ) : null}
    </div>
  )
}
