import { useCallback, useEffect, useMemo, useState } from "react"
import { Alert, Button, Col, Descriptions, Empty, Modal, Radio, Row, Space, Spin, Tag, Typography } from "antd"
import { ArrowRight, CheckCircle, XCircle } from "lucide-react"
import {
  executeUpgrade,
  getUpgradeProducts,
  getUpgradeQuote,
  type ServerDetail,
  type UpgradeProduct,
  type UpgradeQuoteResult,
} from "../../api/servers"
import { toast } from "../../utils/toast"
import { formatCycle, formatMemory, formatMoney } from "./helpers"

const { Text } = Typography

interface UpgradeTabProps {
  server: ServerDetail
  onUpgradeSuccess: () => void
}

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

function signedMoney(cents: number) {
  if (cents > 0) return `+${formatMoney(cents)}`
  if (cents < 0) return `-${formatMoney(Math.abs(cents))}`
  return formatMoney(0)
}

function bandwidthText(inBw?: number | null, outBw?: number | null) {
  if (inBw == null && outBw == null) return "-"
  if (inBw != null && outBw != null && inBw === outBw) return `${inBw} Mbps`
  return `${inBw ?? "-"} / ${outBw ?? "-"} Mbps`
}

function ProductSpecs({ product }: { product: Pick<UpgradeProduct, "cpu" | "memory" | "in_bw" | "out_bw"> }) {
  return (
    <Space size={16} wrap>
      <Text type="secondary">CPU：{product.cpu ?? "-"} 核</Text>
      <Text type="secondary">内存：{product.memory ? formatMemory(product.memory) : "-"}</Text>
      <Text type="secondary">带宽：{bandwidthText(product.in_bw, product.out_bw)}</Text>
    </Space>
  )
}

export default function UpgradeTab({ server, onUpgradeSuccess }: UpgradeTabProps) {
  const [products, setProducts] = useState<UpgradeProduct[]>([])
  const [selectedProductId, setSelectedProductId] = useState<number | null>(null)
  const [quote, setQuote] = useState<UpgradeQuoteResult | null>(null)
  const [loadingProducts, setLoadingProducts] = useState(false)
  const [loadingQuote, setLoadingQuote] = useState(false)
  const [upgrading, setUpgrading] = useState(false)
  const [modalOpen, setModalOpen] = useState(false)

  const canSwitchPackage = server.status === "active" || server.status === "suspended"
  const selectedProduct = useMemo(
    () => products.find((product) => product.id === selectedProductId) ?? null,
    [products, selectedProductId],
  )

  const loadProducts = useCallback(async () => {
    if (!canSwitchPackage) return
    setLoadingProducts(true)
    try {
      const res = await getUpgradeProducts(server.id)
      const list = res.data.data ?? []
      setProducts(list)
      setSelectedProductId((current) => {
        if (current && list.some((product) => product.id === current)) return current
        return list[0]?.id ?? null
      })
    } catch (error) {
      toast.error(errorDetail(error, "套餐列表加载失败"))
      setProducts([])
      setSelectedProductId(null)
    } finally {
      setLoadingProducts(false)
    }
  }, [canSwitchPackage, server.id])

  const loadQuote = useCallback(async (targetProductId: number) => {
    setLoadingQuote(true)
    try {
      const res = await getUpgradeQuote(server.id, { target_product_id: targetProductId })
      setQuote(res.data.data ?? null)
    } catch (error) {
      toast.error(errorDetail(error, "套餐报价失败"))
      setQuote(null)
    } finally {
      setLoadingQuote(false)
    }
  }, [server.id])

  useEffect(() => {
    const timer = window.setTimeout(() => {
      if (!canSwitchPackage) {
        setProducts([])
        setSelectedProductId(null)
        setQuote(null)
        return
      }
      void loadProducts()
    }, 0)
    return () => window.clearTimeout(timer)
  }, [canSwitchPackage, loadProducts])

  useEffect(() => {
    const timer = window.setTimeout(() => {
      if (!selectedProductId) {
        setQuote(null)
        return
      }
      void loadQuote(selectedProductId)
    }, 0)
    return () => window.clearTimeout(timer)
  }, [loadQuote, selectedProductId])

  const renderConfigComparison = (
    label: string,
    currentValue: number | null | undefined,
    targetValue: number | null | undefined,
    unit: string,
    formatter?: (value: number) => string,
  ) => {
    if (currentValue == null && targetValue == null) return null
    const current = currentValue ?? 0
    const target = targetValue ?? 0
    const isUpgrade = target > current
    const isDowngrade = target < current
    const display = formatter ?? ((value: number) => `${value}${unit}`)

    return (
      <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
        <Text>{label}：</Text>
        <Text>{currentValue == null ? "-" : display(currentValue)}</Text>
        <ArrowRight size={15} color="#94a3b8" />
        <Text strong style={{ color: isUpgrade ? "#16a34a" : isDowngrade ? "#dc2626" : undefined }}>
          {targetValue == null ? "-" : display(targetValue)}
        </Text>
        {isUpgrade ? <CheckCircle size={15} color="#16a34a" /> : null}
        {isDowngrade ? <XCircle size={15} color="#dc2626" /> : null}
        {!isUpgrade && !isDowngrade ? <Text type="secondary">不变</Text> : null}
      </div>
    )
  }

  const handleSwitchPackage = async () => {
    if (!selectedProductId || !quote) return
    setUpgrading(true)
    try {
      const res = await executeUpgrade(server.id, { target_product_id: selectedProductId })
      const result = res.data.data
      toast.success(
        result?.is_downgrade
          ? "套餐降配已完成，下次续费金额已更新"
          : `套餐升级已完成，已扣费 ${formatMoney(result?.charged ?? 0)}`,
      )
      setModalOpen(false)
      onUpgradeSuccess()
    } catch (error) {
      toast.error(errorDetail(error, "套餐切换失败"))
      throw error
    } finally {
      setUpgrading(false)
    }
  }

  if (!canSwitchPackage) {
    return (
      <Alert
        type="warning"
        showIcon
        message="当前实例状态不支持套餐切换"
        description="只有运行中或已暂停的实例可以切换套餐。"
      />
    )
  }

  return (
    <>
      <Space direction="vertical" size={16} style={{ width: "100%" }}>
        <Alert
          type="info"
          showIcon
          message="套餐切换说明"
          description="可在同一产品组内切换套餐。升配按当前到期前剩余时间补差价；降配不退差价，但会更新下次续费金额。"
        />

        <Row gutter={[16, 16]}>
          <Col xs={24} lg={15}>
            <Space direction="vertical" size={14} style={{ width: "100%" }}>
              <div style={{ border: "1px solid #f0f0f0", borderRadius: 8, padding: 16 }}>
                <Text strong style={{ display: "block", marginBottom: 10 }}>当前套餐</Text>
                <Descriptions column={1} size="small">
                  <Descriptions.Item label="套餐">{server.product_name}</Descriptions.Item>
                  <Descriptions.Item label="CPU">{server.cpu ?? "-"} 核</Descriptions.Item>
                  <Descriptions.Item label="内存">{server.memory ? formatMemory(server.memory) : "-"}</Descriptions.Item>
                  <Descriptions.Item label="带宽">{bandwidthText(server.in_bw, server.out_bw)}</Descriptions.Item>
                  <Descriptions.Item label="当前周期">{formatCycle(server.cycle)}</Descriptions.Item>
                  <Descriptions.Item label="当前续费">{formatMoney(server.next_renew_amount)}</Descriptions.Item>
                </Descriptions>
              </div>

              <div style={{ border: "1px solid #f0f0f0", borderRadius: 8, padding: 16 }}>
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, marginBottom: 12 }}>
                  <Text strong>目标套餐</Text>
                  {loadingProducts ? <Spin size="small" /> : null}
                </div>

                {loadingProducts ? (
                  <div style={{ padding: "32px 0", textAlign: "center" }}>
                    <Spin tip="正在加载可切换套餐..." />
                  </div>
                ) : products.length === 0 ? (
                  <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="当前产品组没有可切换套餐" />
                ) : (
                  <Radio.Group
                    value={selectedProductId}
                    onChange={(event) => setSelectedProductId(event.target.value)}
                    style={{ width: "100%" }}
                  >
                    <Space direction="vertical" size={10} style={{ width: "100%" }}>
                      {products.map((product) => {
                        const active = product.id === selectedProductId
                        return (
                          <label
                            key={product.id}
                            style={{
                              display: "block",
                              border: `1px solid ${active ? "#91caff" : "#f0f0f0"}`,
                              borderRadius: 8,
                              padding: 12,
                              background: active ? "#e6f4ff" : "#fff",
                              cursor: "pointer",
                              transition: "all .15s ease",
                            }}
                          >
                            <Radio value={product.id} style={{ width: "100%" }}>
                              <Space direction="vertical" size={6} style={{ width: "100%", marginLeft: 4 }}>
                                <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
                                  <Text strong>{product.name}</Text>
                                  <Tag color={active ? "blue" : "default"}>
                                    {formatMoney(product.cycle_price)} / {formatCycle(server.cycle)}
                                  </Tag>
                                </div>
                                {product.description ? <Text type="secondary">{product.description}</Text> : null}
                                <ProductSpecs product={product} />
                              </Space>
                            </Radio>
                          </label>
                        )
                      })}
                    </Space>
                  </Radio.Group>
                )}
              </div>
            </Space>
          </Col>

          <Col xs={24} lg={9}>
            <div style={{ border: "1px solid #f0f0f0", borderRadius: 8, padding: 16 }}>
              <Text strong style={{ display: "block", marginBottom: 12 }}>费用预览</Text>

              {!selectedProductId ? <Text type="secondary">请选择目标套餐</Text> : null}
              {loadingQuote ? (
                <div style={{ padding: "24px 0", textAlign: "center" }}>
                  <Spin tip="正在计算费用..." />
                </div>
              ) : null}

              {quote && !loadingQuote ? (
                <Space direction="vertical" size={16} style={{ width: "100%" }}>
                  {quote.is_downgrade ? (
                    <Alert type="warning" showIcon message="降配不退差价" description="降配会立即修改云服务器配置，本次不退款。" />
                  ) : null}

                  <Space direction="vertical" size={8} style={{ width: "100%" }}>
                    {renderConfigComparison("CPU", quote.current_product.cpu, quote.target_product.cpu, " 核")}
                    {renderConfigComparison("内存", quote.current_product.memory, quote.target_product.memory, "", formatMemory)}
                    {renderConfigComparison("进带宽", quote.current_product.in_bw, quote.target_product.in_bw, " Mbps")}
                    {renderConfigComparison("出带宽", quote.current_product.out_bw, quote.target_product.out_bw, " Mbps")}
                  </Space>

                  <Descriptions column={1} size="small">
                    <Descriptions.Item label="周期价格">
                      {formatMoney(quote.current_product.cycle_price)} → <Text strong>{formatMoney(quote.target_product.cycle_price)}</Text>
                    </Descriptions.Item>
                    <Descriptions.Item label="周期差价">
                      <Text style={{ color: quote.price_diff_cents > 0 ? "#16a34a" : quote.price_diff_cents < 0 ? "#dc2626" : undefined }}>
                        {signedMoney(quote.price_diff_cents)}
                      </Text>
                    </Descriptions.Item>
                    <Descriptions.Item label="剩余时间">{quote.remaining_days} 天</Descriptions.Item>
                    <Descriptions.Item label="下次续费">
                      {formatMoney(server.next_renew_amount)} → <Text strong>{formatMoney(quote.new_renew_amount)}</Text>
                    </Descriptions.Item>
                  </Descriptions>

                  <div style={{ background: "#f8fafc", borderRadius: 8, padding: 16 }}>
                    <Text type="secondary">本次应付</Text>
                    <div>
                      <Text strong style={{ fontSize: 28, color: quote.current_charge > 0 ? "#1677ff" : "#64748b" }}>
                        {formatMoney(quote.current_charge)}
                      </Text>
                      {quote.is_downgrade ? <Text type="secondary">（降配不扣费）</Text> : null}
                    </div>
                  </div>

                  <Button type="primary" block size="large" onClick={() => setModalOpen(true)}>
                    {quote.is_downgrade ? "确认降配" : "确认切换"}
                  </Button>
                </Space>
              ) : null}
            </div>
          </Col>
        </Row>
      </Space>

      <Modal
        title={quote?.is_downgrade ? "确认降配" : "确认套餐切换"}
        open={modalOpen}
        onCancel={() => setModalOpen(false)}
        onOk={handleSwitchPackage}
        okText="确认"
        cancelText="取消"
        confirmLoading={upgrading}
      >
        {quote && selectedProduct ? (
          <Space direction="vertical" size={14} style={{ width: "100%" }}>
            <Descriptions column={1} size="small" bordered>
              <Descriptions.Item label="当前套餐">{quote.current_product.name}</Descriptions.Item>
              <Descriptions.Item label="目标套餐">{selectedProduct.name}</Descriptions.Item>
              <Descriptions.Item label="本次应付">{formatMoney(quote.current_charge)}</Descriptions.Item>
              <Descriptions.Item label="下次续费">{formatMoney(quote.new_renew_amount)}</Descriptions.Item>
            </Descriptions>
            <Text type="secondary">
              {quote.is_downgrade
                ? "降配不会退还当前周期差价，确认后会立即提交到云服务器。"
                : "确认后会扣除本次应付金额，并提交套餐配置到云服务器。"}
            </Text>
          </Space>
        ) : null}
      </Modal>
    </>
  )
}
