import { ArrowLeftOutlined, DownloadOutlined } from '@ant-design/icons'
import { Button, Select, Space, Spin, Tabs, Tag, Typography, message } from 'antd'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link, useParams, useSearchParams } from 'react-router-dom'
import { examApi, studentApi, subjectApi, wrongQuestionApi } from '../api/client'
import ScoreForm from '../components/ScoreForm'
import ScoreOverview from '../components/ScoreOverview'
import TrendChart from '../components/TrendChart'
import WrongQuestionList from '../components/WrongQuestionList'
import WrongQuestionUpload, { WrongQuestionFilters } from '../components/WrongQuestionUpload'
import ExamReviewPanel from '../components/ExamReviewPanel'
import CompositionPanel from '../components/CompositionPanel'
import StudentAvatar from '../components/StudentAvatar'
import StudentSettingsPanel from '../components/StudentSettingsPanel'
import { formatStudentSubtitle, SCHOOL_LEVEL_LABELS } from '../constants/school'
import type { Exam, Student, Subject, TrendResponse, WrongQuestion } from '../types'

const TAB_KEYS = ['scores', 'overview', 'trend', 'review', 'composition', 'wrong', 'olympiad', 'settings'] as const
type TabKey = (typeof TAB_KEYS)[number]

export default function StudentDetailPage() {
  const { id } = useParams<{ id: string }>()
  const [searchParams, setSearchParams] = useSearchParams()
  const tabParam = searchParams.get('tab')
  const activeTab: TabKey = TAB_KEYS.includes(tabParam as TabKey) ? (tabParam as TabKey) : 'scores'

  const [student, setStudent] = useState<Student | null>(null)
  const [subjects, setSubjects] = useState<Subject[]>([])
  const [exams, setExams] = useState<Exam[]>([])
  const [trend, setTrend] = useState<TrendResponse | null>(null)
  const [selectedSubject, setSelectedSubject] = useState<number>()
  const [wrongQuestions, setWrongQuestions] = useState<WrongQuestion[]>([])
  const [olympiadQuestions, setOlympiadQuestions] = useState<WrongQuestion[]>([])
  const [wqSubjectFilter, setWqSubjectFilter] = useState<number>()
  const [wqSearch, setWqSearch] = useState('')
  const [olympiadSearch, setOlympiadSearch] = useState('')
  const [selectedWq, setSelectedWq] = useState<string | null>(null)
  const [selectedOlympiad, setSelectedOlympiad] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)

  const mathSubject = useMemo(() => subjects.find((s) => s.name === '数学'), [subjects])
  const subjectNames = Object.fromEntries(subjects.map((s) => [s.id, s.name]))

  const loadExams = useCallback(async () => {
    if (!id) return
    const { data } = await examApi.list(id)
    setExams(data)
  }, [id])

  const loadTrend = useCallback(async () => {
    if (!id || !selectedSubject) return
    const { data } = await examApi.trend(id, selectedSubject)
    setTrend(data)
  }, [id, selectedSubject])

  const loadWrongQuestions = useCallback(async () => {
    if (!id) return
    const { data } = await wrongQuestionApi.list(id, {
      subject_id: wqSubjectFilter,
      q: wqSearch || undefined,
      category: 'regular',
    })
    setWrongQuestions(data)
  }, [id, wqSubjectFilter, wqSearch])

  const loadOlympiadQuestions = useCallback(async () => {
    if (!id) return
    const { data } = await wrongQuestionApi.list(id, {
      subject_id: mathSubject?.id,
      q: olympiadSearch || undefined,
      category: 'olympiad',
    })
    setOlympiadQuestions(data)
  }, [id, mathSubject?.id, olympiadSearch])

  useEffect(() => {
    if (!id) return
    let cancelled = false
    ;(async () => {
      setLoading(true)
      try {
        const [studentRes, subjectRes] = await Promise.all([
          studentApi.get(id),
          subjectApi.list(),
        ])
        if (cancelled) return
        setStudent(studentRes.data)
        setSubjects(subjectRes.data)
        if (subjectRes.data.length) setSelectedSubject(subjectRes.data[0].id)
        const examRes = await examApi.list(id)
        if (!cancelled) setExams(examRes.data)
      } finally {
        if (!cancelled) setLoading(false)
      }
    })()
    return () => {
      cancelled = true
    }
  }, [id])

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

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

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

  const handleTabChange = (key: string) => {
    setSearchParams({ tab: key }, { replace: true })
  }

  const handleExport = async () => {
    if (!id) return
    try {
      const res = await examApi.exportCsv(id)
      const blob = res.data
      if (blob.type?.includes('application/json')) {
        const text = await blob.text()
        try {
          const err = JSON.parse(text) as { detail?: string }
          message.error(err.detail || '导出失败')
        } catch {
          message.error('导出失败')
        }
        return
      }
      const disposition = res.headers['content-disposition'] as string | undefined
      let filename = `${student?.name || 'student'}_scores.csv`
      if (disposition) {
        const utf8Match = disposition.match(/filename\*=UTF-8''([^;]+)/i)
        const plainMatch = disposition.match(/filename="?([^";]+)"?/i)
        if (utf8Match?.[1]) filename = decodeURIComponent(utf8Match[1])
        else if (plainMatch?.[1]) filename = plainMatch[1]
      }
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = filename
      a.click()
      URL.revokeObjectURL(url)
    } catch {
      message.error('导出失败')
    }
  }

  if (loading) {
    return (
      <div style={{ textAlign: 'center', padding: 80 }}>
        <Spin size="large" />
      </div>
    )
  }

  if (!student) return <Typography.Text>学生不存在</Typography.Text>

  const stageLabel = SCHOOL_LEVEL_LABELS[student.school_level]

  return (
    <div className="page-container">
      <Space className="page-header" wrap>
        <Link to="/">
          <Button icon={<ArrowLeftOutlined />}>返回</Button>
        </Link>
        <StudentAvatar student={student} size={40} />
        <Typography.Title level={4} style={{ margin: 0 }}>
          {student.name}
        </Typography.Title>
        <Tag color={student.school_level === 'senior_high' ? 'purple' : 'blue'}>{stageLabel}</Tag>
        <Typography.Text type="secondary">{formatStudentSubtitle(student)}</Typography.Text>
        <Button icon={<DownloadOutlined />} onClick={handleExport}>
          导出 CSV
        </Button>
      </Space>

      <Tabs
        className="student-tabs"
        activeKey={activeTab}
        onChange={handleTabChange}
        destroyInactiveTabPane={false}
        items={[
          {
            key: 'scores',
            label: '成绩录入',
            children: (
              <ScoreForm studentId={id!} subjects={subjects} exams={exams} onRefresh={loadExams} />
            ),
          },
          {
            key: 'overview',
            label: '成绩总览',
            children: <ScoreOverview exams={exams} subjectNames={subjectNames} />,
          },
          {
            key: 'trend',
            label: '分科曲线',
            children: (
              <div>
                <Select
                  style={{ width: '100%', maxWidth: 160, marginBottom: 16 }}
                  value={selectedSubject}
                  onChange={setSelectedSubject}
                  options={subjects.map((s) => ({ value: s.id, label: s.name }))}
                />
                {trend && (
                  <TrendChart
                    points={trend.points}
                    subjectName={trend.subject_name}
                    threshold={trend.threshold}
                  />
                )}
              </div>
            ),
          },
          {
            key: 'review',
            label: '成绩复盘',
            children: <ExamReviewPanel studentId={id!} exams={exams} onRefresh={loadExams} />,
          },
          {
            key: 'composition',
            label: '作文区',
            children: <CompositionPanel studentId={id!} student={student} />,
          },
          {
            key: 'wrong',
            label: '错题库',
            children: (
              <div>
                <Typography.Paragraph type="secondary" style={{ marginBottom: 12 }}>
                  上传后自动标注错误位置（红框），并生成解题思路，按{stageLabel}课内标准解题
                </Typography.Paragraph>
                <WrongQuestionUpload
                  studentId={id!}
                  subjects={subjects}
                  category="regular"
                  onUploaded={loadWrongQuestions}
                />
                <WrongQuestionFilters
                  subjectId={wqSubjectFilter}
                  onSubjectChange={setWqSubjectFilter}
                  search={wqSearch}
                  onSearchChange={setWqSearch}
                  onRefresh={loadWrongQuestions}
                  subjects={subjects}
                />
                <WrongQuestionList
                  items={wrongQuestions}
                  selectedId={selectedWq}
                  onSelect={setSelectedWq}
                  onRefresh={loadWrongQuestions}
                  emptyText="暂无错题"
                />
              </div>
            ),
          },
          {
            key: 'olympiad',
            label: '奥数区',
            children: (
              <div>
                <Typography.Paragraph type="secondary" style={{ marginBottom: 12 }}>
                  {stageLabel}数学奥数，严格限制在{stageLabel}奥数培优范围内，禁止超纲
                </Typography.Paragraph>
                <WrongQuestionUpload
                  studentId={id!}
                  subjects={subjects}
                  category="olympiad"
                  onUploaded={loadOlympiadQuestions}
                />
                <WrongQuestionFilters
                  search={olympiadSearch}
                  onSearchChange={setOlympiadSearch}
                  onRefresh={loadOlympiadQuestions}
                  subjects={subjects}
                  hideSubjectFilter
                />
                <WrongQuestionList
                  items={olympiadQuestions}
                  selectedId={selectedOlympiad}
                  onSelect={setSelectedOlympiad}
                  onRefresh={loadOlympiadQuestions}
                  emptyText="暂无奥数题"
                />
              </div>
            ),
          },
          {
            key: 'settings',
            label: '设置',
            children: (
              <StudentSettingsPanel
                student={student}
                onUpdated={(updated) => setStudent(updated)}
              />
            ),
          },
        ]}
      />
    </div>
  )
}
