import { type FormEvent, useEffect, useMemo, useState } from 'react'
import { Link, useParams, useSearchParams } from 'react-router-dom'
import {
  fetchAdminCompetitionWinnerScores,
  saveAdminCompetitionWinnerScores,
} from '../../api/session'
import type { CompetitionScoreStudentRow, CompetitionWinnerAdminScoresResponse } from '../../api/types'
import {
  ApiScopeNote,
  CompetitionPageShell,
  COMPETITION_WINNERS_BASE,
  competitionLabel,
} from './competitionWinnersShared'

function numberOrNull(value: string | number | null | undefined): number | null {
  if (value === null || value === undefined || value === '') return null
  const parsed = Number(value)
  return Number.isFinite(parsed) ? parsed : null
}

/** CI `admin/competition_winners/scores.php` */
export function CompetitionWinnerScoresPage() {
  const { id } = useParams()
  const competitionId = Number(id)
  const [searchParams, setSearchParams] = useSearchParams()
  const selectedClassId = numberOrNull(searchParams.get('class_section_id'))
  const [data, setData] = useState<CompetitionWinnerAdminScoresResponse | null>(null)
  const [scores, setScores] = useState<Record<string, number | string>>({})
  const [message, setMessage] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)

  async function load(classSectionId = selectedClassId) {
    try {
      const response = await fetchAdminCompetitionWinnerScores(competitionId, classSectionId)
      setData(response)
      setScores(response.scoreMap ?? {})
      setError(response.ok ? null : response.message ?? 'Unable to load competition scores.')
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Unable to load competition scores.')
    }
  }

  useEffect(() => {
    if (!Number.isFinite(competitionId) || competitionId <= 0) return
    void load()
  }, [competitionId, selectedClassId])

  const classOptions = useMemo(
    () =>
      (data?.classSections ?? [])
        .map((section) => ({
          id: numberOrNull(section.class_section_id),
          label: String(section.class_section_name ?? section.class_section_id ?? ''),
        }))
        .filter((section): section is { id: number; label: string } => section.id !== null),
    [data?.classSections],
  )

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    if (!competitionId) return
    try {
      const result = await saveAdminCompetitionWinnerScores(competitionId, {
        class_section_id: selectedClassId ?? data?.activeClassSectionId ?? null,
        scores,
      })
      setMessage(result.message ?? 'Scores saved.')
      if (result.ok) {
        await load()
      }
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Unable to save scores.')
    }
  }

  return (
    <CompetitionPageShell title="Enter Scores">
      <ApiScopeNote>
        This admin score-entry page uses the dedicated Laravel competition-winners endpoints, so it works for administrator
        workflows without relying on teacher class assignments.
      </ApiScopeNote>
      {error ? <div className="alert alert-danger">{error}</div> : null}
      {message ? <div className="alert alert-success">{message}</div> : null}
      {data?.competition ? (
        <>
          <div className="mb-3">
            <div>
              <strong>Competition:</strong> {competitionLabel(data.competition)}
            </div>
            <div>
              <strong>Class Section:</strong> {data.classSectionName ?? '—'}
            </div>
            <div>
              <strong>Students:</strong> {data.classStudentCount ?? 0} | <strong>Questions:</strong>{' '}
              {data.classQuestionCount ?? '—'} | <strong>Final Winners:</strong> {data.classFinalWinners ?? '—'}
            </div>
          </div>
          <form onSubmit={(e) => void onSubmit(e)}>
            {data.classSelectionLocked === false ? (
              <div className="mb-3" style={{ maxWidth: 360 }}>
                <label className="form-label">Class Section</label>
                <select
                  className="form-select"
                  value={String(selectedClassId ?? data.activeClassSectionId ?? '')}
                  onChange={(e) =>
                    setSearchParams(e.target.value ? { class_section_id: e.target.value } : {})
                  }
                >
                  <option value="">Select a class</option>
                  {classOptions.map((section) => (
                    <option key={section.id} value={section.id}>
                      {section.label}
                    </option>
                  ))}
                </select>
              </div>
            ) : null}
            <div className="table-responsive">
              <table className="table table-bordered table-sm align-middle">
                <thead className="table-light">
                  <tr>
                    <th>School ID</th>
                    <th>Student</th>
                    <th>Score{data.classQuestionCount ? ` (max ${data.classQuestionCount})` : ''}</th>
                  </tr>
                </thead>
                <tbody>
                  {(data.students ?? []).length === 0 ? (
                    <tr>
                      <td colSpan={3} className="text-muted">
                        No students loaded for this competition.
                      </td>
                    </tr>
                  ) : (
                    (data.students ?? []).map((student: CompetitionScoreStudentRow) => {
                      const studentId = Number(student.id ?? student.student_id ?? 0)
                      const name =
                        `${student.firstname ?? ''} ${student.lastname ?? ''}`.trim() ||
                        `Student #${studentId}`
                      return (
                        <tr key={studentId}>
                          <td>{student.school_id ?? studentId}</td>
                          <td>{name}</td>
                          <td>
                            <input
                              className="form-control form-control-sm"
                              type="number"
                              step="1"
                              min="0"
                              max={data.classQuestionCount ?? undefined}
                              disabled={Boolean(data.competition?.is_locked)}
                              value={String(scores[String(studentId)] ?? '')}
                              onChange={(e) =>
                                setScores((current) => ({
                                  ...current,
                                  [String(studentId)]: e.target.value,
                                }))
                              }
                            />
                          </td>
                        </tr>
                      )
                    })
                  )}
                </tbody>
              </table>
            </div>
            <div className="d-flex gap-2 mt-3">
              <button className="btn btn-primary" disabled={Boolean(data.competition?.is_locked)}>
                Save Scores
              </button>
              <Link className="btn btn-outline-secondary" to={`${COMPETITION_WINNERS_BASE}/${competitionId}/preview`}>
                Preview
              </Link>
            </div>
          </form>
        </>
      ) : (
        <p className="text-muted mb-0">No competition data loaded.</p>
      )}
    </CompetitionPageShell>
  )
}
