import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react"
import { Link, useParams } from "react-router-dom"
import {
  ArrowLeftOutlined,
  CheckCircleOutlined,
  CloudServerOutlined,
  MessageOutlined,
  ReloadOutlined,
  SendOutlined,
} from "@ant-design/icons"
import { Button, Card, Col, Form, Input, Popconfirm, Rate, Row, Space, Spin, Tag, Timeline, Typography } from "antd"
import { toast } from "../utils/toast"
import {
  closeTicket,
  getTicket,
  rateTicket,
  reopenTicket,
  replyTicket,
  uploadTicketImage,
  type TicketDetail as TicketDetailData,
} from "../api/tickets"
import RichTextEditor from "../components/RichTextEditor"
import TicketMessageItem from "../components/TicketMessageItem"
import { TICKET_STATUS_META } from "../utils/ticketMeta"
import { isRichTextEmpty, sanitizeRichText } from "../utils/richText"

const { Title, Paragraph, Text } = Typography

function formatDate(value?: string | null) {
  if (!value) return "-"
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return value
  return date.toLocaleString("zh-CN", { hour12: false })
}

function formatMemory(memoryMb: number | null | undefined) {
  if (memoryMb == null) return "-"
  if (memoryMb >= 1024) {
    const gb = memoryMb / 1024
    return `${Number.isInteger(gb) ? gb : gb.toFixed(1)} GB`
  }
  return `${memoryMb} MB`
}

function errorDetail(error: unknown, fallback: string) {
  return (error as { response?: { data?: { detail?: string } } })?.response?.data?.detail || fallback
}

function eventText(eventType: string, fallback?: string | null) {
  const labels: Record<string, string> = {
    created: "创建工单",
    user_replied: "用户回复",
    admin_replied: "客服回复",
    status_changed: "状态更新",
    priority_changed: "优先级更新",
    department_changed: "部门调整",
    closed: "关闭工单",
    reopened: "重新打开",
    rated: "满意度评价",
  }
  return fallback || labels[eventType] || eventType
}

/** Polling interval in ms — increased from 10s to 30s to reduce re-render frequency */
const POLL_INTERVAL = 30000

export default function TicketDetail() {
  const { id } = useParams<{ id: string }>()
  const [form] = Form.useForm<{ content: string }>()
  const [ratingForm] = Form.useForm<{ rating: number; comment?: string }>()
  const [ticket, setTicket] = useState<TicketDetailData | null>(null)
  const [loading, setLoading] = useState(true)
  const [refreshing, setRefreshing] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [changing, setChanging] = useState(false)
  const [ratingSubmitting, setRatingSubmitting] = useState(false)

  const loadTicket = useCallback(async (silent = false) => {
    if (!id) return
    if (silent) setRefreshing(true)
    else setLoading(true)
    try {
      const res = await getTicket(id)
      const data = res.data.data ?? null
      setTicket(data)
    } catch (error) {
      toast.error(errorDetail(error, "工单详情加载失败"))
    } finally {
      setLoading(false)
      setRefreshing(false)
    }
  }, [id])

  useEffect(() => {
    void loadTicket()
  }, [loadTicket])

  useEffect(() => {
    if (!ticket) return
    if (ticket.satisfaction) {
      ratingForm.setFieldsValue({
        rating: ticket.satisfaction.rating,
        comment: ticket.satisfaction.comment || "",
      })
    } else {
      ratingForm.resetFields()
    }
  }, [ratingForm, ticket])

  // Poll but only when the tab is visible — reduces unnecessary network & re-renders
  useEffect(() => {
    let timer: number
    const startPolling = () => {
      timer = window.setInterval(() => {
        void loadTicket(true)
      }, POLL_INTERVAL)
    }
    const handleVisibility = () => {
      window.clearInterval(timer)
      if (document.visibilityState === "visible") {
        // Immediately refresh on tab focus, then resume polling
        void loadTicket(true)
        startPolling()
      }
    }
    startPolling()
    document.addEventListener("visibilitychange", handleVisibility)
    return () => {
      window.clearInterval(timer)
      document.removeEventListener("visibilitychange", handleVisibility)
    }
  }, [loadTicket])

  const statusMeta = ticket ? TICKET_STATUS_META[ticket.status] : TICKET_STATUS_META.open
  const canReply = ticket && !["closed", "resolved"].includes(ticket.status)
  const canRate = ticket && ["closed", "resolved"].includes(ticket.status)

  const instanceTags = useMemo(() => {
    const instance = ticket?.instance
    if (!instance) return []
    return [
      `CPU ${instance.cpu ?? "-"} 核`,
      `内存 ${formatMemory(instance.memory)}`,
      `带宽 ${instance.in_bw ?? "-"} / ${instance.out_bw ?? "-"} Mbps`,
    ]
  }, [ticket?.instance])

  const handleUploadImage = useCallback(async (file: File) => {
    const res = await uploadTicketImage(file)
    if (!res.data.data) throw new Error("图片上传失败")
    return res.data.data
  }, [])

  const handleReply = useCallback(async () => {
    if (!id) return
    const values = await form.validateFields()
    setSubmitting(true)
    try {
      await replyTicket(id, { content: sanitizeRichText(values.content).trim() })
      form.resetFields()
      toast.success("回复已发送")
      await loadTicket(true)
    } catch (error) {
      toast.error(errorDetail(error, "回复发送失败"))
    } finally {
      setSubmitting(false)
    }
  }, [id, form, loadTicket])

  const handleClose = async () => {
    if (!id) return
    setChanging(true)
    try {
      await closeTicket(id)
      toast.success("工单已关闭")
      await loadTicket(true)
    } catch (error) {
      toast.error(errorDetail(error, "关闭工单失败"))
    } finally {
      setChanging(false)
    }
  }

  const handleReopen = async () => {
    if (!id) return
    setChanging(true)
    try {
      await reopenTicket(id)
      toast.success("工单已重新打开")
      await loadTicket(true)
    } catch (error) {
      toast.error(errorDetail(error, "重新打开失败"))
    } finally {
      setChanging(false)
    }
  }

  const handleRate = async () => {
    if (!id) return
    const values = await ratingForm.validateFields()
    setRatingSubmitting(true)
    try {
      await rateTicket(id, {
        rating: values.rating,
        comment: values.comment?.trim() || null,
      })
      toast.success("评价已提交")
      await loadTicket(true)
    } catch (error) {
      toast.error(errorDetail(error, "评价提交失败"))
    } finally {
      setRatingSubmitting(false)
    }
  }

  if (loading) {
    return (
      <div style={{ height: 420, display: "flex", alignItems: "center", justifyContent: "center" }}>
        <Spin size="large" description="正在加载工单详情" />
      </div>
    )
  }

  if (!ticket) {
    return (
      <Card variant="outlined">
        <Space orientation="vertical" size={12}>
          <Text>工单不存在或已无法访问。</Text>
          <Link to="/tickets">
            <Button>返回工单列表</Button>
          </Link>
        </Space>
      </Card>
    )
  }

  return (
    <Space orientation="vertical" size={24} style={{ width: "100%" }}>
      <div>
        <Link to="/tickets">
          <Button type="link" icon={<ArrowLeftOutlined />} style={{ paddingLeft: 0 }}>返回工单列表</Button>
        </Link>
        <Space align="center" wrap>
          <Title level={3} style={{ margin: 0 }}>{ticket.subject}</Title>
          <Tag color={statusMeta.color}>{statusMeta.label}</Tag>
        </Space>
        <Paragraph type="secondary" style={{ marginTop: 8, marginBottom: 0 }}>
          {ticket.ticket_no} · {ticket.department_name || "未分配部门"} · 创建于 {formatDate(ticket.created_at)}
        </Paragraph>
      </div>

      <Row gutter={[16, 16]} align="top">
        <Col xs={24} lg={16}>
          <Card
            variant="outlined"
            title={<Space><MessageOutlined /> 沟通记录</Space>}
            extra={<Button icon={<ReloadOutlined />} loading={refreshing} onClick={() => loadTicket(true)}>刷新</Button>}
          >
            <Space orientation="vertical" size={16} style={{ width: "100%" }}>
              {ticket.messages.map((message) => (
                <TicketMessageItem
                  key={message.id}
                  message={message}
                  mode="user"
                />
              ))}
            </Space>
          </Card>

          <Card variant="outlined" style={{ marginTop: 16 }} title="回复工单">
            {canReply ? (
              <Form form={form} layout="vertical" onFinish={handleReply}>
                <Form.Item
                  name="content"
                  rules={[
                    {
                      validator: async (_, value: string | undefined) => {
                        if (isRichTextEmpty(value)) throw new Error("请输入回复内容")
                        if (sanitizeRichText(value).length > 8000) throw new Error("回复内容过长")
                      },
                    },
                  ]}
                >
                  <RichTextEditor
                    placeholder="补充新的现象、截图说明或处理结果。"
                    uploadImage={handleUploadImage}
                  />
                </Form.Item>
                <Button type="primary" htmlType="submit" icon={<SendOutlined />} loading={submitting}>
                  发送回复
                </Button>
              </Form>
            ) : (
              <Space>
                <Text type="secondary">工单已关闭，如需继续沟通请重新打开。</Text>
                <Button icon={<MessageOutlined />} loading={changing} onClick={handleReopen}>重新打开</Button>
              </Space>
            )}
          </Card>

          {canRate ? (
            <Card variant="outlined" style={{ marginTop: 16 }} title="满意度评价">
              <Form form={ratingForm} layout="vertical" onFinish={handleRate}>
                <Form.Item
                  name="rating"
                  label="评分"
                  rules={[{ required: true, message: "请选择评分" }]}
                >
                  <Rate />
                </Form.Item>
                <Form.Item name="comment" label="反馈">
                  <Input.TextArea rows={3} maxLength={1000} showCount placeholder="可以补充本次服务体验" />
                </Form.Item>
                <Space>
                  <Button type="primary" htmlType="submit" loading={ratingSubmitting}>
                    {ticket.satisfaction ? "更新评价" : "提交评价"}
                  </Button>
                  {ticket.satisfaction?.rated_at ? (
                    <Text type="secondary">已于 {formatDate(ticket.satisfaction.rated_at)} 评价</Text>
                  ) : null}
                </Space>
              </Form>
            </Card>
          ) : null}
        </Col>

        <Col xs={24} lg={8}>
          <Space orientation="vertical" size={16} style={{ width: "100%" }}>
            <Card variant="outlined" title="工单信息">
              <Space orientation="vertical" size={8} style={{ width: "100%" }}>
                <InfoLine label="状态" value={<Tag color={statusMeta.color}>{statusMeta.label}</Tag>} />
                <InfoLine label="优先级" value={ticket.priority} />
                <InfoLine label="消息数" value={`${ticket.message_count} 条`} />
                <InfoLine label="最后更新" value={formatDate(ticket.last_message_at)} />
                {ticket.satisfaction ? (
                  <InfoLine label="满意度" value={<Rate disabled value={ticket.satisfaction.rating} style={{ fontSize: 14 }} />} />
                ) : null}
                {!["closed", "resolved"].includes(ticket.status) ? (
                  <Popconfirm
                    title="关闭工单"
                    description="确认问题已处理完成并关闭工单吗？"
                    okText="关闭"
                    cancelText="取消"
                    onConfirm={handleClose}
                  >
                    <Button icon={<CheckCircleOutlined />} loading={changing}>关闭工单</Button>
                  </Popconfirm>
                ) : (
                  <Button icon={<MessageOutlined />} loading={changing} onClick={handleReopen}>重新打开</Button>
                )}
              </Space>
            </Card>

            <Card variant="outlined" title={<Space><CloudServerOutlined /> 关联实例</Space>}>
              {ticket.instance ? (
                <Space orientation="vertical" size={8}>
                  <Text strong>#{ticket.instance.id} {ticket.instance.hostname || "云服务器"}</Text>
                  <Text type="secondary">{ticket.instance.main_ip || "未返回公网 IP"}</Text>
                  <Space size={[4, 4]} wrap>
                    {instanceTags.map((item) => <Tag key={item}>{item}</Tag>)}
                  </Space>
                </Space>
              ) : (
                <Text type="secondary">未关联实例。</Text>
              )}
            </Card>

            {ticket.events?.length ? (
              <Card variant="outlined" title="处理记录">
                <Timeline
                  items={ticket.events.map((event) => ({
                    key: event.id,
                    children: (
                      <Space orientation="vertical" size={2}>
                        <Text>{eventText(event.event_type, event.message)}</Text>
                        <Text type="secondary" style={{ fontSize: 12 }}>
                          {event.actor_name || (event.actor_type === "admin" ? "客服" : "系统")} · {formatDate(event.created_at)}
                        </Text>
                      </Space>
                    ),
                  }))}
                />
              </Card>
            ) : null}
          </Space>
        </Col>
      </Row>
    </Space>
  )
}

function InfoLine({ label, value }: { label: string; value: ReactNode }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
      <Text type="secondary">{label}</Text>
      <span style={{ textAlign: "right" }}>{value}</span>
    </div>
  )
}
