import { useEffect, useMemo, useState } from 'react'
import {
  ExternalLink,
  File,
  FileSpreadsheet,
  FileText,
  Files,
  Presentation,
  Search,
  Trash2,
  Wand2
} from 'lucide-react'
import { toast } from 'sonner'

import { DashboardFooter } from '@renderer/components/dashboard/DashboardFooter'
import { Badge } from '@renderer/components/ui/badge'
import { Button } from '@renderer/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle
} from '@renderer/components/ui/card'
import { Input } from '@renderer/components/ui/input'
import { ScrollArea } from '@renderer/components/ui/scroll-area'
import { Select } from '@renderer/components/ui/select'
import type { ClassProfile, ReportFormat, ReportItem, TemplateItem } from '@renderer/types/app'

const formatOptions: Array<{ value: ReportFormat | 'all'; label: string }> = [
  { value: 'all', label: '全部格式' },
  { value: 'word', label: 'Word' },
  { value: 'ppt', label: 'PPT' },
  { value: 'pdf', label: 'PDF' },
  { value: 'excel', label: 'Excel' }
]

function getReportFormatLabel(format: ReportFormat): string {
  const option = formatOptions.find((item) => item.value === format)

  return option?.label ?? '文件'
}

function getReportIcon(format: ReportFormat): typeof FileText {
  if (format === 'ppt') {
    return Presentation
  }

  if (format === 'excel') {
    return FileSpreadsheet
  }

  if (format === 'pdf') {
    return File
  }

  return FileText
}

function formatDateTime(value: string): string {
  const date = new Date(value)

  if (Number.isNaN(date.getTime())) {
    return value || '未生成'
  }

  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  })
}

export function ReportPage(): React.JSX.Element {
  const [classes, setClasses] = useState<ClassProfile[]>([])
  const [templates, setTemplates] = useState<TemplateItem[]>([])
  const [reports, setReports] = useState<ReportItem[]>([])
  const [query, setQuery] = useState('')
  const [selectedClassId, setSelectedClassId] = useState('all')
  const [selectedFormat, setSelectedFormat] = useState<ReportFormat | 'all'>('all')
  const [selectedTemplateId, setSelectedTemplateId] = useState('')
  const [generating, setGenerating] = useState(false)
  const [openingId, setOpeningId] = useState('')
  const [deletingId, setDeletingId] = useState('')

  useEffect(() => {
    async function loadPageData(): Promise<void> {
      const [studentResponse, templateResponse, reportResponse] = await Promise.all([
        window.api.loadStudentData(),
        window.api.loadTemplates(),
        window.api.loadReports()
      ])

      if (!studentResponse.ok) {
        toast.error('读取班级失败', { description: studentResponse.message })
      } else {
        setClasses(studentResponse.classes)
      }

      if (!templateResponse.ok) {
        toast.error('读取模板失败', { description: templateResponse.message })
      } else {
        setTemplates(templateResponse.templates)
        setSelectedTemplateId(
          templateResponse.templates.find((template) => template.fileExtension === '.pptx')?.id ??
            ''
        )
      }

      if (!reportResponse.ok) {
        toast.error('读取报告失败', { description: reportResponse.message })
      } else {
        setReports(reportResponse.reports)
      }
    }

    loadPageData()
  }, [])

  const pptxTemplates = templates.filter((template) => template.fileExtension === '.pptx')

  const filteredReports = useMemo(() => {
    const keyword = query.trim().toLowerCase()

    return reports.filter((report) => {
      const matchesKeyword =
        !keyword ||
        [
          report.title,
          report.className,
          report.studentName,
          report.originalFileName,
          getReportFormatLabel(report.format)
        ]
          .join(' ')
          .toLowerCase()
          .includes(keyword)
      const matchesClass = selectedClassId === 'all' || report.classId === selectedClassId
      const matchesFormat = selectedFormat === 'all' || report.format === selectedFormat

      return matchesKeyword && matchesClass && matchesFormat
    })
  }, [query, reports, selectedClassId, selectedFormat])

  async function handleGenerateReports(): Promise<void> {
    if (!selectedTemplateId) {
      toast.error('请先选择 PPTX 报告模板')
      return
    }

    if (selectedClassId === 'all') {
      toast.error('请选择要生成报告的班级')
      return
    }

    setGenerating(true)

    try {
      const response = await window.api.generateReports({
        templateId: selectedTemplateId,
        classId: selectedClassId
      })

      if (!response.ok) {
        toast.error('生成报告失败', { description: response.message })
        return
      }

      setReports((currentReports) => [...response.reports, ...currentReports])
      toast.success('报告生成完成', {
        description:
          response.skipped.length > 0
            ? `成功 ${response.reports.length} 份，跳过 ${response.skipped.length} 份`
            : `成功 ${response.reports.length} 份`
      })
    } finally {
      setGenerating(false)
    }
  }

  async function handleOpenReport(report: ReportItem): Promise<void> {
    setOpeningId(report.id)

    try {
      const response = await window.api.openReport(report.filePath)

      if (!response.ok) {
        toast.error('打开报告失败', { description: response.message })
      }
    } finally {
      setOpeningId('')
    }
  }

  async function handleDeleteReport(report: ReportItem): Promise<void> {
    setDeletingId(report.id)

    try {
      const response = await window.api.deleteReport(report.id)

      if (!response.ok) {
        toast.error('删除报告失败', { description: response.message })
        return
      }

      setReports((currentReports) =>
        currentReports.filter((currentReport) => currentReport.id !== report.id)
      )
      toast.success(`已删除报告「${report.title}」`)
    } finally {
      setDeletingId('')
    }
  }

  return (
    <>
      <section className="space-y-4 bg-white px-4 py-4">
        <div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
          <div>
            <CardTitle>
              <div className="flex items-center gap-2">
                <Files className="size-5 text-primary" />
                报告管理
              </div>
            </CardTitle>
            <CardDescription className="mt-1">
              管理已生成的成长报告，支持按班级、学生姓名和文件格式筛选。
            </CardDescription>
          </div>
          <Badge variant={filteredReports.length > 0 ? 'success' : 'secondary'}>
            {filteredReports.length} 份报告
          </Badge>
        </div>

        <div className="grid gap-3 rounded-md border border-dashed bg-muted/30 p-4">
          <div className="grid gap-3 xl:grid-cols-[minmax(0,1fr)_220px_180px]">
            <div className="relative min-w-0">
              <Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                className="pl-9"
                value={query}
                onChange={(event) => setQuery(event.target.value)}
                placeholder="搜索学生姓名、班级、报告名称或文件名"
              />
            </div>
            <Select
              value={selectedClassId}
              onChange={(event) => setSelectedClassId(event.target.value)}
            >
              <option value="all">全部班级</option>
              {classes.map((classItem) => (
                <option key={classItem.id} value={classItem.id}>
                  {classItem.name}
                </option>
              ))}
            </Select>
            <Select
              value={selectedFormat}
              onChange={(event) => setSelectedFormat(event.target.value as ReportFormat | 'all')}
            >
              {formatOptions.map((option) => (
                <option key={option.value} value={option.value}>
                  {option.label}
                </option>
              ))}
            </Select>
          </div>
          <div className="grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto]">
            <Select
              value={selectedTemplateId}
              onChange={(event) => setSelectedTemplateId(event.target.value)}
            >
              <option value="">选择 PPTX 报告模板</option>
              {pptxTemplates.map((template) => (
                <option key={template.id} value={template.id}>
                  {template.name} - {template.originalFileName}
                </option>
              ))}
            </Select>
            <Button
              disabled={generating || selectedClassId === 'all' || !selectedTemplateId}
              onClick={handleGenerateReports}
            >
              <Wand2 />
              {generating ? '生成中' : '生成当前班级报告'}
            </Button>
          </div>
        </div>

        <ScrollArea className="h-140">
          <div className="grid gap-3 pr-3 md:grid-cols-2 xl:grid-cols-3">
            {filteredReports.map((report) => {
              const ReportIcon = getReportIcon(report.format)

              return (
                <Card key={report.id} className="shadow-none">
                  <CardHeader className="space-y-4">
                    <div className="flex items-start justify-between gap-3">
                      <div className="grid size-11 shrink-0 place-items-center rounded-md bg-muted text-primary">
                        <ReportIcon className="size-5" />
                      </div>
                      <Badge variant="secondary">{getReportFormatLabel(report.format)}</Badge>
                    </div>
                    <div className="min-w-0">
                      <CardTitle className="truncate text-base">{report.title}</CardTitle>
                      <CardDescription className="mt-2 truncate">
                        {report.originalFileName}
                      </CardDescription>
                    </div>
                  </CardHeader>
                  <CardContent className="space-y-4">
                    <div className="grid grid-cols-2 gap-3">
                      <div className="rounded-md bg-muted px-3 py-2">
                        <p className="text-xs text-muted-foreground">班级</p>
                        <p className="mt-1 truncate font-medium">{report.className}</p>
                      </div>
                      <div className="rounded-md bg-muted px-3 py-2">
                        <p className="text-xs text-muted-foreground">学生</p>
                        <p className="mt-1 truncate font-medium">{report.studentName}</p>
                      </div>
                      <div className="col-span-2 rounded-md bg-muted px-3 py-2">
                        <p className="text-xs text-muted-foreground">生成时间</p>
                        <p className="mt-1 truncate text-sm">{formatDateTime(report.createdAt)}</p>
                      </div>
                    </div>

                    <div className="flex justify-end gap-2">
                      <Button
                        size="sm"
                        disabled={openingId === report.id}
                        onClick={() => handleOpenReport(report)}
                      >
                        <ExternalLink />
                        {openingId === report.id ? '打开中' : '打开报告'}
                      </Button>
                      <Button
                        size="sm"
                        variant="destructive"
                        disabled={deletingId === report.id}
                        onClick={() => handleDeleteReport(report)}
                      >
                        <Trash2 />
                        {deletingId === report.id ? '删除中' : '删除'}
                      </Button>
                    </div>
                  </CardContent>
                </Card>
              )
            })}

            {filteredReports.length === 0 && (
              <div className="col-span-full grid min-h-52 place-items-center rounded-md border bg-background p-6 text-center text-sm text-muted-foreground">
                <div className="space-y-3">
                  <div className="mx-auto grid size-12 place-items-center rounded-full bg-muted text-primary">
                    <Files className="size-5" />
                  </div>
                  <div>
                    <p className="font-medium text-foreground">暂无报告</p>
                    <p className="mt-1">选择班级和 PPTX 模板生成报告后，会以卡片形式显示在这里。</p>
                  </div>
                </div>
              </div>
            )}
          </div>
        </ScrollArea>
      </section>

      <DashboardFooter />
    </>
  )
}
