'use client'

import { PointerEvent, useEffect, useMemo, useRef, useState } from 'react'
import { ArrowLeft, Loader2, UserRoundCheck, X } from 'lucide-react'

import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { generateIdPhoto } from '@/lib/certificate-browser'
import {
  DEFAULT_ID_PHOTO_CROP,
  type IdPhotoCrop,
  type Rect,
  idPhotoBackgroundColor,
  idPhotoBackgroundLabel,
  idPhotoSizeLabel,
  resolveIdPhotoCrop,
  resolveIdPhotoConfig
} from '@/lib/certificate-types'
import {
  type ClassItem,
  type ClassStudent,
  hydrateClassItem,
  hydrateClassMetadata,
  loadAppState,
  persistClasses,
  saveAppState
} from '@/lib/certificate-page-utils'
import type { PersistedAppState } from '@/lib/storage-types'

function navigate(href: string) {
  window.history.pushState(null, '', href)
  window.dispatchEvent(new PopStateEvent('popstate'))
}

export default function StudentsPage() {
  const cropImageRef = useRef<HTMLImageElement | null>(null)
  const [storedState, setStoredState] = useState<PersistedAppState | null>(null)
  const [classes, setClasses] = useState<ClassItem[]>([])
  const [activeClass, setActiveClass] = useState<ClassItem | null>(null)
  const [selectedStudentId, setSelectedStudentId] = useState('')
  const [cropDraft, setCropDraft] = useState<IdPhotoCrop>(DEFAULT_ID_PHOTO_CROP)
  const [cropDragStart, setCropDragStart] = useState<{ x: number; y: number } | null>(null)
  const [isWorking, setIsWorking] = useState(false)

  const selectedStudent = useMemo(
    () => activeClass?.students.find((student) => student.id === selectedStudentId),
    [activeClass?.students, selectedStudentId]
  )
  const idPhotoConfig = resolveIdPhotoConfig(activeClass?.idPhotoConfig)

  useEffect(() => {
    if (selectedStudent) {
      setCropDraft(resolveIdPhotoCrop(selectedStudent.idPhotoCrop))
    }
  }, [selectedStudent])

  useEffect(() => {
    async function loadStudents() {
      const state = await loadAppState()
      const classIdFromUrl = new URLSearchParams(window.location.search).get('classId') ?? ''
      const persistedClass =
        state.classes.find((classItem) => classItem.id === classIdFromUrl) ?? state.classes[0]
      const restoredClasses = (state.classes ?? []).map(hydrateClassMetadata)
      const hydratedClass = persistedClass ? await hydrateClassItem(persistedClass) : null

      setStoredState(state)
      setClasses(
        hydratedClass
          ? restoredClasses.map((classItem) => (classItem.id === hydratedClass.id ? hydratedClass : classItem))
          : restoredClasses
      )
      setActiveClass(hydratedClass)
    }

    loadStudents()
  }, [])

  async function persistActiveClass(nextClass: ClassItem) {
    if (!storedState) {
      return
    }

    const nextClasses = classes.map((classItem) => (classItem.id === nextClass.id ? nextClass : classItem))
    const nextState: PersistedAppState = {
      ...storedState,
      classes: persistClasses(nextClasses, storedState),
      activeClassId: nextClass.id
    }

    await saveAppState(nextState)
    setStoredState(nextState)
    setClasses(nextClasses)
    setActiveClass(nextClass)
  }

  async function generateStudentIdPhoto(student: ClassStudent) {
    if (!activeClass || !student.photo) {
      return
    }

    setIsWorking(true)

    try {
      const crop = resolveIdPhotoCrop(cropDraft)
      const idPhoto = await generateIdPhoto(student.photo, idPhotoConfig, crop)
      const nextClass: ClassItem = {
        ...activeClass,
        idPhotoConfig,
        students: activeClass.students.map((item) =>
          item.id === student.id
            ? {
              ...item,
              idPhoto,
              idPhotoFileName: idPhoto.fileName,
              idPhotoCrop: crop
            }
            : item
        )
      }

      await persistActiveClass(nextClass)
    } finally {
      setIsWorking(false)
    }
  }

  function cropPoint(event: PointerEvent<HTMLElement>) {
    const image = cropImageRef.current

    if (!image) {
      return null
    }

    const bounds = image.getBoundingClientRect()
    const x = (event.clientX - bounds.left) / bounds.width
    const y = (event.clientY - bounds.top) / bounds.height

    return {
      x: Math.min(Math.max(x, 0), 1),
      y: Math.min(Math.max(y, 0), 1)
    }
  }

  function cropRectFromPoints(start: { x: number; y: number }, end: { x: number; y: number }): Rect {
    return {
      x: Math.min(start.x, end.x),
      y: Math.min(start.y, end.y),
      width: Math.max(Math.abs(end.x - start.x), 0.01),
      height: Math.max(Math.abs(end.y - start.y), 0.01)
    }
  }

  function handleCropPointerDown(event: PointerEvent<HTMLElement>) {
    const point = cropPoint(event)

    if (!point) {
      return
    }

    event.currentTarget.setPointerCapture(event.pointerId)
    setCropDragStart(point)
    setCropDraft((current) => resolveIdPhotoCrop({ ...current, sourceRect: { ...point, width: 0.01, height: 0.01 } }))
  }

  function handleCropPointerMove(event: PointerEvent<HTMLElement>) {
    if (!cropDragStart) {
      return
    }

    const point = cropPoint(event)

    if (!point) {
      return
    }

    setCropDraft((current) =>
      resolveIdPhotoCrop({
        ...current,
        sourceRect: cropRectFromPoints(cropDragStart, point)
      })
    )
  }

  function handleCropPointerUp(event: PointerEvent<HTMLElement>) {
    if (cropDragStart) {
      handleCropPointerMove(event)
    }
    setCropDragStart(null)
  }

  if (!activeClass) {
    return (
      <div className="rounded-md border border-dashed bg-card p-10 text-center text-muted-foreground">
        正在加载幼儿信息...
      </div>
    )
  }

  return (
    <div className="space-y-5">
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div>
          <p className="text-sm text-muted-foreground">Student Management</p>
          <h2 className="text-2xl font-semibold tracking-normal">{activeClass.name}幼儿信息</h2>
          <div className="mt-2 flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
            <span
              className="h-4 w-4 rounded-full border"
              style={{ backgroundColor: idPhotoBackgroundColor(idPhotoConfig) }}
            />
            <span>
              证件照：{idPhotoSizeLabel(idPhotoConfig.size)} / {idPhotoBackgroundLabel(idPhotoConfig.background)}
            </span>
          </div>
        </div>
        <Button type="button" variant="outline" onClick={() => navigate('/classes')}>
          <ArrowLeft />
          返回班级
        </Button>
      </div>

      {activeClass.students.length > 0 ? (
        <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
          {activeClass.students.map((student) => (
            <Card key={student.id} className="overflow-hidden">
              <div className="grid grid-cols-2 gap-2 bg-muted p-2">
                <div className="aspect-[3/4] overflow-hidden rounded-sm border bg-background">
                  {student.photo ? (
                    <img src={student.photo.dataUrl} alt={`${student.name}原始照片`} className="h-full w-full object-cover" />
                  ) : (
                    <div className="flex h-full items-center justify-center px-3 text-center text-xs text-muted-foreground">
                      未上传原图
                    </div>
                  )}
                </div>
                <div className="aspect-[3/4] overflow-hidden rounded-sm border bg-background">
                  {student.idPhoto ? (
                    <img src={student.idPhoto.dataUrl} alt={`${student.name}证件照`} className="h-full w-full object-cover" />
                  ) : (
                    <div className="flex h-full items-center justify-center px-3 text-center text-xs text-muted-foreground">
                      未生成证件照
                    </div>
                  )}
                </div>
              </div>
              <CardContent className="space-y-3 p-4">
                <div>
                  <h3 className="text-base font-semibold">{student.name}</h3>
                  <p className="mt-1 text-xs text-muted-foreground">{student.idPhoto ? '证件照已生成' : '证件照待生成'}</p>
                </div>
                <Button type="button" size="sm" className="w-full" onClick={() => setSelectedStudentId(student.id)}>
                  查看幼儿详情
                </Button>
              </CardContent>
            </Card>
          ))}
        </div>
      ) : (
        <Card className="border-dashed">
          <CardContent className="p-10 text-center text-muted-foreground">
            当前班级还没有幼儿资料。
          </CardContent>
        </Card>
      )}

      {selectedStudent ? (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center bg-foreground/35 p-4"
          role="dialog"
          aria-modal="true"
          aria-labelledby="student-detail-title"
        >
          <Card className="max-h-[90vh] w-full max-w-3xl overflow-auto shadow-xl">
            <CardHeader className="flex-row items-center justify-between space-y-0">
              <CardTitle id="student-detail-title">{selectedStudent.name}详情</CardTitle>
              <Button type="button" size="icon" variant="ghost" aria-label="关闭详情" onClick={() => setSelectedStudentId('')}>
                <X />
              </Button>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="grid gap-4 md:grid-cols-2">
                <div className="space-y-2">
                  <div className="text-sm font-medium">原始照片</div>
                  <div className="overflow-hidden rounded-md border bg-muted">
                    {selectedStudent.photo ? (
                      <div
                        className="relative cursor-crosshair select-none"
                        onPointerDown={handleCropPointerDown}
                        onPointerMove={handleCropPointerMove}
                        onPointerUp={handleCropPointerUp}
                        onPointerCancel={() => setCropDragStart(null)}
                      >
                        <img
                          ref={cropImageRef}
                          src={selectedStudent.photo.dataUrl}
                          alt={`${selectedStudent.name}原始照片`}
                          className="block w-full"
                          draggable={false}
                        />
                        {cropDraft.sourceRect ? (
                          <div
                            className="pointer-events-none absolute border-2 border-primary bg-primary/10 shadow-[0_0_0_9999px_rgba(15,23,42,0.35)]"
                            style={{
                              left: `${cropDraft.sourceRect.x * 100}%`,
                              top: `${cropDraft.sourceRect.y * 100}%`,
                              width: `${cropDraft.sourceRect.width * 100}%`,
                              height: `${cropDraft.sourceRect.height * 100}%`
                            }}
                          />
                        ) : null}
                      </div>
                    ) : (
                      <div className="flex h-full items-center justify-center text-sm text-muted-foreground">
                        未上传原图
                      </div>
                    )}
                  </div>
                </div>
                <div className="space-y-2">
                  <div className="text-sm font-medium">证件照</div>
                  <div className="aspect-[3/4] overflow-hidden rounded-md border bg-muted">
                    {selectedStudent.idPhoto ? (
                      <img
                        src={selectedStudent.idPhoto.dataUrl}
                        alt={`${selectedStudent.name}证件照`}
                        className="h-full w-full object-contain"
                      />
                    ) : (
                      <div className="flex h-full items-center justify-center text-sm text-muted-foreground">
                        未生成证件照
                      </div>
                    )}
                  </div>
                </div>
              </div>

              <div className="rounded-md border bg-muted/30 p-4">
                <div className="text-sm font-medium">证件照框选裁剪</div>
                <p className="mt-1 text-sm text-muted-foreground">
                  在左侧原始照片上按住鼠标拖拽，自由框选需要换底生成证件照的范围。
                </p>
              </div>

              <div className="flex justify-end gap-2">
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => setCropDraft(resolveIdPhotoCrop(DEFAULT_ID_PHOTO_CROP))}
                >
                  清除框选
                </Button>
                <Button type="button" variant="outline" onClick={() => setSelectedStudentId('')}>
                  关闭
                </Button>
                <Button
                  type="button"
                  disabled={isWorking || !selectedStudent.photo}
                  onClick={() => generateStudentIdPhoto(selectedStudent)}
                >
                  {isWorking ? <Loader2 className="animate-spin" /> : <UserRoundCheck />}
                  生成证件照
                </Button>
              </div>
            </CardContent>
          </Card>
        </div>
      ) : null}
    </div>
  )
}
