import { type FormEvent, useCallback, useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import {
  cancelIncidentFlag,
  closeIncidentFlag,
  createIncidentFlag,
  fetchFlagsFormMeta,
  fetchFlagsPending,
  fetchStudentsByGrade,
  type GradeOption,
  type IncidentFlagRow,
} from '../../api/flags'
import { AcademicFilterBar } from '../discounts/AcademicFilterBar'
import { INCIDENT_DESCRIPTIONS, INCIDENT_ACTION_TEMPLATES } from './flagIncidentsConstants'
import {
  descriptionForFlag,
  formatIncidentDatetime,
  incidentTypeLabel,
  lastUpdaterCell,
} from './flagRowUtils'
import { normalizeIncidentKey } from './incidentLabels'

/** CI `flags/flags_management.php` — pending incidents, update state, add incident. */
export function FlagsManagementPage() {
  const [searchParams] = useSearchParams()
  const schoolYear = searchParams.get('school_year') ?? ''
  const semester = searchParams.get('semester') ?? ''

  const [rows, setRows] = useState<IncidentFlagRow[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [flashOk, setFlashOk] = useState<string | null>(null)

  const [grades, setGrades] = useState<GradeOption[]>([])
  const [gradesError, setGradesError] = useState<string | null>(null)

  const [showAddForm, setShowAddForm] = useState(false)
  const [gradeId, setGradeId] = useState('')
  const [students, setStudents] = useState<Array<{ id: number; name: string }>>([])
  const [studentsLoading, setStudentsLoading] = useState(false)
  const [studentId, setStudentId] = useState('')
  const [incidentKey, setIncidentKey] = useState('')
  const [description, setDescription] = useState('')
  const [descAutofill, setDescAutofill] = useState(false)
  const [addBusy, setAddBusy] = useState(false)

  const [modalFlagId, setModalFlagId] = useState<number | null>(null)
  const [modalAction, setModalAction] = useState<'Closed' | 'Canceled' | null>(null)
  const [modalDescription, setModalDescription] = useState('')
  const [modalActionTaken, setModalActionTaken] = useState('')
  const [modalBusy, setModalBusy] = useState(false)

  const loadPending = useCallback(() => {
    setLoading(true)
    fetchFlagsPending(searchParams)
      .then((data) => {
        setRows(data)
        setError(null)
      })
      .catch((e: unknown) => {
        setError(e instanceof ApiHttpError ? e.message : 'Unable to load incidents.')
      })
      .finally(() => setLoading(false))
  }, [searchParams])

  useEffect(() => {
    loadPending()
  }, [loadPending])

  useEffect(() => {
    fetchFlagsFormMeta()
      .then((m) => {
        setGrades(m.grades ?? [])
        setGradesError(null)
      })
      .catch((e: unknown) => {
        setGrades([])
        setGradesError(e instanceof ApiHttpError ? e.message : 'Unable to load grades.')
      })
  }, [])

  useEffect(() => {
    if (!gradeId) {
      setStudents([])
      setStudentId('')
      return
    }
    const id = Number(gradeId)
    if (!Number.isFinite(id)) return
    setStudentsLoading(true)
    fetchStudentsByGrade(id)
      .then((list) => {
        setStudents(list)
        setStudentId('')
      })
      .catch(() => {
        setStudents([])
        setStudentId('')
      })
      .finally(() => setStudentsLoading(false))
  }, [gradeId])

  function onIncidentChange(next: string) {
    setIncidentKey(next)
    if (!description.trim() || descAutofill) {
      const text = INCIDENT_DESCRIPTIONS[next] ?? ''
      setDescription(text)
      setDescAutofill(Boolean(text))
    }
  }

  function onDescriptionInput(v: string) {
    setDescription(v)
    setDescAutofill(false)
  }

  function openStateModal(flagId: number, action: 'Closed' | 'Canceled', incidentRaw: string) {
    setModalFlagId(flagId)
    setModalAction(action)
    setModalActionTaken('')
    const key = normalizeIncidentKey(incidentRaw)
    if (action === 'Closed') {
      const text =
        INCIDENT_ACTION_TEMPLATES[key] ?? INCIDENT_ACTION_TEMPLATES[incidentRaw] ?? ''
      setModalDescription(text)
    } else {
      setModalDescription('')
    }
  }

  function closeModal() {
    setModalFlagId(null)
    setModalAction(null)
    setModalDescription('')
    setModalActionTaken('')
  }

  async function submitModal() {
    if (modalFlagId == null || !modalAction) return
    setModalBusy(true)
    try {
      const body = {
        state_description: modalDescription,
        action_taken: modalActionTaken,
      }
      if (modalAction === 'Closed') {
        await closeIncidentFlag(modalFlagId, body)
      } else {
        await cancelIncidentFlag(modalFlagId, body)
      }
      setFlashOk('Incident updated.')
      closeModal()
      loadPending()
    } catch (e: unknown) {
      setError(e instanceof ApiHttpError ? e.message : 'Update failed.')
    } finally {
      setModalBusy(false)
    }
  }

  function onFlagStateSelect(flag: IncidentFlagRow, next: string) {
    const id = flag.id
    if (id == null) return
    if (next === 'Closed' || next === 'Canceled') {
      openStateModal(id, next, String(flag.flag ?? ''))
    }
  }

  async function onAddSubmit(e: FormEvent) {
    e.preventDefault()
    if (!gradeId || !studentId || !incidentKey || !description.trim()) return
    setAddBusy(true)
    setFlashOk(null)
    setError(null)
    try {
      await createIncidentFlag({
        grade: gradeId,
        student: studentId,
        flag: incidentKey,
        description: description.trim(),
        school_year: schoolYear || undefined,
        semester: semester || undefined,
      })
      setFlashOk('Incident saved.')
      setShowAddForm(false)
      setGradeId('')
      setStudentId('')
      setIncidentKey('')
      setDescription('')
      setDescAutofill(false)
      loadPending()
    } catch (err: unknown) {
      setError(err instanceof ApiHttpError ? err.message : 'Could not save incident.')
    } finally {
      setAddBusy(false)
    }
  }

  return (
    <div className="container-fluid">
      <h2 className="text-center mt-4 mb-3">Incidents Management</h2>

      <AcademicFilterBar />

      {flashOk ? (
        <div className="alert alert-success" role="alert">
          {flashOk}
        </div>
      ) : null}
      {error ? <div className="alert alert-danger">{error}</div> : null}

      <h4 className="mb-3">Pending Incidents</h4>
      {loading ? <p className="text-muted">Loading…</p> : null}

      <div className="table-responsive">
        <table className="table table-bordered">
          <thead>
            <tr>
              <th>Last Updater</th>
              <th>Student Name</th>
              <th>Grade</th>
              <th>Incident Type</th>
              <th>Description</th>
              <th>Datetime</th>
              <th>Incident State</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {!loading && rows.length === 0 ? (
              <tr>
                <td colSpan={8}>No incidents found.</td>
              </tr>
            ) : null}
            {rows.map((flag, i) => (
              <tr key={flag.id ?? i}>
                <td>{lastUpdaterCell(flag)}</td>
                <td>{flag.student_name ?? ''}</td>
                <td>{flag.grade ?? ''}</td>
                <td>{incidentTypeLabel(flag.flag)}</td>
                <td>{descriptionForFlag(flag)}</td>
                <td>{formatIncidentDatetime(flag.flag_datetime)}</td>
                <td>{flag.flag_state ?? ''}</td>
                <td>
                  <select
                    className="form-select form-select-sm"
                    value=""
                    aria-label={`Update state for incident ${flag.id}`}
                    onChange={(ev) => {
                      const v = ev.target.value
                      if (v === 'Closed' || v === 'Canceled') onFlagStateSelect(flag, v)
                      ev.currentTarget.value = ''
                    }}
                  >
                    <option value="">Select Action</option>
                    <option value="Closed">Closed</option>
                    <option value="Canceled">Canceled</option>
                  </select>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {modalFlagId != null && modalAction ? (
        <>
          <div className="modal-backdrop fade show" />
          <div className="modal fade show d-block" tabIndex={-1} role="dialog" aria-modal>
            <div className="modal-dialog">
              <div className="modal-content">
                <div className="modal-header">
                  <h5 className="modal-title">Add Description</h5>
                  <button type="button" className="btn-close" aria-label="Close" onClick={closeModal} />
                </div>
                <div className="modal-body">
                  <textarea
                    className="form-control"
                    rows={3}
                    placeholder="Enter description here"
                    value={modalDescription}
                    onChange={(e) => setModalDescription(e.target.value)}
                  />
                  <div className="mt-3">
                    <label className="form-label" htmlFor="flagActionTaken">
                      Action Taken
                    </label>
                    <textarea
                      id="flagActionTaken"
                      className="form-control"
                      rows={3}
                      placeholder="Enter action taken here"
                      value={modalActionTaken}
                      onChange={(e) => setModalActionTaken(e.target.value)}
                    />
                  </div>
                </div>
                <div className="modal-footer">
                  <button
                    type="button"
                    className="btn btn-primary"
                    disabled={modalBusy}
                    onClick={() => void submitModal()}
                  >
                    {modalBusy ? 'Saving…' : 'Save'}
                  </button>
                  <button type="button" className="btn btn-secondary" onClick={closeModal}>
                    Cancel
                  </button>
                </div>
              </div>
            </div>
          </div>
        </>
      ) : null}

      <div className="d-flex gap-2 mb-3 justify-content-end flex-wrap">
        <button
          type="button"
          className="btn btn-success"
          onClick={() => setShowAddForm((v) => !v)}
        >
          {showAddForm ? 'Hide form' : 'Add New Incident'}
        </button>
        <Link className="btn btn-info" to="/app/administrator/flags/incident-analysis">
          Incident Analysis
        </Link>
        <Link className="btn btn-secondary" to="/app/administrator/flags/processed">
          View Processed Incidents
        </Link>
      </div>

      {showAddForm ? (
        <div className="container my-4 border rounded p-3 bg-light">
          <h5 className="mb-3">New incident</h5>
          {gradesError ? <div className="alert alert-warning small">{gradesError}</div> : null}
          <form className="row g-3" onSubmit={(e) => void onAddSubmit(e)}>
            <div className="col-md-6">
              <label className="form-label" htmlFor="flags-grade">
                Grade
              </label>
              <select
                id="flags-grade"
                className="form-select"
                required
                value={gradeId}
                onChange={(e) => setGradeId(e.target.value)}
              >
                <option value="">Select Grade</option>
                {grades.map((g) => (
                  <option key={g.id} value={g.id}>
                    {g.name}
                  </option>
                ))}
              </select>
            </div>
            <div className="col-md-6">
              <label className="form-label" htmlFor="flags-student">
                Student Name
              </label>
              <select
                id="flags-student"
                className="form-select"
                required
                value={studentId}
                onChange={(e) => setStudentId(e.target.value)}
                disabled={!gradeId || studentsLoading}
              >
                <option value="">{studentsLoading ? 'Loading…' : 'Select Student'}</option>
                {students.map((s) => (
                  <option key={s.id} value={s.id}>
                    {s.name}
                  </option>
                ))}
              </select>
            </div>
            <div className="col-md-6">
              <label className="form-label" htmlFor="flags-incident">
                Incident
              </label>
              <select
                id="flags-incident"
                className="form-select"
                required
                value={incidentKey}
                onChange={(e) => onIncidentChange(e.target.value)}
              >
                <option value="">Select Incident</option>
                <option value="payment">Payment</option>
                <option value="attendance">Attendance</option>
                <option value="grade">Grade</option>
                <option value="behavior">Behavior (General)</option>
                <optgroup label="Level 1 - Minor (Teacher-managed)">
                  <option value="talking_off_task">Talking/off-task</option>
                  <option value="calling_out">Calling out</option>
                  <option value="minor_disruption">Minor disruption</option>
                  <option value="minor_dress_code">Minor dress code</option>
                  <option value="forgetting_materials">Forgetting materials</option>
                </optgroup>
                <optgroup label="Level 2 - Moderate / Repeated">
                  <option value="repeated_defiance">Repeated defiance</option>
                  <option value="disrespectful_tone">Disrespectful tone</option>
                  <option value="minor_profanity">Minor profanity</option>
                  <option value="repeated_tardiness">Repeated tardiness</option>
                  <option value="device_misuse">Device misuse</option>
                  <option value="minor_conflict">Minor conflict/horseplay</option>
                </optgroup>
                <optgroup label="Level 3 - Serious (Immediate admin)">
                  <option value="bullying_harassment">Bullying/harassment</option>
                  <option value="fighting_aggression">Fighting/aggression</option>
                  <option value="threats">Threats</option>
                  <option value="theft">Theft</option>
                  <option value="vandalism">Vandalism</option>
                  <option value="sexual_harassment">Sexual harassment</option>
                  <option value="serious_cyber_incident">Serious cyber incident</option>
                  <option value="contraband">Contraband</option>
                  <option value="weapons_drugs">Weapons/drugs</option>
                </optgroup>
                <option value="other">Other</option>
              </select>
            </div>
            <div className="col-12">
              <label className="form-label" htmlFor="flags-desc">
                Description
              </label>
              <textarea
                id="flags-desc"
                name="description"
                className="form-control"
                rows={3}
                required
                value={description}
                onChange={(e) => onDescriptionInput(e.target.value)}
              />
            </div>
            <div className="col-12">
              <button type="submit" className="btn btn-primary" disabled={addBusy}>
                {addBusy ? 'Saving…' : 'Save'}
              </button>
              <button
                type="button"
                className="btn btn-secondary ms-2"
                onClick={() => setShowAddForm(false)}
              >
                Cancel
              </button>
            </div>
          </form>
        </div>
      ) : null}
    </div>
  )
}
