import { type FormEvent, useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import {
  fetchStickerFormOptions,
  fetchStickerPreviewCounts,
  fetchStudentsByClass,
  postStickerGenerate,
  type StudentOption,
  type StickerPreviewCounts,
} from '../../api/printables'
import { AcademicFilterBar } from '../discounts/AcademicFilterBar'

/** Student stickers — `/api/v1/administrator/printables/stickers/*` (JWT). SPA: `/app/printables_reports/stickers`. */

export function StickerFormPage() {
  const [searchParams] = useSearchParams()
  const schoolYear = searchParams.get('school_year') ?? undefined
  const semester = searchParams.get('semester') ?? undefined

  const [classes, setClasses] = useState<Array<{ class_section_id?: number; id?: number; class_section_name?: string }>>([])
  const [studentsAll, setStudentsAll] = useState<StudentOption[]>([])
  const [classId, setClassId] = useState('')
  const [studentId, setStudentId] = useState('')
  const [rows, setRows] = useState<StudentOption[]>([])
  const [loadingStudents, setLoadingStudents] = useState(false)

  const [previewOpen, setPreviewOpen] = useState(false)
  const [previewData, setPreviewData] = useState<StickerPreviewCounts | null>(null)
  const [previewMode, setPreviewMode] = useState<'all' | 'class'>('all')
  const [pendingFd, setPendingFd] = useState<FormData | null>(null)

  useEffect(() => {
    fetchStickerFormOptions({ school_year: schoolYear, semester })
      .then((d) => {
        setClasses(d.classes ?? [])
        setStudentsAll(d.students ?? [])
      })
      .catch(() => {})
  }, [schoolYear, semester])

  useEffect(() => {
    if (!classId) {
      setRows([])
      return
    }
    setLoadingStudents(true)
    fetchStudentsByClass(classId)
      .then(setRows)
      .catch(() => setRows([]))
      .finally(() => setLoadingStudents(false))
  }, [classId])

  async function handleSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const form = e.currentTarget
    const fd = new FormData(form)
    fd.set('school_year', schoolYear ?? '')
    fd.set('semester', semester ?? '')
    try {
      const blob = await postStickerGenerate(fd)
      window.open(URL.createObjectURL(blob), '_blank', 'noopener')
    } catch (err: unknown) {
      alert(err instanceof ApiHttpError ? err.message : 'Generate failed.')
    }
  }

  async function mirrorLayoutTo(fd: FormData, source: HTMLFormElement) {
    fd.set('sticker_size', (source.querySelector('[name=sticker_size]') as HTMLSelectElement)?.value ?? '')
    fd.set('sticker_width', (source.querySelector('[name=sticker_width]') as HTMLInputElement)?.value ?? '')
    fd.set('sticker_height', (source.querySelector('[name=sticker_height]') as HTMLInputElement)?.value ?? '')
    fd.set('stickers_per_page', (source.querySelector('[name=stickers_per_page]') as HTMLInputElement)?.value ?? '')
    fd.set('page_size', (source.querySelector('[name=page_size]') as HTMLSelectElement)?.value ?? '')
    fd.set('orientation', (source.querySelector('[name=orientation]') as HTMLSelectElement)?.value ?? '')
    fd.set('margin_left', (source.querySelector('[name=margin_left]') as HTMLInputElement)?.value ?? '')
    fd.set('margin_top', (source.querySelector('[name=margin_top]') as HTMLInputElement)?.value ?? '')
    fd.set('margin_right', (source.querySelector('[name=margin_right]') as HTMLInputElement)?.value ?? '')
    fd.set('margin_bottom', (source.querySelector('[name=margin_bottom]') as HTMLInputElement)?.value ?? '')
    fd.set('gap_x', (source.querySelector('[name=gap_x]') as HTMLInputElement)?.value ?? '')
    fd.set('gap_y', (source.querySelector('[name=gap_y]') as HTMLInputElement)?.value ?? '')
    fd.set('school_year', schoolYear ?? '')
    fd.set('semester', semester ?? '')
  }

  async function autoPrint(classScope: 'all' | 'class') {
    const form = document.getElementById('stickerForm') as HTMLFormElement | null
    if (!form) return
    try {
      const cid = classScope === 'class' ? classId : ''
      if (classScope === 'class' && !cid) {
        alert('Please select a class first.')
        return
      }
      const data = await fetchStickerPreviewCounts(cid || undefined)
      setPreviewData(data)
      setPreviewMode(classScope)
      const fd = new FormData()
      await mirrorLayoutTo(fd, form)
      fd.set('print_all', classScope === 'all' ? '1' : '0')
      if (cid) fd.set('class_id', cid)
      const students = data.students ?? []
      for (const s of students) {
        const copies = Number(s.primary_count) || 0
        if (copies <= 0) continue
        fd.append(`copies[${s.student_id}]`, String(copies))
      }
      setPendingFd(fd)
      setPreviewOpen(true)
    } catch (e: unknown) {
      alert(e instanceof ApiHttpError ? e.message : 'Preview failed.')
    }
  }

  async function proceedPrint() {
    if (!pendingFd) return
    try {
      const blob = await postStickerGenerate(pendingFd)
      window.open(URL.createObjectURL(blob), '_blank', 'noopener')
    } catch (e: unknown) {
      alert(e instanceof ApiHttpError ? e.message : 'Generate failed.')
    }
    setPreviewOpen(false)
  }

  function fillAllQty(n: number) {
    document.querySelectorAll<HTMLInputElement>('input[name^="copies["]').forEach((inp) => {
      inp.value = String(Math.max(0, Math.min(100, n)))
    })
  }

  return (
    <div className="container-fluid py-3">
      <h2 className="mb-4">Generate Student Stickers</h2>
      <AcademicFilterBar />

      <div className="d-flex gap-2 mb-3 flex-wrap">
        <button type="button" className="btn btn-primary" onClick={() => autoPrint('all')}>
          Auto-count & Print All
        </button>
        <button type="button" className="btn btn-outline-primary" onClick={() => autoPrint('class')}>
          Auto-count Selected Class
        </button>
      </div>

      <form id="stickerForm" onSubmit={handleSubmit}>
        <div className="row g-3 mb-4">
          <div className="col-md-4">
            <label className="form-label" htmlFor="sticker_size">
              Sticker Size
            </label>
            <select
              name="sticker_size"
              id="sticker_size"
              className="form-select"
              required
              defaultValue="102x34"
            >
              <option value="60x30">Small — 60×30 mm</option>
              <option value="102x34">Medium — 102×34 mm</option>
              <option value="90x45">Large — 90×45 mm</option>
              <option value="custom">Custom (enter mm below)</option>
            </select>
            <div className="row g-2 mt-2">
              <div className="col-6">
                <input
                  type="number"
                  min={1}
                  step={0.1}
                  className="form-control"
                  name="sticker_width"
                  placeholder="Width (mm)"
                />
              </div>
              <div className="col-6">
                <input
                  type="number"
                  min={1}
                  step={0.1}
                  className="form-control"
                  name="sticker_height"
                  placeholder="Height (mm)"
                />
              </div>
            </div>
          </div>
          <div className="col-md-4">
            <label className="form-label" htmlFor="stickers_per_page">
              Stickers per Page
            </label>
            <input
              type="number"
              min={1}
              max={200}
              defaultValue={20}
              className="form-control"
              id="stickers_per_page"
              name="stickers_per_page"
              required
            />
          </div>
          <div className="col-md-4">
            <label className="form-label">Paper / Orientation</label>
            <div className="input-group">
              <select name="page_size" id="page_size" className="form-select" defaultValue="A4">
                <option value="A4">A4</option>
                <option value="Letter">Letter</option>
              </select>
              <select name="orientation" id="orientation" className="form-select" style={{ maxWidth: 140 }} defaultValue="P">
                <option value="P">Portrait</option>
                <option value="L">Landscape</option>
              </select>
            </div>
          </div>
        </div>

        <div className="row g-3 mb-4">
          <div className="col-md-6">
            <label className="form-label">Margins (mm)</label>
            <div className="row g-2">
              <div className="col-6 col-lg-3">
                <input type="number" min={0} step={0.1} className="form-control" name="margin_left" defaultValue={3} />
                <div className="form-text">Left</div>
              </div>
              <div className="col-6 col-lg-3">
                <input type="number" min={0} step={0.1} className="form-control" name="margin_top" defaultValue={12} />
                <div className="form-text">Top</div>
              </div>
              <div className="col-6 col-lg-3">
                <input type="number" min={0} step={0.1} className="form-control" name="margin_right" defaultValue={3} />
                <div className="form-text">Right</div>
              </div>
              <div className="col-6 col-lg-3">
                <input type="number" min={0} step={0.1} className="form-control" name="margin_bottom" defaultValue={12} />
                <div className="form-text">Bottom</div>
              </div>
            </div>
          </div>
          <div className="col-md-6">
            <label className="form-label">Gaps Between Stickers (mm)</label>
            <div className="row g-2">
              <div className="col-6">
                <input type="number" min={0} step={0.1} className="form-control" name="gap_x" defaultValue={3} />
                <div className="form-text">Horizontal (X)</div>
              </div>
              <div className="col-6">
                <input type="number" min={0} step={0.1} className="form-control" name="gap_y" defaultValue={3} />
                <div className="form-text">Vertical (Y)</div>
              </div>
            </div>
          </div>
        </div>

        <div className="row g-3 align-items-end mb-3">
          <div className="col-md-6">
            <label className="form-label" htmlFor="class_id">
              Select a Class
            </label>
            <select
              name="class_id"
              id="class_id"
              className="form-select"
              value={classId}
              onChange={(e) => {
                setClassId(e.target.value)
                setStudentId('')
              }}
            >
              <option value="">-- Select Class --</option>
              {classes.map((c) => {
                const id = String(c.class_section_id ?? c.id ?? '')
                return (
                  <option key={id} value={id}>
                    {c.class_section_name ?? id}
                  </option>
                )
              })}
            </select>
          </div>
          <div className="col-md-3">
            <label className="form-label" htmlFor="student_id">
              Or Select a Specific Student (optional)
            </label>
            <select
              name="student_id"
              id="student_id"
              className="form-select"
              value={studentId}
              onChange={(e) => {
                setStudentId(e.target.value)
                if (e.target.value) setClassId('')
              }}
            >
              <option value="">-- None (generate by class) --</option>
              {studentsAll.map((s) => (
                <option key={String(s.id)} value={String(s.id)}>
                  {(s.firstname ?? '') + ' ' + (s.lastname ?? '')}
                </option>
              ))}
            </select>
          </div>
          <div className="col-md-3">
            <label className="form-label" htmlFor="single_copies">
              Copies (if a student is selected)
            </label>
            <input
              type="number"
              min={0}
              max={100}
              defaultValue={1}
              className="form-control"
              name="single_copies"
              id="single_copies"
            />
          </div>
        </div>

        <div className="mb-4 d-flex gap-2 align-items-center flex-wrap">
          <button type="submit" className="btn btn-primary">
            Generate Stickers
          </button>
          <div className="input-group" style={{ maxWidth: 260 }}>
            <span className="input-group-text">Set all Qty</span>
            <input type="number" min={0} max={100} defaultValue={1} id="fillAllQty" className="form-control" />
            <button type="button" className="btn btn-outline-secondary" onClick={() => fillAllQty(Number((document.getElementById('fillAllQty') as HTMLInputElement)?.value || 1))}>
              Apply
            </button>
          </div>
        </div>

        {classId ? (
          <div className="mt-2">
            <div className="table-responsive">
              <table className="table table-bordered table-striped mb-0">
                <thead>
                  <tr>
                    <th style={{ width: '50%' }}>Name</th>
                    <th>Grade</th>
                    <th>Gender</th>
                    <th style={{ width: 120 }}>Qty</th>
                  </tr>
                </thead>
                <tbody>
                  {loadingStudents ? (
                    <tr>
                      <td colSpan={4} className="text-center text-muted">
                        Loading students…
                      </td>
                    </tr>
                  ) : rows.length === 0 ? (
                    <tr>
                      <td colSpan={4} className="text-center text-muted">
                        No students found for this class.
                      </td>
                    </tr>
                  ) : (
                    rows.map((stu) => (
                      <tr key={String(stu.id)}>
                        <td>
                          {(stu.firstname ?? '') + ' ' + (stu.lastname ?? '')}
                        </td>
                        <td>{stu.registration_grade ?? ''}</td>
                        <td>{stu.gender ?? ''}</td>
                        <td>
                          <input
                            type="number"
                            className="form-control form-control-sm"
                            name={`copies[${stu.id}]`}
                            min={0}
                            max={100}
                            defaultValue={1}
                          />
                        </td>
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </div>
          </div>
        ) : null}
      </form>

      {previewOpen ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.35)' }}>
          <div className="modal-dialog modal-sm modal-dialog-centered">
            <div className="modal-content">
              <div className="modal-header">
                <h6 className="modal-title">Sticker Totals</h6>
                <button type="button" className="btn-close" onClick={() => setPreviewOpen(false)} />
              </div>
              <div className="modal-body small">
                <div>
                  <strong>Students:</strong> {previewData?.totals?.students ?? previewData?.students?.length ?? '—'}
                </div>
                <div>
                  <strong>Total stickers:</strong>{' '}
                  {previewData?.totals?.stickers ??
                    (previewData?.students ?? []).reduce((s, x) => s + (Number(x.primary_count) || 0), 0)}
                </div>
                <div className="text-muted mt-2">Mode: {previewMode === 'all' ? 'All students' : 'Selected class'}</div>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-success" onClick={proceedPrint}>
                  Proceed to Print
                </button>
              </div>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  )
}
