import { useCallback, useEffect, useMemo, useState } from "react"
import { Link, useNavigate, useSearchParams } from "react-router-dom"
import {
  ArrowLeftOutlined,
  CloudServerOutlined,
  MessageOutlined,
  SendOutlined,
} from "@ant-design/icons"
import { Button, Card, Col, Form, Input, Row, Select, Space, Spin, Tag, Typography } from "antd"
import { toast } from "../utils/toast"
import type { ServerItem } from "../api/servers"
import {
  createTicket,
  listTicketInstances,
  listTicketDepartments,
  uploadTicketImage,
  type TicketCreatePayload,
  type TicketDepartment,
  type TicketPriority,
} from "../api/tickets"
import RichTextEditor from "../components/RichTextEditor"
import { isRichTextEmpty, sanitizeRichText } from "../utils/richText"

const { Title, Paragraph, Text } = Typography

const INSTANCE_STATUS_LABEL: Record<string, { label: string; color: string }> = {
  active: { label: "运行中", color: "success" },
  suspended: { label: "已暂停", color: "warning" },
}

const AGENT_APPLICATION_META: Record<string, { name: string; code: string }> = {
  yunqi: { name: "云启伙伴", code: "agent_yunqi" },
  yunxiang: { name: "云享伙伴", code: "agent_yunxiang" },
  yunce: { name: "云策伙伴", code: "agent_yunce" },
  yunling: { name: "云领伙伴", code: "agent_yunling" },
  yunzun: { name: "云尊伙伴", code: "agent_yunzun" },
  yunguan: { name: "云冠伙伴", code: "agent_yunguan" },
}

const AGENT_APPLICATION_CODE_MAP = Object.values(AGENT_APPLICATION_META).reduce<Record<string, { name: string; code: string }>>(
  (map, item) => ({ ...map, [item.code]: item }),
  {},
)

interface TicketFormValues {
  department_id: number
  priority: TicketPriority
  instance_id?: number
  subject: string
  content: string
}

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

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

function instanceDisplayName(server: ServerItem) {
  return server.hostname?.trim() || server.product_name || `实例 #${server.id}`
}

function instanceSearchText(server: ServerItem) {
  return [
    server.id,
    server.hostname,
    server.product_name,
    server.product_group_name,
    server.main_ip,
    server.status,
  ].filter(Boolean).join(" ")
}

function instanceSelectLabel(server: ServerItem) {
  const status = INSTANCE_STATUS_LABEL[server.status] ?? { label: server.status || "未知", color: "default" }
  return (
    <Space direction="vertical" size={2} style={{ width: "100%" }}>
      <Space size={6} wrap>
        <Text strong>#{server.id} {instanceDisplayName(server)}</Text>
        <Tag color={status.color}>{status.label}</Tag>
      </Space>
      <Text type="secondary" style={{ fontSize: 12 }}>
        {server.product_name}{server.product_group_name ? ` · ${server.product_group_name}` : ""} · {server.main_ip || "无公网 IP"}
      </Text>
      <Text type="secondary" style={{ fontSize: 12 }}>
        CPU {server.cpu ?? "-"} 核 · 内存 {formatMemory(server.memory)} · 带宽 {server.in_bw ?? "-"} / {server.out_bw ?? "-"} Mbps
      </Text>
    </Space>
  )
}

function findDepartmentByCodeOrName(departments: TicketDepartment[], code: string) {
  const normalizedCode = code.trim().toLowerCase()
  const byCode = departments.find((item) => item.code?.trim().toLowerCase() === normalizedCode)
  if (byCode) return byCode

  if (normalizedCode === "finance" || normalizedCode === "billing") {
    return departments.find((item) => item.name.includes("财务") || item.name.includes("账单"))
  }
  return undefined
}

function resolveRequestedDepartment(departments: TicketDepartment[], searchParams: URLSearchParams) {
  const departmentId = parseNumberParam(searchParams.get("department_id"))
  if (departmentId != null) {
    return departments.find((item) => item.id === departmentId)
  }
  const tier = searchParams.get("tier") || searchParams.get("agent_tier")
  const code = searchParams.get("department_code")
    || searchParams.get("department")
    || (tier ? AGENT_APPLICATION_META[tier]?.code : null)
  if (!code) return undefined
  return findDepartmentByCodeOrName(departments, code)
}

function buildPrefill(searchParams: URLSearchParams, department?: TicketDepartment) {
  const subject = searchParams.get("subject")
  const content = searchParams.get("content")
  const template = searchParams.get("template")
  const tier = searchParams.get("tier") || searchParams.get("agent_tier")
  const meta = (tier && AGENT_APPLICATION_META[tier])
    || (department?.code ? AGENT_APPLICATION_CODE_MAP[department.code] : undefined)

  if (subject || content) {
    return {
      subject: subject || undefined,
      content: content ? toRichText(content) : undefined,
    }
  }
  if (template === "agent_application" && meta) {
    return {
      subject: `${meta.name}申请`,
      content: [
        `<p>申请档位：${meta.name}</p>`,
        "<p>申请理由：</p>",
        "<p><br></p>",
        "<p>预计推广场景：</p>",
        "<p><br></p>",
        "<p>希望绑定或服务的客户类型：</p>",
        "<p><br></p>",
      ].join(""),
    }
  }
  return {}
}

function parseNumberParam(value: string | null) {
  if (!value) return undefined
  const parsed = Number(value)
  return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined
}

function parsePriorityParam(value: string | null): TicketPriority {
  return value === "low" || value === "high" || value === "urgent" ? value : "normal"
}

function toRichText(value: string) {
  if (/<[a-z][\s\S]*>/i.test(value)) return value
  return `<p>${escapeHtml(value).replace(/\n/g, "<br />")}</p>`
}

function escapeHtml(value: string) {
  return value
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;")
}

export default function TicketCreate() {
  const navigate = useNavigate()
  const [searchParams] = useSearchParams()
  const [form] = Form.useForm<TicketFormValues>()
  const [departments, setDepartments] = useState<TicketDepartment[]>([])
  const [servers, setServers] = useState<ServerItem[]>([])
  const [loading, setLoading] = useState(true)
  const [submitting, setSubmitting] = useState(false)
  const selectedDepartmentId = Form.useWatch("department_id", form)
  const selectedInstanceId = Form.useWatch("instance_id", form)

  useEffect(() => {
    void (async () => {
      setLoading(true)
      try {
        const [departmentRes, serverRes] = await Promise.all([listTicketDepartments(), listTicketInstances()])
        const list = departmentRes.data.data ?? []
        const ticketInstances = serverRes.data.data ?? []
        setDepartments(list)
        setServers(ticketInstances)
        const requestedDepartment = resolveRequestedDepartment(list, searchParams)
        const requestedInstanceId = parseNumberParam(searchParams.get("instance_id"))
        const nextInstanceId = requestedInstanceId && ticketInstances.some((item) => item.id === requestedInstanceId)
          ? requestedInstanceId
          : undefined
        const priority = parsePriorityParam(searchParams.get("priority"))
        const prefill = buildPrefill(searchParams, requestedDepartment)
        if ((searchParams.get("department_code") || searchParams.get("department_id")) && !requestedDepartment) {
          toast.info("当前账号暂不可选择该工单部门")
        }
        if (requestedInstanceId && !nextInstanceId) {
          toast.info("该实例当前不可关联工单")
        }
        form.setFieldsValue({
          priority,
          department_id: requestedDepartment?.id ?? list[0]?.id,
          instance_id: nextInstanceId,
          ...prefill,
        })
      } catch (error) {
        toast.error(errorDetail(error, "工单创建数据加载失败"))
      } finally {
        setLoading(false)
      }
    })()
  }, [form, searchParams])

  const selectedDepartment = useMemo(
    () => departments.find((item) => item.id === selectedDepartmentId),
    [departments, selectedDepartmentId],
  )
  const selectedInstance = useMemo(
    () => servers.find((item) => item.id === selectedInstanceId),
    [servers, selectedInstanceId],
  )

  const handleSubmit = useCallback(async () => {
    const values = await form.validateFields()
    const payload: TicketCreatePayload = {
      department_id: values.department_id,
      priority: values.priority,
      instance_id: values.instance_id ?? null,
      subject: values.subject.trim(),
      content: sanitizeRichText(values.content).trim(),
    }
    setSubmitting(true)
    try {
      const res = await createTicket(payload)
      const ticket = res.data.data
      toast.success("工单已创建")
      navigate(ticket ? `/tickets/${ticket.id}` : "/tickets")
    } catch (error) {
      toast.error(errorDetail(error, "工单创建失败"))
    } finally {
      setSubmitting(false)
    }
  }, [form, navigate])

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

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

  return (
    <Space orientation="vertical" size={24} style={{ width: "100%" }}>
      <div>
        <Link to="/tickets">
          <Button type="link" icon={<ArrowLeftOutlined />} style={{ paddingLeft: 0 }}>返回工单列表</Button>
        </Link>
        <Title level={3} style={{ margin: 0 }}>创建工单</Title>
        <Paragraph type="secondary" style={{ marginTop: 8, marginBottom: 0 }}>
          选择问题类型并补充关联实例、现象和期望结果，方便支持团队快速定位。
        </Paragraph>
      </div>

      <Row gutter={[16, 16]} align="stretch">
        <Col xs={24} lg={16}>
          <Card variant="outlined" title={<Space><MessageOutlined /> 工单内容</Space>}>
            <Form<TicketFormValues>
              form={form}
              layout="vertical"
              initialValues={{ priority: "normal" }}
              onFinish={handleSubmit}
            >
              <Row gutter={12}>
                <Col xs={24} md={12}>
                  <Form.Item name="department_id" label="工单部门" rules={[{ required: true, message: "请选择工单部门" }]}>
                    <Select
                      placeholder="请选择部门"
                      options={departments.map((item) => ({
                        value: item.id,
                        label: item.name,
                      }))}
                    />
                  </Form.Item>
                </Col>
                <Col xs={24} md={12}>
                  <Form.Item name="priority" label="优先级" rules={[{ required: true, message: "请选择优先级" }]}>
                    <Select
                      options={[
                        { value: "low", label: "低" },
                        { value: "normal", label: "普通" },
                        { value: "high", label: "高" },
                        { value: "urgent", label: "紧急" },
                      ]}
                    />
                  </Form.Item>
                </Col>
              </Row>

              <Form.Item name="instance_id" label="关联实例">
                <Select
                  allowClear
                  placeholder="不关联实例"
                  showSearch
                  optionLabelProp="labelText"
                  filterOption={(input, option) => String(option?.searchText ?? "").toLowerCase().includes(input.toLowerCase())}
                  options={servers.map((server) => ({
                    value: server.id,
                    label: instanceSelectLabel(server),
                    labelText: `#${server.id} ${instanceDisplayName(server)}`,
                    searchText: instanceSearchText(server),
                  }))}
                />
              </Form.Item>

              <Form.Item
                name="subject"
                label="标题"
                rules={[
                  { required: true, message: "请输入工单标题" },
                  { min: 2, message: "标题至少 2 个字符" },
                  { max: 160, message: "标题不能超过 160 个字符" },
                ]}
              >
                <Input placeholder="例如：实例无法通过 SSH 连接" />
              </Form.Item>

              <Form.Item
                name="content"
                label="问题描述"
                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>

              <Space>
                <Button type="primary" htmlType="submit" icon={<SendOutlined />} loading={submitting}>
                  提交工单
                </Button>
                <Link to="/tickets">
                  <Button>取消</Button>
                </Link>
              </Space>
            </Form>
          </Card>
        </Col>

        <Col xs={24} lg={8}>
          <Space orientation="vertical" size={16} style={{ width: "100%" }}>
            <Card variant="outlined" title="部门说明">
              {selectedDepartment ? (
                <Space orientation="vertical" size={8}>
                  <Text strong>{selectedDepartment.name}</Text>
                  <Text type="secondary">{selectedDepartment.description || "暂无说明"}</Text>
                  {selectedDepartment.auto_reply_enabled && <Tag color="blue">提交后自动回复</Tag>}
                </Space>
              ) : (
                <Text type="secondary">请选择工单部门。</Text>
              )}
            </Card>

            <Card variant="outlined" title={<Space><CloudServerOutlined /> 关联实例</Space>}>
              {selectedInstance ? (
                <Space orientation="vertical" size={6}>
                  <Text strong>#{selectedInstance.id} {selectedInstance.hostname || selectedInstance.product_name}</Text>
                  <Text type="secondary">{selectedInstance.main_ip || "未返回公网 IP"}</Text>
                  <Space size={[4, 4]} wrap>
                    <Tag>CPU {selectedInstance.cpu ?? "-"} 核</Tag>
                    <Tag>内存 {formatMemory(selectedInstance.memory)}</Tag>
                    <Tag>带宽 {selectedInstance.in_bw ?? "-"} / {selectedInstance.out_bw ?? "-"} Mbps</Tag>
                  </Space>
                </Space>
              ) : (
                <Text type="secondary">如果问题与实例相关，建议关联对应服务器。</Text>
              )}
            </Card>
          </Space>
        </Col>
      </Row>
    </Space>
  )
}
