import { type FormEvent, useEffect, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchPlacementSection, postPlacementSection } from '../../api/grading'
import { AcademicFilterBar } from '../discounts/AcademicFilterBar'
import { rowsFromUnknown } from './gradingPayloadHelpers'
import { GRADING_PLACEMENT_INDEX_PATH } from './gradingPaths'

/** CI `grading/placement.php` — per-section placement scores. */
export function PlacementSectionPage() {
  const [searchParams] = useSearchParams()
  const classSectionId = searchParams.get('class_section_id') ?? ''

  const [rows, setRows] = useState<Record<string, unknown>[]>([])
  const [locked, setLocked] = useState(false)
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    if (!classSectionId) {
      setLoading(false)
      return
    }
    let c = false
    setLoading(true)
    fetchPlacementSection(searchParams)
      .then((p) => {
        if (c) return
        setRows(rowsFromUnknown(p))
        if (p && typeof p === 'object') {
          const o = p as Record<string, unknown>
          setLocked(Boolean(o.scoresLocked ?? o.locked))
        }
        setError(null)
      })
      .catch((e: unknown) => {
        if (!c) setError(e instanceof ApiHttpError ? e.message : 'Unable to load placement.')
      })
      .finally(() => {
        if (!c) setLoading(false)
      })
    return () => {
      c = true
    }
  }, [searchParams, classSectionId])

  const scoreKey = (row: Record<string, unknown>): string => {
    if ('placement_score' in row) return 'placement_score'
    if ('score' in row) return 'score'
    return 'placement_score'
  }

  function setScore(i: number, value: string) {
    setRows((prev) => {
      const next = [...prev]
      const k = scoreKey(next[i] ?? {})
      next[i] = { ...next[i], [k]: value === '' ? null : Number(value) }
      return next
    })
  }

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    setSaving(true)
    setError(null)
    try {
      await postPlacementSection({
        class_section_id: Number(classSectionId),
        rows,
        school_year: searchParams.get('school_year') ?? undefined,
        semester: searchParams.get('semester') ?? undefined,
      })
      const next = await fetchPlacementSection(searchParams)
      setRows(rowsFromUnknown(next))
    } catch (err: unknown) {
      setError(err instanceof ApiHttpError ? err.message : 'Save failed.')
    } finally {
      setSaving(false)
    }
  }

  const qs = searchParams.toString()
  const cols = rows[0] ? Object.keys(rows[0]) : ['student_id', 'firstname', 'lastname', 'placement_score']

  if (!classSectionId) {
    return (
      <div className="container mt-4">
        <div className="alert alert-info">
          Add <code>class_section_id</code> to the URL (open from Placement index).
        </div>
        <Link className="btn btn-secondary" to={GRADING_PLACEMENT_INDEX_PATH}>
          Placement index
        </Link>
      </div>
    )
  }

  return (
    <div className="container-fluid py-3">
      <h2 className="text-center mt-2 mb-3">Placement scores</h2>
      <p className="text-center text-muted small">Section #{classSectionId}</p>
      <AcademicFilterBar />

      <div className="mb-3">
        <Link className="btn btn-outline-secondary btn-sm" to={`${GRADING_PLACEMENT_INDEX_PATH}${qs ? `?${qs}` : ''}`}>
          All sections
        </Link>
      </div>

      {locked ? <div className="alert alert-warning">Scores are locked.</div> : null}
      {error ? <div className="alert alert-danger">{error}</div> : null}
      {loading ? <p className="text-muted">Loading…</p> : null}

      {!loading && rows.length > 0 ? (
        <form onSubmit={(ev) => void onSubmit(ev)}>
          <div className="table-responsive">
            <table className="table table-bordered align-middle">
              <thead className="table-light">
                <tr>
                  {cols.map((c) => (
                    <th key={c}>{c.replace(/_/g, ' ')}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {rows.map((row, i) => {
                  const sk = scoreKey(row)
                  return (
                    <tr key={i}>
                      {cols.map((col) =>
                        col === sk && !locked ? (
                          <td key={col}>
                            <input
                              type="number"
                              className="form-control form-control-sm"
                              style={{ width: 96 }}
                              value={row[col] === null || row[col] === undefined ? '' : String(row[col])}
                              onChange={(ev) => setScore(i, ev.target.value)}
                            />
                          </td>
                        ) : (
                          <td key={col}>{row[col] === null || row[col] === undefined ? '—' : String(row[col])}</td>
                        ),
                      )}
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
          <div className="text-center mt-3">
            <button type="submit" className="btn btn-primary" disabled={locked || saving}>
              {saving ? 'Saving…' : 'Save'}
            </button>
          </div>
        </form>
      ) : null}

      {!loading && rows.length === 0 ? (
        <div className="alert alert-light border">No rows for this section.</div>
      ) : null}
    </div>
  )
}
