import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useNavigate, useParams, useSearchParams } from "react-router-dom"
import {
  Button,
  Card,
  Col,
  Empty,
  Input,
  Modal,
  Row,
  Space,
  Spin,
  Tabs,
  Typography,
} from "antd"
import {
  ArrowLeftOutlined,
  ReloadOutlined,
} from "@ant-design/icons"
import { toast } from "../utils/toast"
import InfoMonitorTab from "./server-detail/InfoMonitorTab"
import InfoTab from "./server-detail/InfoTab"
import RenewalTab from "./server-detail/RenewalTab"
import DiskTab from "./server-detail/DiskTab"
import BackupTab from "./server-detail/BackupTab"
import FirewallTab from "./server-detail/FirewallTab"
import ReinstallTab from "./server-detail/ReinstallTab"
import UpgradeTab from "./server-detail/UpgradeTab"
import NatForwardingTab from "./server-detail/NatForwardingTab"
import PointsTab from "./server-detail/PointsTab"
import RefundTab from "./server-detail/RefundTab"
import PluginManageTab from "./server-detail/PluginManageTab"
import { formatDate, inferPowerFromTasks, isPluginServer, isZjmfFinanceServer, PLUGIN_TAB_LABELS, TAB_LABELS, TASK_TERMINAL } from "./server-detail/helpers"
import {
  getServer,
  hardShutdown,
  listTasks,
  powerOn,
  reboot,
  resetPassword,
  renewInstance,
  runPluginAction,
  shutdown,
  updateAutoRenew,
  type ServerDetail as ServerDetailType,
  type UpstreamTask,
} from "../api/servers"

const { Title, Text, Paragraph } = Typography

const TAB_KEYS = new Set([...TAB_LABELS.map((tab) => tab.key), "points"])

type PowerActionSupport = {
  on: boolean
  reboot: boolean
  shutdown: boolean
  hardoff: boolean
}

function financePowerActionSupport(server: ServerDetailType | null): PowerActionSupport | null {
  if (!isZjmfFinanceServer(server)) return null
  const upstream = server?.upstream as Record<string, unknown> | undefined
  const moduleButton = upstream?.module_button as { control?: unknown } | undefined
  const control = Array.isArray(moduleButton?.control) ? moduleButton.control : []
  if (control.length === 0) return null

  const funcs = new Set<string>()
  for (const item of control) {
    if (!item || typeof item !== "object") continue
    const func = String((item as { func?: unknown }).func ?? "").trim()
    if (func) funcs.add(func)
  }
  if (funcs.size === 0) return null
  return {
    on: funcs.has("on"),
    reboot: funcs.has("reboot"),
    shutdown: funcs.has("off"),
    hardoff: funcs.has("hard_off") || funcs.has("hardoff"),
  }
}

function hasFinanceNatSupport(server: ServerDetailType | null) {
  if (!isZjmfFinanceServer(server)) return false
  const limit = Number(server?.nat_acl_limit)
  if (Number.isFinite(limit) && limit >= 0) return true
  const upstream = server?.upstream as Record<string, unknown> | undefined
  if (upstream?.support_nat === true) return true
  if (String(upstream?.support_nat ?? "").trim().toLowerCase() === "1") return true
  const raw = JSON.stringify({
    module_client_area: upstream?.module_client_area,
    modules: upstream?.modules,
  }).toLowerCase()
  return raw.includes("nat_acl") || raw.includes("nat")
}

export default function ServerDetail() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()
  const [searchParams, setSearchParams] = useSearchParams()
  const initialTab = searchParams.get("tab")
  const [server, setServer] = useState<ServerDetailType | null>(null)
  const [tasks, setTasks] = useState<UpstreamTask[]>([])
  const [loading, setLoading] = useState(true)
  const [refreshing, setRefreshing] = useState(false)
  const [taskLoading, setTaskLoading] = useState(false)
  const [actionLoading, setActionLoading] = useState<string | null>(null)
  const [activeTab, setActiveTab] = useState(initialTab && TAB_KEYS.has(initialTab) ? initialTab : "info")
  const [contentTab, setContentTab] = useState(activeTab)
  const [tabSwitching, setTabSwitching] = useState(false)
  const [passwordModalOpen, setPasswordModalOpen] = useState(false)
  const [newPassword, setNewPassword] = useState("")
  const [renewCycles, setRenewCycles] = useState(1)
  const [renewLoading, setRenewLoading] = useState(false)
  const [autoRenewLoading, setAutoRenewLoading] = useState(false)
  const pollStoppedRef = useRef(false)
  const tabFrameRef = useRef<number | null>(null)

  const instanceId = Number(id)

  useEffect(() => {
    const timer = window.setTimeout(() => {
      const tab = searchParams.get("tab")
      const nextTab = tab && TAB_KEYS.has(tab) ? tab : "info"
      setActiveTab((current) => (current === nextTab ? current : nextTab))
      setContentTab((current) => (current === nextTab ? current : nextTab))
      setTabSwitching(false)
    }, 0)
    return () => window.clearTimeout(timer)
  }, [searchParams])

  const changeTab = useCallback((key: string) => {
    setActiveTab(key)
    setTabSwitching(true)

    if (tabFrameRef.current !== null) {
      window.cancelAnimationFrame(tabFrameRef.current)
    }

    const nextParams = new URLSearchParams(searchParams)
    if (key === "info") {
      nextParams.delete("tab")
    } else {
      nextParams.set("tab", key)
    }

    tabFrameRef.current = window.requestAnimationFrame(() => {
      setContentTab(key)
      setTabSwitching(false)
      setSearchParams(nextParams)
      tabFrameRef.current = null
    })
  }, [searchParams, setSearchParams])

  const loadServer = useCallback(async (mode: "initial" | "manual" | "silent" = "initial") => {
    if (!instanceId) return
    if (mode === "initial") setLoading(true)
    if (mode === "manual") setRefreshing(true)
    try {
      const res = await getServer(instanceId)
      setServer(res.data.data ?? null)
      if (mode === "manual") toast.success("已刷新实例详情")
    } catch {
      toast.error("实例详情加载失败")
    } finally {
      setLoading(false)
      setRefreshing(false)
    }
  }, [instanceId, setLoading, setRefreshing, setServer])

  const loadTasks = useCallback(async (silent = false) => {
    if (!instanceId) return
    if (!silent) setTaskLoading(true)
    try {
      const res = await listTasks(instanceId)
      setTasks(res.data.data?.list ?? [])
    } catch {
      if (!silent) toast.error("任务记录加载失败")
    } finally {
      setTaskLoading(false)
    }
  }, [instanceId, setTaskLoading, setTasks])

  const pollTasks = useCallback(async () => {
    pollStoppedRef.current = false
    for (let i = 0; i < 30; i += 1) {
      if (pollStoppedRef.current) return
      try {
        const res = await listTasks(instanceId)
        const list = res.data.data?.list ?? []
        setTasks(list)
        const latest = list[0]
        if (latest && TASK_TERMINAL.has(latest.status)) {
          await loadServer("silent")
          return
        }
      } catch {
        // Keep polling during short upstream/network hiccups.
      }
      await new Promise((resolve) => setTimeout(resolve, 1500))
    }
  }, [instanceId, loadServer, setTasks])

  useEffect(() => {
    const timer = window.setTimeout(() => {
      void loadServer()
      void loadTasks(true)
    }, 0)
    return () => {
      window.clearTimeout(timer)
      pollStoppedRef.current = true
      if (tabFrameRef.current !== null) {
        window.cancelAnimationFrame(tabFrameRef.current)
      }
    }
  }, [loadServer, loadTasks])

  useEffect(() => {
    if (!instanceId) return
    const timer = window.setInterval(() => {
      void loadServer("silent")
      void loadTasks(true)
    }, 30000)
    return () => window.clearInterval(timer)
  }, [instanceId, loadServer, loadTasks])

  const taskRunning = tasks.some((task) => !TASK_TERMINAL.has(task.status))
  const actionDisabled = !server?.upstream_id || taskRunning
  const hasPointRewards = (server?.point_rewards?.length ?? 0) > 0
  const isFinanceServer = isZjmfFinanceServer(server)
  const isPlugin = isPluginServer(server)
  const powerActionSupport = financePowerActionSupport(server)
  const financeNatVisible = hasFinanceNatSupport(server)
  const visibleTabs = useMemo(() => {
    if (isPlugin) {
      return hasPointRewards
        ? [...PLUGIN_TAB_LABELS, { key: "points", label: "积分管理" }]
        : PLUGIN_TAB_LABELS
    }
    const baseTabs = isFinanceServer
      ? TAB_LABELS.filter((tab) => tab.key !== "upgrade" && (tab.key !== "nat" || financeNatVisible))
      : TAB_LABELS
    return hasPointRewards
      ? [...baseTabs, { key: "points", label: "积分管理" }]
      : baseTabs
  }, [financeNatVisible, hasPointRewards, isFinanceServer, isPlugin])
  const visibleTabKeys = useMemo(() => new Set(visibleTabs.map((tab) => tab.key)), [visibleTabs])

  useEffect(() => {
    if (server && !visibleTabKeys.has(activeTab)) {
      changeTab("info")
    }
  }, [activeTab, changeTab, server, visibleTabKeys])

  const runAction = async (key: string, label: string, fn: (id: number) => Promise<unknown>) => {
    if (!server) return
    setActionLoading(key)
    try {
      await fn(server.id)
      toast.success(`${label}指令已下发`)
      void pollTasks()
    } catch {
      toast.error(`${label}失败`)
    } finally {
      setActionLoading(null)
    }
  }

  const runPluginManageAction = async (action: string, label: string) => {
    if (!server) return
    setActionLoading(`plugin:${action}`)
    try {
      const res = await runPluginAction(server.id, action)
      const message = typeof res.data.data?.message === "string" ? res.data.data.message : `${label}执行成功`
      toast.success(message)
      await loadServer("silent")
    } catch (e: unknown) {
      const detail = (e as { response?: { data?: { detail?: string } } })?.response?.data?.detail
      toast.error(detail || `${label}执行失败`)
    } finally {
      setActionLoading(null)
    }
  }

  const submitPasswordReset = async () => {
    if (!server) return
    const password = newPassword.trim()
    if (password.length < 6 || password.length > 64) {
      toast.error("密码长度需要为 6-64 位")
      return
    }
    setActionLoading("password")
    try {
      await resetPassword(server.id, password)
      setPasswordModalOpen(false)
      setNewPassword("")
      toast.success("重置密码指令已下发")
      void pollTasks()
    } catch {
      toast.error("重置密码失败")
    } finally {
      setActionLoading(null)
    }
  }

  const submitRenewal = async () => {
    if (!server) return
    setRenewLoading(true)
    try {
      const res = await renewInstance(server.id, renewCycles)
      const data = res.data.data
      if (!data) throw new Error("续费返回数据异常")
      toast.success(`续费成功，新到期时间 ${formatDate(data.expires_at)}`)
      navigate(`/orders/${data.order_id}`)
    } catch (error: unknown) {
      const detail = (error as { response?: { data?: { detail?: string } } })?.response?.data?.detail
      toast.error(detail || "续费失败")
    } finally {
      setRenewLoading(false)
    }
  }

  const submitAutoRenewChange = async (enabled: boolean) => {
    if (!server) return
    setAutoRenewLoading(true)
    try {
      const res = await updateAutoRenew(server.id, enabled)
      const value = res.data.data?.auto_renew ?? (enabled ? 1 : 0)
      setServer({ ...server, auto_renew: value })
      toast.success(enabled ? "自动续费已开启" : "自动续费已关闭")
    } catch (error: unknown) {
      const detail = (error as { response?: { data?: { detail?: string } } })?.response?.data?.detail
      toast.error(detail || "自动续费设置失败")
    } finally {
      setAutoRenewLoading(false)
    }
  }

  if (!instanceId) return null

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

  if (!server) {
    return (
      <Card variant="outlined">
        <Empty description="实例不存在或无权访问">
          <Button onClick={() => navigate("/control/server")}>返回服务器列表</Button>
        </Empty>
      </Card>
    )
  }

  const effectivePower = server.upstream_power ?? inferPowerFromTasks(tasks)

  const activeTabContent = tabSwitching
    ? <TabContentLoading />
    : contentTab === "info"
      ? isPlugin
        ? (
          <PluginManageTab
            server={server}
            actionLoading={actionLoading}
            onActionLoading={setActionLoading}
            onServerRefresh={() => loadServer("silent")}
          />
        )
        : (
        <InfoTab
          server={server}
          tasks={tasks}
          taskLoading={taskLoading}
          actionLoading={actionLoading}
          actionDisabled={actionDisabled}
          powerActionSupport={powerActionSupport}
          effectivePower={effectivePower}
          onPowerOn={() => runAction("on", "开机", powerOn)}
          onReboot={() => runAction("reboot", "重启", reboot)}
          onShutdown={() => runAction("shutdown", "关机", shutdown)}
          onHardShutdown={() => runAction("hardoff", "强制关机", hardShutdown)}
          onPasswordModalOpen={() => setPasswordModalOpen(true)}
          onPluginAction={(action, label) => void runPluginManageAction(action, label)}
          onRefreshTasks={() => loadTasks()}
          onShowMonitor={() => changeTab("monitor")}
        />
      )
      : contentTab === "monitor"
        ? <InfoMonitorTab server={server} />
        : contentTab === "nat"
          ? <NatForwardingTab server={server} />
        : contentTab === "disk"
          ? (
            <DiskTab
              server={server}
              onRefresh={() => loadServer("silent")}
              onTaskSubmitted={() => pollTasks()}
            />
          )
        : contentTab === "backup"
          ? <BackupTab server={server} onTaskSubmitted={() => pollTasks()} />
        : contentTab === "firewall"
          ? <FirewallTab server={server} onRefresh={() => loadServer("silent")} />
        : contentTab === "reinstall"
          ? (
            <ReinstallTab
              server={server}
              disabled={actionDisabled}
              onRefresh={() => loadServer("silent")}
              onTaskSubmitted={() => pollTasks()}
            />
          )
        : contentTab === "upgrade"
          ? <UpgradeTab server={server} onUpgradeSuccess={() => loadServer("silent")} />
        : contentTab === "refund"
          ? (
            <RefundTab
              server={server}
              onRefresh={() => loadServer("silent")}
              onTaskSubmitted={() => pollTasks()}
            />
          )
        : contentTab === "points" && hasPointRewards
          ? <PointsTab server={server} onClaimed={() => {
              void loadServer("silent")
              changeTab("info")
            }} />
        : contentTab === "renewal"
          ? (
            <RenewalTab
              server={server}
              cycles={renewCycles}
              loading={renewLoading}
              autoRenewLoading={autoRenewLoading}
              maxCycles={isFinanceServer ? 1 : 36}
              onCyclesChange={(cycles) => setRenewCycles(isFinanceServer ? 1 : cycles)}
              onSubmit={submitRenewal}
              onAutoRenewChange={submitAutoRenewChange}
            />
          )
          : <Empty description="该功能暂未开放" />

  return (
    <Space direction="vertical" size={16} style={{ width: "100%" }}>
      <Row gutter={[16, 16]} align="bottom" justify="space-between">
        <Col>
          <Button type="link" icon={<ArrowLeftOutlined />} style={{ paddingLeft: 0 }} onClick={() => navigate("/control/server")}>
            返回服务器列表
          </Button>
          <Title level={3} style={{ margin: 0 }}>{server.hostname || `实例 #${server.id}`}</Title>
          <Paragraph type="secondary" style={{ marginTop: 8, marginBottom: 0 }}>
            {server.product_name} / {server.product_group_name || "默认线路"}
          </Paragraph>
        </Col>
        <Col>
          <Button icon={<ReloadOutlined />} loading={refreshing} onClick={() => loadServer("manual")}>
            刷新
          </Button>
        </Col>
      </Row>

      <Card variant="outlined" styles={{ body: { padding: 0 } }}>
        <Tabs
          activeKey={activeTab}
          onChange={changeTab}
          tabBarStyle={{ margin: 0, padding: "0 20px", height: 52 }}
          items={visibleTabs.map((tab) => ({ key: tab.key, label: tab.label }))}
        />
        <div style={{ padding: 20, minHeight: tabSwitching || contentTab === "info" || contentTab === "monitor" ? undefined : 280 }}>
          {activeTabContent}
        </div>
      </Card>

      <Modal
        title="重置 Root 密码"
        open={passwordModalOpen}
        onCancel={() => setPasswordModalOpen(false)}
        onOk={submitPasswordReset}
        confirmLoading={actionLoading === "password"}
        okText="确认重置"
        cancelText="取消"
      >
        <Space direction="vertical" size={12} style={{ width: "100%" }}>
          <Text type="secondary">请输入 6-64 位新密码。指令下发后请等待任务完成。</Text>
          <Input.Password
            value={newPassword}
            onChange={(event) => setNewPassword(event.target.value)}
            placeholder="请输入新密码"
            onPressEnter={submitPasswordReset}
          />
        </Space>
      </Modal>
    </Space>
  )
}

function TabContentLoading() {
  return (
    <div style={{ minHeight: 260, display: "flex", alignItems: "center", justifyContent: "center" }}>
      <Spin size="large" description="正在加载内容" />
    </div>
  )
}
