import { type FormEvent, useEffect, useMemo, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { formatProgressDate } from '../classProgress/classProgressUtils'
import { ClassProgressUnitDisplay } from '../classProgress/ClassProgressUnitDisplay'
import { TeacherShell } from './TeacherShell'
import { useTeacherResource } from './useTeacherResource'

const STATUS_OPTIONS: Record<string, string> = {
  on_track: 'On track',
  slightly_behind: 'Slightly behind',
  behind: 'Behind',
}

type Pagination = {
  current_page?: number
  last_page?: number
  per_page?: number
  total?: number
}

export type TeacherProgressReportRow = {
  id?: number
  class_section_id?: number
  class_section_name?: string | null
  week_start?: string | null
  week_end?: string | null
  subject?: string | null
  unit_title?: string | null
  covered?: string | null
  homework?: string | null
  status?: string | null
  status_label?: string | null
  teacher_name?: string | null
  updated_at?: string | null
}

/** Laravel `JsonResource::collection()` often serializes as `{ data: [...] }` under `items`. */
function extractReportRows(rawItems: unknown): TeacherProgressReportRow[] {
  if (rawItems == null) return []
  if (Array.isArray(rawItems)) return rawItems as TeacherProgressReportRow[]
  if (typeof rawItems === 'object' && 'data' in (rawItems as object)) {
    const inner = (rawItems as { data: unknown }).data
    if (Array.isArray(inner)) return inner as TeacherProgressReportRow[]
  }
  return []
}

function unwrapHistoryList(raw: unknown): { items: TeacherProgressReportRow[]; pagination?: Pagination } | null {
  if (raw == null || typeof raw !== 'object') return null
  const o = raw as Record<string, unknown>
  let data = (o.data ?? o) as Record<string, unknown>
  // Rare: double-wrapped `data` from intermediaries
  if (!('items' in data) && typeof data.data === 'object' && data.data !== null) {
    const inner = data.data as Record<string, unknown>
    if ('items' in inner) data = inner
  }
  if (!('items' in data)) return null
  const rows = extractReportRows(data.items)
  return {
    items: rows,
    pagination: data.pagination as Pagination | undefined,
  }
}

/** Empty values (e.g. `week_start=`) break Laravel `date_format` validation on the index endpoint. */
function buildHistoryQueryString(qs: string): string {
  const p = new URLSearchParams(qs || undefined)
  const emptyKeys: string[] = []
  p.forEach((v, k) => {
    if (v === '' || v == null) emptyKeys.push(k)
  })
  emptyKeys.forEach((k) => p.delete(k))
  if (!p.has('per_page')) p.set('per_page', '100')
  if (!p.has('sort_by')) p.set('sort_by', 'week_start')
  if (!p.has('sort_dir')) p.set('sort_dir', 'desc')
  return p.toString()
}

function statusBadgeClass(status: string | null | undefined): string {
  const s = String(status ?? '').toLowerCase()
  if (s === 'on_track') return 'text-bg-success'
  if (s === 'slightly_behind') return 'text-bg-warning text-dark'
  if (s === 'behind') return 'text-bg-danger'
  return 'text-bg-secondary'
}

function truncate(s: string | null | undefined, max: number): string {
  const t = String(s ?? '').trim()
  if (t.length <= max) return t
  return `${t.slice(0, max - 1)}…`
}

/** `GET /api/v1/teacher/class-progress-history` — paginated report rows for the logged-in teacher. */
export function TeacherClassProgressHistoryPage() {
  const [search, setSearch] = useSearchParams()
  const qs = search.toString()

  const listPath = useMemo(() => {
    return `/class-progress-history?${buildHistoryQueryString(qs)}`
  }, [qs])

  const { data: raw, loading, error, reload } = useTeacherResource<unknown>(listPath)
  const parsed = useMemo(() => unwrapHistoryList(raw), [raw])
  const items = parsed?.items ?? []
  const pagination = parsed?.pagination

  const [draftWeekStart, setDraftWeekStart] = useState(() => search.get('week_start') ?? '')
  const [draftWeekEnd, setDraftWeekEnd] = useState(() => search.get('week_end') ?? '')
  const [draftSection, setDraftSection] = useState(() => search.get('class_section_id') ?? '')
  const [draftStatus, setDraftStatus] = useState(() => search.get('status') ?? '')
  const [draftSortDir, setDraftSortDir] = useState(() => search.get('sort_dir') || 'desc')

  useEffect(() => {
    const p = new URLSearchParams(buildHistoryQueryString(qs))
    setDraftWeekStart(p.get('week_start') ?? '')
    setDraftWeekEnd(p.get('week_end') ?? '')
    setDraftSection(p.get('class_section_id') ?? '')
    setDraftStatus(p.get('status') ?? '')
    setDraftSortDir(p.get('sort_dir') || 'desc')
  }, [qs])

  const sectionOptions = useMemo(() => {
    const m = new Map<number, string>()
    for (const r of items) {
      const id = Number(r.class_section_id ?? 0)
      if (!id) continue
      const name = String(r.class_section_name ?? '').trim() || `Section ${id}`
      if (!m.has(id)) m.set(id, name)
    }
    return [...m.entries()].sort((a, b) => a[0] - b[0])
  }, [items])

  function applyFilters(e: FormEvent) {
    e.preventDefault()
    const next = new URLSearchParams()
    next.set('per_page', search.get('per_page') || '100')
    next.set('sort_by', search.get('sort_by') || 'week_start')
    next.set('sort_dir', draftSortDir === 'asc' ? 'asc' : 'desc')
    if (draftWeekStart.trim()) next.set('week_start', draftWeekStart.trim())
    if (draftWeekEnd.trim()) next.set('week_end', draftWeekEnd.trim())
    if (draftSection.trim()) next.set('class_section_id', draftSection.trim())
    if (draftStatus.trim()) next.set('status', draftStatus.trim())
    next.delete('page')
    setSearch(next, { replace: true })
  }

  function resetFilters() {
    setDraftWeekStart('')
    setDraftWeekEnd('')
    setDraftSection('')
    setDraftStatus('')
    const next = new URLSearchParams()
    next.set('per_page', '100')
    next.set('sort_by', 'week_start')
    next.set('sort_dir', 'desc')
    setDraftSortDir('desc')
    setSearch(next, { replace: true })
  }

  const currentPage = Math.max(1, Number(pagination?.current_page) || 1)
  const lastPage = Math.max(1, Number(pagination?.last_page) || 1)
  const total = pagination?.total != null ? Number(pagination.total) : items.length

  function goPage(p: number) {
    const next = new URLSearchParams(buildHistoryQueryString(qs))
    if (p <= 1) next.delete('page')
    else next.set('page', String(p))
    setSearch(next, { replace: true })
  }

  return (
    <TeacherShell
      title="Class progress — history"
      subtitle="Your submitted weekly progress reports."
      loading={loading}
      error={error}
    >
      <div className="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
        <Link to="/app/teacher/class-progress-submit" className="btn btn-outline-primary btn-sm">
          Submit progress
        </Link>
        <button type="button" className="btn btn-outline-secondary btn-sm" onClick={() => reload()}>
          Refresh
        </button>
      </div>

      {!loading && raw != null && parsed == null ? (
        <div className="alert alert-warning">
          Unexpected response shape.
          <pre className="small mb-0 mt-2 bg-light p-2 rounded overflow-auto" style={{ maxHeight: 200 }}>
            {JSON.stringify(raw, null, 2)}
          </pre>
        </div>
      ) : null}

      <form className="card border mb-3" onSubmit={applyFilters}>
        <div className="card-body py-3">
          <div className="row g-2 align-items-end">
            <div className="col-md-3 col-lg-2">
              <label className="form-label small mb-0" htmlFor="hist-ws">
                Week from
              </label>
              <input
                id="hist-ws"
                type="date"
                className="form-control form-control-sm"
                value={draftWeekStart}
                onChange={(e) => setDraftWeekStart(e.target.value)}
              />
            </div>
            <div className="col-md-3 col-lg-2">
              <label className="form-label small mb-0" htmlFor="hist-we">
                Week to
              </label>
              <input
                id="hist-we"
                type="date"
                className="form-control form-control-sm"
                value={draftWeekEnd}
                onChange={(e) => setDraftWeekEnd(e.target.value)}
              />
            </div>
            <div className="col-md-3 col-lg-2">
              <label className="form-label small mb-0" htmlFor="hist-sec">
                Section
              </label>
              <select
                id="hist-sec"
                className="form-select form-select-sm"
                value={draftSection}
                onChange={(e) => setDraftSection(e.target.value)}
              >
                <option value="">All</option>
                {sectionOptions.map(([id, name]) => (
                  <option key={id} value={String(id)}>
                    {name}
                  </option>
                ))}
              </select>
            </div>
            <div className="col-md-3 col-lg-2">
              <label className="form-label small mb-0" htmlFor="hist-st">
                Status
              </label>
              <select
                id="hist-st"
                className="form-select form-select-sm"
                value={draftStatus}
                onChange={(e) => setDraftStatus(e.target.value)}
              >
                <option value="">All</option>
                {Object.entries(STATUS_OPTIONS).map(([value, label]) => (
                  <option key={value} value={value}>
                    {label}
                  </option>
                ))}
              </select>
            </div>
            <div className="col-md-3 col-lg-2">
              <label className="form-label small mb-0" htmlFor="hist-sort">
                Week order
              </label>
              <select
                id="hist-sort"
                className="form-select form-select-sm"
                value={draftSortDir}
                onChange={(e) => setDraftSortDir(e.target.value)}
              >
                <option value="desc">Newest first</option>
                <option value="asc">Oldest first</option>
              </select>
            </div>
            <div className="col-md-12 col-lg-4 d-flex flex-wrap gap-2">
              <button type="submit" className="btn btn-primary btn-sm">
                Apply filters
              </button>
              <button type="button" className="btn btn-outline-secondary btn-sm" onClick={resetFilters}>
                Reset
              </button>
            </div>
          </div>
        </div>
      </form>

      {items.length === 0 && !loading ? (
        <p className="text-muted mb-0">No progress reports match these filters.</p>
      ) : null}

      {items.length > 0 ? (
        <>
          <div className="table-responsive border rounded bg-white shadow-sm">
            <table className="table table-sm table-striped table-hover align-middle mb-0">
              <thead className="table-light">
                <tr>
                  <th scope="col">Week</th>
                  <th scope="col">Section</th>
                  <th scope="col">Subject</th>
                  <th scope="col">Status</th>
                  <th scope="col">Unit</th>
                  <th scope="col">Covered</th>
                  <th scope="col">Homework</th>
                  <th scope="col" className="text-nowrap">
                    Updated
                  </th>
                </tr>
              </thead>
              <tbody>
                {items.map((row) => {
                  const id = Number(row.id ?? 0)
                  const week =
                    row.week_start || row.week_end
                      ? `${formatProgressDate(row.week_start)} – ${formatProgressDate(row.week_end)}`
                      : '—'
                  const section = String(row.class_section_name ?? '').trim() || `ID ${row.class_section_id ?? '—'}`
                  const subject = String(row.subject ?? '—')
                  const isQuran = subject.toLowerCase().includes('quran')
                  const st = row.status_label ?? STATUS_OPTIONS[String(row.status ?? '')] ?? row.status ?? '—'

                  return (
                    <tr key={id || `${week}-${subject}`}>
                      <td className="text-nowrap small">{week}</td>
                      <td className="small">{section}</td>
                      <td className="small fw-semibold">{subject}</td>
                      <td>
                        <span className={`badge rounded-pill ${statusBadgeClass(row.status)}`}>{st}</span>
                      </td>
                      <td className="small">
                        <ClassProgressUnitDisplay unitTitle={row.unit_title} isQuran={isQuran} compact />
                      </td>
                      <td className="small text-muted" title={row.covered ?? undefined}>
                        {truncate(row.covered, 120) || '—'}
                      </td>
                      <td className="small text-muted" title={row.homework ?? undefined}>
                        {truncate(row.homework, 80) || '—'}
                      </td>
                      <td className="small text-nowrap text-muted">
                        {formatProgressDate(row.updated_at, true)}
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>

          {lastPage > 1 ? (
            <div className="d-flex flex-wrap align-items-center justify-content-between gap-2 mt-3">
              <span className="small text-muted">
                Page {currentPage} of {lastPage} ({total} total)
              </span>
              <div className="btn-group btn-group-sm">
                <button
                  type="button"
                  className="btn btn-outline-secondary"
                  disabled={currentPage <= 1}
                  onClick={() => goPage(currentPage - 1)}
                >
                  Previous
                </button>
                <button
                  type="button"
                  className="btn btn-outline-secondary"
                  disabled={currentPage >= lastPage}
                  onClick={() => goPage(currentPage + 1)}
                >
                  Next
                </button>
              </div>
            </div>
          ) : null}
        </>
      ) : null}
    </TeacherShell>
  )
}
