import { type FormEvent, useEffect, useState } from 'react'
import { ApiHttpError, apiFetch } from '../../api/http'
import { useAuth } from '../../auth/AuthProvider'
import {
  createCopyRequest,
  createPrintRequest,
  deletePrintRequest,
  fetchTeacherPrintRequestsContext,
  openPrintRequestFile,
  updatePrintRequest,
  type PrintRequestRow,
} from '../../api/printRequests'

type TeacherPrintRequestsContextPayload = Awaited<ReturnType<typeof fetchTeacherPrintRequestsContext>>

function unwrapTeacherPrintRequestsContext(raw: TeacherPrintRequestsContextPayload | null): TeacherPrintRequestsContextPayload | null {
  if (raw == null || typeof raw !== 'object') return null
  const record = raw as Record<string, unknown>
  const inner = record.data
  if (inner != null && typeof inner === 'object' && !Array.isArray(inner)) {
    return inner as TeacherPrintRequestsContextPayload
  }
  return raw
}

function statusBadge(req: PrintRequestRow): { className: string; label: string } {
  const status = String(req.status ?? '')
  const adminFirst = String(req.admin_firstname ?? '').trim()
  const adminLast = String(req.admin_lastname ?? '').trim()
  const assignedAdmin = `${adminFirst} ${adminLast}`.trim()
  switch (status) {
    case 'not_assigned':
      return { className: 'bg-secondary', label: 'Pending assignment' }
    case 'assigned':
      return {
        className: 'bg-warning text-dark',
        label: assignedAdmin ? `Assigned to ${assignedAdmin}` : 'Assigned',
      }
    case 'done':
      return { className: 'bg-primary', label: 'Printed. Pending delivery/pick-up' }
    case 'delivered':
      return { className: 'bg-success', label: 'Done' }
    default:
      return { className: 'bg-light text-dark', label: status.replace(/_/g, ' ') }
  }
}

function combineRequiredBy(dateYmd: string, timeHm: string): string {
  if (!dateYmd || !timeHm) return ''
  return `${dateYmd}T${timeHm}`
}

type FrontendMeResponse = {
  status?: boolean
  data?: {
    user?: {
      class_section_id?: number | null
      class_section_name?: string | null
    } | null
  } | null
}

export function TeacherPrintRequestsPage() {
  const { user } = useAuth()
  const [tab, setTab] = useState<'print' | 'copy'>('print')
  const [ctx, setCtx] = useState<Awaited<ReturnType<typeof fetchTeacherPrintRequestsContext>> | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [msg, setMsg] = useState<string | null>(null)
  const [sessionClassSectionId, setSessionClassSectionId] = useState<number | null>(
    user?.class_section_id != null ? Number(user.class_section_id) : null,
  )
  const [sessionClassSectionName, setSessionClassSectionName] = useState<string | null>(
    user?.class_section_name != null ? String(user.class_section_name) : null,
  )

  const [editOpen, setEditOpen] = useState(false)
  const [editRow, setEditRow] = useState<PrintRequestRow | null>(null)

  const [reqDate, setReqDate] = useState('')
  const [reqTime, setReqTime] = useState('')
  const [copyReqDate, setCopyReqDate] = useState('')
  const [copyReqTime, setCopyReqTime] = useState('')
  const [editReqDate, setEditReqDate] = useState('')
  const [editReqTime, setEditReqTime] = useState('')
  const payload = unwrapTeacherPrintRequestsContext(ctx)

  function load() {
    setLoading(true)
    setError(null)
    fetchTeacherPrintRequestsContext()
      .then(setCtx)
      .catch((e: unknown) =>
        setError(e instanceof ApiHttpError ? e.message : 'Could not load print requests.'),
      )
      .finally(() => setLoading(false))
  }

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

  useEffect(() => {
    if (user?.class_section_id != null) {
      setSessionClassSectionId(Number(user.class_section_id))
      setSessionClassSectionName(user?.class_section_name != null ? String(user.class_section_name) : null)
      return
    }

    let cancelled = false

    apiFetch<FrontendMeResponse>('/api/v1/frontend/me')
      .then((body) => {
        if (cancelled) return
        const nextId = body?.data?.user?.class_section_id
        const nextName = body?.data?.user?.class_section_name
        setSessionClassSectionId(nextId != null ? Number(nextId) : null)
        setSessionClassSectionName(nextName != null ? String(nextName) : null)
      })
      .catch(() => {
        if (cancelled) return
        setSessionClassSectionId(null)
        setSessionClassSectionName(null)
      })

    return () => {
      cancelled = true
    }
  }, [user?.class_section_id, user?.class_section_name])

  const authClassSectionId = sessionClassSectionId
  const classId =
    payload?.class_id != null
      ? Number(payload.class_id)
      : payload?.class_section_id != null
        ? Number(payload.class_section_id)
        : authClassSectionId
  const activeClassLabel =
    payload?.class_section_name?.trim() ||
    (sessionClassSectionName != null ? String(sessionClassSectionName).trim() : '') ||
    (classId ? `Class section ${classId}` : '')
  const rows = (payload?.print_requests ?? []) as PrintRequestRow[]
  const sundays = payload?.sundays ?? []
  const times = payload?.times ?? []

  async function onCreatePrint(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    if (!classId) return
    const fd = new FormData(e.currentTarget)
    const rb = combineRequiredBy(reqDate, reqTime)
    fd.set('required_by', rb)
    setMsg(null)
    try {
      await createPrintRequest(fd)
      setMsg('Print request submitted.')
      load()
      e.currentTarget.reset()
      setReqDate('')
      setReqTime('')
    } catch (err: unknown) {
      setMsg(err instanceof ApiHttpError ? err.message : 'Submit failed.')
    }
  }

  async function onCreateCopy(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    if (!classId) return
    const fd = new FormData(e.currentTarget)
    fd.set('required_by', combineRequiredBy(copyReqDate, copyReqTime))
    setMsg(null)
    try {
      await createCopyRequest(fd)
      setMsg('Copy request submitted.')
      load()
      e.currentTarget.reset()
      setCopyReqDate('')
      setCopyReqTime('')
    } catch (err: unknown) {
      setMsg(err instanceof ApiHttpError ? err.message : 'Submit failed.')
    }
  }

  function openEdit(row: PrintRequestRow) {
    setEditRow(row)
    const raw = String(row.required_by ?? '')
    const m = raw.match(/^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})/)
    if (m) {
      setEditReqDate(m[1])
      setEditReqTime(m[2])
    } else {
      setEditReqDate('')
      setEditReqTime('')
    }
    setEditOpen(true)
  }

  async function onEditSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    if (!editRow) return
    const rawId = editRow.id
    if (rawId == null || rawId === '') return
    const id = rawId as number | string
    const fd = new FormData(e.currentTarget)
    fd.set('required_by', combineRequiredBy(editReqDate, editReqTime))
    setMsg(null)
    try {
      await updatePrintRequest(id, fd)
      setMsg('Request updated.')
      setEditOpen(false)
      load()
    } catch (err: unknown) {
      setMsg(err instanceof ApiHttpError ? err.message : 'Update failed.')
    }
  }

  async function onDelete(id: number | string) {
    if (!confirm('Are you sure you want to delete this request?')) return
    try {
      await deletePrintRequest(id)
      load()
    } catch (err: unknown) {
      setMsg(err instanceof ApiHttpError ? err.message : 'Delete failed.')
    }
  }

  async function onFileClick(requestId: number | string) {
    try {
      await openPrintRequestFile(requestId)
    } catch {
      setMsg('Could not open file.')
    }
  }

  return (
    <div className="container-fluid py-5">
      <h2>Print/Copy Requests</h2>
      {loading ? <p className="text-muted">Loading…</p> : null}
      {error ? <div className="alert alert-danger">{error}</div> : null}
      {msg ? <div className="alert alert-info">{msg}</div> : null}
      {activeClassLabel ? <div className="text-muted small mb-3">Active class section: {activeClassLabel}</div> : null}

      <div className="card my-4">
        <div className="card-header pb-0">
          <div className="btn-group" role="group">
            <button
              type="button"
              className={`btn btn-outline-primary ${tab === 'print' ? 'active' : ''}`}
              onClick={() => setTab('print')}
            >
              Print Request
            </button>
            <button
              type="button"
              className={`btn btn-outline-primary ${tab === 'copy' ? 'active' : ''}`}
              onClick={() => setTab('copy')}
            >
              Copy Request
            </button>
          </div>
        </div>
        <div className="card-body">
          {tab === 'print' ? (
            <form onSubmit={onCreatePrint} encType="multipart/form-data">
              <div className="row g-3 align-items-end">
                <div className="col-md-3">
                  <label className="form-label" htmlFor="file">
                    File (PDF, JPG, PNG, DOC, TXT)
                  </label>
                  <input type="file" className="form-control" id="file" name="file" required />
                </div>
                <div className="col-md-3">
                  <label className="form-label" htmlFor="page_selection">
                    Page Selection (Optional)
                  </label>
                  <input
                    type="text"
                    className="form-control"
                    id="page_selection"
                    name="page_selection"
                    placeholder="Examples: 1-4, 8, 12-15"
                  />
                </div>
                <div className="col-md-3">
                  <label className="form-label" htmlFor="num_copies">
                    Number of Copies
                  </label>
                  <input
                    type="number"
                    className="form-control"
                    id="num_copies"
                    name="num_copies"
                    min={1}
                    required
                  />
                </div>
                <div className="col-md-3">
                  <label className="form-label" htmlFor="pickup_method">
                    Pickup Method
                  </label>
                  <select className="form-select" id="pickup_method" name="pickup_method" required>
                    <option value="">Please select</option>
                    <option value="Self Pickup">Self Pickup</option>
                    <option value="Delivered to class">Delivered to class</option>
                  </select>
                </div>
              </div>
              <div className="row g-3 mt-3">
                <div className="col-md-6">
                  <label className="form-label">Job Needed By</label>
                  <div className="row g-2">
                    <div className="col">
                      <select
                        className="form-select"
                        value={reqDate}
                        onChange={(e) => setReqDate(e.target.value)}
                        required
                      >
                        <option value="">Select a Sunday</option>
                        {sundays.map((s) => (
                          <option key={s} value={s}>
                            {s}
                          </option>
                        ))}
                      </select>
                    </div>
                    <div className="col">
                      <select
                        className="form-select"
                        value={reqTime}
                        onChange={(e) => setReqTime(e.target.value)}
                        required
                      >
                        <option value="">Select a time</option>
                        {times.map((t) => (
                          <option key={t} value={t}>
                            {t}
                          </option>
                        ))}
                      </select>
                    </div>
                  </div>
                </div>
                <div className="col-md-6 text-end">
                  {classId ? <input type="hidden" name="class_id" value={classId} /> : null}
                  {!classId ? (
                    <div className="alert alert-warning mb-0 text-start">
                      No class section is available for your teacher session. Re-login or contact the administrator if
                      your class assignment is missing.
                    </div>
                  ) : null}
                  <button type="submit" className="btn btn-primary mt-3" disabled={!classId}>
                    Submit Request
                  </button>
                </div>
              </div>
            </form>
          ) : (
            <div>
              <p className="text-muted">
                Submit a copy request for a physical document. Bring the originals to the copy center instead of
                uploading a file.
              </p>
              <form onSubmit={onCreateCopy}>
                <div className="row g-3">
                  <div className="col-md-4">
                    <label className="form-label" htmlFor="copy_num_copies">
                      Number of Copies
                    </label>
                    <input
                      type="number"
                      className="form-control"
                      id="copy_num_copies"
                      name="num_copies"
                      min={1}
                      required
                    />
                  </div>
                  <div className="col-md-4">
                    <label className="form-label">Job Needed By</label>
                    <div className="row g-2">
                      <div className="col">
                        <select
                          className="form-select"
                          value={copyReqDate}
                          onChange={(e) => setCopyReqDate(e.target.value)}
                          required
                        >
                          <option value="">Select a Sunday</option>
                          {sundays.map((s) => (
                            <option key={s} value={s}>
                              {s}
                            </option>
                          ))}
                        </select>
                      </div>
                      <div className="col">
                        <select
                          className="form-select"
                          value={copyReqTime}
                          onChange={(e) => setCopyReqTime(e.target.value)}
                          required
                        >
                          <option value="">Select a time</option>
                          {times.map((t) => (
                            <option key={t} value={t}>
                              {t}
                            </option>
                          ))}
                        </select>
                      </div>
                    </div>
                  </div>
                  <div className="col-md-4">
                    <label className="form-label" htmlFor="copy_pickup_method">
                      Pickup Method
                    </label>
                    <select className="form-select" id="copy_pickup_method" name="pickup_method" required>
                      <option value="">Please select</option>
                      <option value="Self Pickup">Self Pickup</option>
                      <option value="Delivered to class">Delivered to class</option>
                    </select>
                  </div>
                </div>
                {classId ? <input type="hidden" name="class_id" value={classId} /> : null}
                <div className="form-text mt-2">
                  No file upload is required; please hand the original document to the copy staff after submitting.
                </div>
                <button type="submit" className="btn btn-outline-primary mt-3" disabled={!classId}>
                  Submit Copy Request
                </button>
              </form>
            </div>
          )}
        </div>
      </div>

      <div className="card">
        <div className="card-header">Print Request History</div>
        <div className="card-body table-responsive">
          <table className="table table-bordered table-striped">
            <thead>
              <tr>
                <th>ID</th>
                <th>File</th>
                <th>Pages</th>
                <th>Copies</th>
                <th>Job Needed By</th>
                <th>Pickup Method</th>
                <th>Status</th>
                <th>Actions</th>
              </tr>
            </thead>
            <tbody>
              {rows.length === 0 ? (
                <tr>
                  <td colSpan={8} className="text-center">
                    No print requests found.
                  </td>
                </tr>
              ) : (
                rows.map((request) => {
                  const id = request.id
                  const st = String(request.status ?? '')
                  const badge = statusBadge(request)
                  const fp = request.file_path ? String(request.file_path) : ''
                  return (
                    <tr key={String(id)}>
                      <td>{String(id)}</td>
                      <td>
                        {fp ? (
                          <button type="button" className="btn btn-link btn-sm p-0" onClick={() => onFileClick(id as string)}>
                            {fp}
                          </button>
                        ) : (
                          <span className="text-muted">Physical copy request</span>
                        )}
                      </td>
                      <td>
                        {request.page_selection ? String(request.page_selection) : <span className="text-muted">ALL</span>}
                      </td>
                      <td>{String(request.num_copies ?? '')}</td>
                      <td>{String(request.required_by ?? '')}</td>
                      <td>{String(request.pickup_method ?? '')}</td>
                      <td>
                        <span className={`badge ${badge.className}`}>{badge.label}</span>
                      </td>
                      <td>
                        <div className="d-flex flex-wrap gap-1">
                          {st === 'not_assigned' || st === 'assigned' ? (
                            <button type="button" className="btn btn-sm btn-warning" onClick={() => openEdit(request)}>
                              Edit
                            </button>
                          ) : null}
                          {st === 'not_assigned' ? (
                            <button type="button" className="btn btn-sm btn-danger" onClick={() => onDelete(id as string)}>
                              Delete
                            </button>
                          ) : null}
                        </div>
                      </td>
                    </tr>
                  )
                })
              )}
            </tbody>
          </table>
        </div>
      </div>

      {editOpen && editRow ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.4)' }}>
          <div className="modal-dialog">
            <form className="modal-content" onSubmit={onEditSubmit} encType="multipart/form-data">
              <div className="modal-header">
                <h5 className="modal-title">Edit Print Request</h5>
                <button type="button" className="btn-close" onClick={() => setEditOpen(false)} />
              </div>
              <div className="modal-body">
                <input type="hidden" name="request_id" value={String(editRow.id)} />
                <div className="mb-3">
                  <label className="form-label" htmlFor="edit_num_copies">
                    Number of Copies
                  </label>
                  <input
                    type="number"
                    className="form-control"
                    id="edit_num_copies"
                    name="num_copies"
                    defaultValue={Number(editRow.num_copies ?? 1)}
                    required
                  />
                </div>
                <div className="mb-3">
                  <label className="form-label" htmlFor="edit_page_selection">
                    Page Selection
                  </label>
                  <input
                    type="text"
                    className="form-control"
                    id="edit_page_selection"
                    name="page_selection"
                    defaultValue={String(editRow.page_selection ?? '')}
                  />
                </div>
                <div className="mb-3">
                  <label className="form-label" htmlFor="edit_pickup_method">
                    Pickup Method
                  </label>
                  <select
                    className="form-select"
                    id="edit_pickup_method"
                    name="pickup_method"
                    defaultValue={String(editRow.pickup_method ?? '')}
                    required
                  >
                    <option value="">Please select</option>
                    <option value="Self Pickup">Self Pickup</option>
                    <option value="Delivered to class">Delivered to class</option>
                  </select>
                </div>
                <div className="mb-3">
                  <label className="form-label">Job Needed By</label>
                  <div className="row">
                    <div className="col-md-8">
                      <select
                        className="form-select"
                        value={editReqDate}
                        onChange={(e) => setEditReqDate(e.target.value)}
                        required
                      >
                        <option value="">Select a Sunday</option>
                        {sundays.map((s) => (
                          <option key={s} value={s}>
                            {s}
                          </option>
                        ))}
                      </select>
                    </div>
                    <div className="col-md-4">
                      <select
                        className="form-select"
                        value={editReqTime}
                        onChange={(e) => setEditReqTime(e.target.value)}
                        required
                      >
                        <option value="">Select a time</option>
                        {times.map((t) => (
                          <option key={t} value={t}>
                            {t}
                          </option>
                        ))}
                      </select>
                    </div>
                  </div>
                </div>
                <div className="mb-3">
                  <label className="form-label" htmlFor="edit_file">
                    Replace File (optional)
                  </label>
                  <input type="file" className="form-control" id="edit_file" name="file" />
                </div>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-secondary" onClick={() => setEditOpen(false)}>
                  Close
                </button>
                <button type="submit" className="btn btn-primary">
                  Save changes
                </button>
              </div>
            </form>
          </div>
        </div>
      ) : null}
    </div>
  )
}
