import { type FormEvent, useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchPlacementBatch, postPlacementBatch } from '../../api/grading'
import { rowsFromUnknown } from './gradingPayloadHelpers'
import { GRADING_PLACEMENT_INDEX_PATH } from './gradingPaths'

/** CI `grading/placement_batch.php` */
export function PlacementBatchPage() {
  const { batchId = '' } = useParams()
  const [payload, setPayload] = useState<unknown>(null)
  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 (!batchId) {
      setLoading(false)
      return
    }
    let c = false
    setLoading(true)
    fetchPlacementBatch(batchId)
      .then((p) => {
        if (c) return
        setPayload(p)
        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 batch.')
      })
      .finally(() => {
        if (!c) setLoading(false)
      })
    return () => {
      c = true
    }
  }, [batchId])

  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 postPlacementBatch(batchId, { rows })
      const next = await fetchPlacementBatch(batchId)
      setPayload(next)
      setRows(rowsFromUnknown(next))
    } catch (err: unknown) {
      setError(err instanceof ApiHttpError ? err.message : 'Save failed.')
    } finally {
      setSaving(false)
    }
  }

  const cols = rows[0] ? Object.keys(rows[0]) : ['student_id', 'placement_score']

  if (!batchId) {
    return (
      <div className="container mt-4">
        <div className="alert alert-warning">Missing batch id in the URL.</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 batch</h2>
      <p className="text-center text-muted small">Batch #{batchId}</p>

      <div className="mb-3">
        <Link className="btn btn-outline-secondary btn-sm" to={GRADING_PLACEMENT_INDEX_PATH}>
          Placement index
        </Link>
      </div>

      {locked ? <div className="alert alert-warning">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 in this batch.</div>
      ) : null}

      {payload != null && !loading ? (
        <details className="mt-4">
          <summary className="small text-muted">Raw payload</summary>
          <pre className="small bg-light p-3 rounded mt-2 overflow-auto" style={{ maxHeight: 260 }}>
            {JSON.stringify(payload, null, 2)}
          </pre>
        </details>
      ) : null}
    </div>
  )
}
