import { type FormEvent, useCallback, useEffect, useMemo, useState } from 'react'
import {
  fetchAdministratorAbsenceForm,
  submitAdministratorAbsence,
} from '../../api/session'
import type { AdministratorAbsenceFormResponse } from '../../api/types'

const DEFAULT_REASON_TYPES: Record<string, string> = {
  sick: 'Illness / medical',
  vacation: 'Vacation',
  personal: 'Personal',
  professional: 'Professional development',
  other: 'Other',
}

function formatYmd(d: string): string {
  const t = String(d).trim()
  if (!/^\d{4}-\d{2}-\d{2}/.test(t)) return t
  const date = new Date(t.slice(0, 10) + 'T12:00:00')
  if (Number.isNaN(date.getTime())) return t
  return date.toLocaleDateString(undefined, {
    weekday: 'short',
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  })
}

function normalizeFormPayload(body: AdministratorAbsenceFormResponse): {
  adminName: string
  semester: string
  schoolYear: string
  existing: NonNullable<AdministratorAbsenceFormResponse['existing']>
  available: string[]
  reasonTypes: Record<string, string>
} {
  const available =
    body.availableDates?.length ? body.availableDates : body.available_dates ?? []
  const schoolYear = body.schoolYear ?? body.school_year ?? ''
  const reasonTypes =
    body.reason_types && Object.keys(body.reason_types).length > 0
      ? body.reason_types
      : DEFAULT_REASON_TYPES
  return {
    adminName: String(body.admin_name ?? '').trim() || 'Administrator',
    semester: String(body.semester ?? '').trim(),
    schoolYear: String(schoolYear).trim(),
    existing: body.existing ?? [],
    available: [...new Set(available.map((d) => String(d).slice(0, 10)))].sort(),
    reasonTypes,
  }
}

/**
 * Administrator absence requests — `GET`/`POST /api/v1/administrator/absence` (JWT Bearer).
 * Pair with Laravel `routes/api.php` + OpenAPI docs.
 */
export function AdministratorAbsencePage() {
  const [raw, setRaw] = useState<AdministratorAbsenceFormResponse | null>(null)
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [success, setSuccess] = useState<string | null>(null)
  const [selectedDates, setSelectedDates] = useState<Set<string>>(() => new Set())
  const [reasonType, setReasonType] = useState('')
  const [reason, setReason] = useState('')

  const normalized = useMemo(() => (raw ? normalizeFormPayload(raw) : null), [raw])

  const load = useCallback(async () => {
    setLoading(true)
    setError(null)
    try {
      const body = await fetchAdministratorAbsenceForm()
      setRaw(body)
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Unable to load absence form.')
      setRaw(null)
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    void load()
  }, [load])

  useEffect(() => {
    if (!normalized) return
    const firstKey = Object.keys(normalized.reasonTypes)[0] ?? ''
    setReasonType((current) => current || firstKey)
  }, [normalized])

  function toggleDate(ymd: string) {
    setSelectedDates((prev) => {
      const next = new Set(prev)
      if (next.has(ymd)) next.delete(ymd)
      else next.add(ymd)
      return next
    })
  }

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    setSuccess(null)
    setError(null)
    const dates = Array.from(selectedDates).sort()
    if (dates.length === 0) {
      setError('Select at least one date to request absence.')
      return
    }
    if (!reason.trim()) {
      setError('Please enter a reason.')
      return
    }
    setSaving(true)
    try {
      const res = await submitAdministratorAbsence({
        dates,
        reason_type: reasonType || undefined,
        reason: reason.trim(),
      })
      const msg =
        res.message ??
        (typeof res.saved === 'number'
          ? `Saved ${res.saved} date(s).`
          : 'Absence request submitted.')
      setSuccess(msg)
      setSelectedDates(new Set())
      setReason('')
      await load()
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unable to submit absence request.')
    } finally {
      setSaving(false)
    }
  }

  return (
    <div className="container-fluid py-4" style={{ maxWidth: 920 }}>
      <div className="mb-4">
        <h1 className="h3 mb-1">Administrator absence</h1>
        <p className="text-muted mb-0">
          Request scheduled time away. Uses{' '}
          <code className="small">GET</code> / <code className="small">POST</code>{' '}
          <code className="small">/api/v1/administrator/absence</code> with your session JWT.
        </p>
      </div>

      {loading ? (
        <div className="text-muted">Loading…</div>
      ) : null}

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

      {normalized ? (
        <>
          <div className="card shadow-sm mb-4">
            <div className="card-body">
              <div className="row g-2 small">
                <div className="col-md-4">
                  <span className="text-muted">Admin</span>
                  <div className="fw-semibold">{normalized.adminName}</div>
                </div>
                {normalized.semester ? (
                  <div className="col-md-4">
                    <span className="text-muted">Semester</span>
                    <div className="fw-semibold">{normalized.semester}</div>
                  </div>
                ) : null}
                {normalized.schoolYear ? (
                  <div className="col-md-4">
                    <span className="text-muted">School year</span>
                    <div className="fw-semibold">{normalized.schoolYear}</div>
                  </div>
                ) : null}
              </div>
            </div>
          </div>

          <div className="card shadow-sm mb-4">
            <div className="card-header">
              <strong>Recorded absences</strong>
            </div>
            <div className="card-body p-0">
              {normalized.existing.length === 0 ? (
                <div className="p-3 text-muted small">No absence entries on file for this period.</div>
              ) : (
                <div className="table-responsive">
                  <table className="table table-sm table-striped mb-0 align-middle">
                    <thead className="table-light">
                      <tr>
                        <th>Date</th>
                        <th>Status</th>
                        <th>Reason</th>
                      </tr>
                    </thead>
                    <tbody>
                      {normalized.existing.map((row, i) => (
                        <tr key={`${row.date}-${i}`}>
                          <td>{row.date ? formatYmd(String(row.date)) : '—'}</td>
                          <td>{row.status ?? '—'}</td>
                          <td>{row.reason ?? '—'}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          </div>

          <div className="card shadow-sm">
            <div className="card-header">
              <strong>Request absence</strong>
            </div>
            <div className="card-body">
              {normalized.available.length === 0 ? (
                <p className="text-muted mb-0">
                  No open dates are available to select right now. Check back later or contact the office if you need an
                  exception.
                </p>
              ) : (
                <form onSubmit={(e) => void onSubmit(e)}>
                  <fieldset disabled={saving}>
                    <legend className="form-label fw-semibold">Dates</legend>
                    <div className="row row-cols-1 row-cols-md-2 g-2 mb-4">
                      {normalized.available.map((ymd) => (
                        <div key={ymd} className="col">
                          <div className="form-check">
                            <input
                              className="form-check-input"
                              type="checkbox"
                              id={`abs-${ymd}`}
                              checked={selectedDates.has(ymd)}
                              onChange={() => toggleDate(ymd)}
                            />
                            <label className="form-check-label" htmlFor={`abs-${ymd}`}>
                              {formatYmd(ymd)}
                              <span className="text-muted small ms-1">({ymd})</span>
                            </label>
                          </div>
                        </div>
                      ))}
                    </div>

                    <div className="mb-3">
                      <label className="form-label" htmlFor="absenceReasonType">
                        Reason type
                      </label>
                      <select
                        id="absenceReasonType"
                        className="form-select"
                        value={reasonType}
                        onChange={(e) => setReasonType(e.target.value)}
                      >
                        {Object.entries(normalized.reasonTypes).map(([value, label]) => (
                          <option key={value} value={value}>
                            {label}
                          </option>
                        ))}
                      </select>
                    </div>

                    <div className="mb-3">
                      <label className="form-label" htmlFor="absenceReason">
                        Details <span className="text-danger">*</span>
                      </label>
                      <textarea
                        id="absenceReason"
                        className="form-control"
                        rows={4}
                        required
                        value={reason}
                        onChange={(e) => setReason(e.target.value)}
                        placeholder="Brief explanation for HR / scheduling records."
                      />
                    </div>

                    <button type="submit" className="btn btn-primary" disabled={saving}>
                      {saving ? 'Submitting…' : 'Submit request'}
                    </button>
                  </fieldset>
                </form>
              )}
            </div>
          </div>
        </>
      ) : null}
    </div>
  )
}
