import { useEffect, useMemo, useState } from "react"
import { ExclamationCircleOutlined, ReloadOutlined } from "@ant-design/icons"
import { Alert, Button, Form, Input, Modal, Space, Switch, Typography } from "antd"
import { CheckCircle2 } from "lucide-react"
import {
  reinstallInstance,
  type ReinstallPayload,
  type ServerDetail,
  type ServerOsOption,
} from "../../api/servers"
import { toast } from "../../utils/toast"
import { osLogoOrNull } from "../../utils/osLogo"

const { Text, Title } = Typography
const PAGE_SIZE = 10

interface Props {
  server: ServerDetail
  disabled?: boolean
  onRefresh?: () => void
  onTaskSubmitted?: () => void
}

interface ReinstallFormValues {
  os?: number
  format_data_disk?: boolean
}

interface NormalizedOsOption {
  family: string
  label: string
  value: number
}

const FAMILY_RULES: Array<{ label: string; patterns: RegExp[] }> = [
  { label: "Windows", patterns: [/windows/i, /win\s*(server)?/i] },
  { label: "Ubuntu", patterns: [/ubuntu/i] },
  { label: "CentOS", patterns: [/cent\s*os/i, /centos/i] },
  { label: "Debian", patterns: [/debian/i] },
  { label: "Rocky Linux", patterns: [/rocky/i] },
  { label: "AlmaLinux", patterns: [/alma/i] },
  { label: "Fedora", patterns: [/fedora/i] },
  { label: "Arch Linux", patterns: [/arch/i] },
  { label: "Alpine", patterns: [/alpine/i] },
  { label: "openSUSE", patterns: [/open\s*suse/i, /opensuse/i] },
  { label: "FreeBSD", patterns: [/freebsd/i] },
]

const FAMILY_ORDER = new Map(FAMILY_RULES.map((rule, index) => [rule.label, index]))

function OsIcon({ name, size = 20, active = false }: { name: string; size?: number; active?: boolean }) {
  const src = osLogoOrNull(name)
  if (!src) {
    return (
      <div
        style={{ width: size, height: size, fontSize: size * 0.5 }}
        className={`flex shrink-0 items-center justify-center rounded-full font-bold transition-all ${
          active ? "bg-sky-50 text-[#1677ff] ring-1 ring-sky-100" : "bg-gray-100 text-gray-400"
        }`}
      >
        {name.charAt(0).toUpperCase()}
      </div>
    )
  }
  return (
    <img
      src={src}
      alt={name}
      width={size}
      height={size}
      className={`shrink-0 object-contain transition-all ${active ? "opacity-100 saturate-100" : "opacity-55 grayscale"}`}
    />
  )
}

function normalizeOsValue(value: unknown) {
  if (value === null || value === undefined || value === "") return null
  const raw = String(value).split("|", 1)[0].trim()
  const parsed = Number(raw)
  return Number.isInteger(parsed) && parsed > 0 ? parsed : null
}

function optionLabel(option: ServerOsOption) {
  const raw = option.label ?? option["name"] ?? option.value
  return String(raw ?? option.value)
}

function inferFamily(label: string) {
  const match = FAMILY_RULES.find((rule) => rule.patterns.some((pattern) => pattern.test(label)))
  return match?.label || "其他系统"
}

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

export default function ReinstallTab({ server, disabled = false, onRefresh, onTaskSubmitted }: Props) {
  const [form] = Form.useForm<ReinstallFormValues>()
  const [submitting, setSubmitting] = useState(false)
  const [selectedFamily, setSelectedFamily] = useState<string>()
  const [showAll, setShowAll] = useState(false)
  const selectedOsId = Form.useWatch("os", form)
  const formatDataDisk = Boolean(Form.useWatch("format_data_disk", form))

  const osOptions = useMemo<NormalizedOsOption[]>(() => {
    const seen = new Set<number>()
    return (server.os_options ?? []).flatMap((option) => {
      const value = normalizeOsValue(option.value)
      if (!value || seen.has(value)) return []
      seen.add(value)
      const label = optionLabel(option)
      return [{ family: inferFamily(label), label, value }]
    })
  }, [server.os_options])

  const groupedOptions = useMemo(() => {
    const groups = new Map<string, NormalizedOsOption[]>()
    osOptions.forEach((option) => {
      groups.set(option.family, [...(groups.get(option.family) ?? []), option])
    })
    return Array.from(groups.entries())
      .map(([family, options]) => ({
        family,
        options: options.sort((a, b) => a.label.localeCompare(b.label, "zh-CN")),
      }))
      .sort((a, b) => {
        const aOrder = FAMILY_ORDER.get(a.family) ?? 999
        const bOrder = FAMILY_ORDER.get(b.family) ?? 999
        return aOrder === bOrder ? a.family.localeCompare(b.family, "zh-CN") : aOrder - bOrder
      })
  }, [osOptions])

  const defaultOs = useMemo(() => {
    const current = normalizeOsValue(server.os_image)
    return osOptions.find((option) => option.value === current) ?? osOptions[0]
  }, [osOptions, server.os_image])

  const selectedFamilyOptions = useMemo(() => {
    const family = selectedFamily || groupedOptions[0]?.family
    return groupedOptions.find((group) => group.family === family)?.options ?? []
  }, [groupedOptions, selectedFamily])

  const visibleOptions = showAll ? selectedFamilyOptions : selectedFamilyOptions.slice(0, PAGE_SIZE)
  const selectedOs = osOptions.find((option) => option.value === selectedOsId)
  const actionDisabled = disabled || !server.upstream_id || osOptions.length === 0

  useEffect(() => {
    const timer = window.setTimeout(() => {
      if (!defaultOs) return
      const familyExists = selectedFamily && groupedOptions.some((group) => group.family === selectedFamily)
      const nextFamily = familyExists ? selectedFamily : defaultOs.family
      const familyOptions = groupedOptions.find((group) => group.family === nextFamily)?.options ?? []
      const currentOs = form.getFieldValue("os")
      const nextOs = familyOptions.some((option) => option.value === currentOs)
        ? currentOs
        : familyOptions.find((option) => option.value === defaultOs.value)?.value ?? familyOptions[0]?.value
      setSelectedFamily(nextFamily)
      form.setFieldsValue({ os: nextOs })
    }, 0)
    return () => window.clearTimeout(timer)
  }, [defaultOs, form, groupedOptions, selectedFamily])

  const selectFamily = (family: string) => {
    const firstOption = groupedOptions.find((group) => group.family === family)?.options[0]
    setSelectedFamily(family)
    setShowAll(false)
    form.setFieldsValue({ os: firstOption?.value })
  }

  const selectOs = (option: NormalizedOsOption) => {
    form.setFieldsValue({ os: option.value })
  }

  const doReinstall = async (values: ReinstallFormValues) => {
    if (!values.os) {
      toast.error("请选择重装镜像")
      return
    }

    const payload: ReinstallPayload = {
      os: values.os,
      format_data_disk: values.format_data_disk ? 1 : 0,
    }

    setSubmitting(true)
    try {
      await reinstallInstance(server.id, payload)
      toast.success("重装任务已提交")
      onTaskSubmitted?.()
      onRefresh?.()
    } catch (error) {
      toast.error(errorDetail(error, "重装系统失败"))
      throw error
    } finally {
      setSubmitting(false)
    }
  }

  const handleFinish = (values: ReinstallFormValues) => {
    const targetOs = osOptions.find((option) => option.value === values.os)
    Modal.confirm({
      title: "确认重装系统",
      icon: <ExclamationCircleOutlined />,
      content: (
        <Space direction="vertical" size={8}>
          <Text>系统类型：{targetOs?.family || "-"}</Text>
          <Text>发行版本：{targetOs?.label || "所选镜像"}</Text>
          <Text type="danger">重装会覆盖系统盘数据，当前系统盘内的文件和配置可能丢失。</Text>
          <Text type={values.format_data_disk ? "danger" : "secondary"}>
            {values.format_data_disk ? "已选择格式化数据盘，数据盘内容也会被清空。" : "数据盘不会格式化。"}
          </Text>
        </Space>
      ),
      okText: "确认重装",
      cancelText: "取消",
      okButtonProps: { danger: true },
      onOk: () => doReinstall(values),
    })
  }

  return (
    <Space direction="vertical" size={20} style={{ width: "100%", maxWidth: 820 }}>
      <Space direction="vertical" size={4}>
        <Title level={5} style={{ margin: 0 }}>重装系统</Title>
        <Text type="secondary">镜像来自该实例所属产品组，选择方式与购买页保持一致。</Text>
      </Space>

      {!server.upstream_id ? (
        <Alert type="warning" showIcon message="实例尚未开通，暂不能重装系统" />
      ) : osOptions.length === 0 ? (
        <Alert type="warning" showIcon message="当前产品组没有可用镜像" />
      ) : null}

      <Form<ReinstallFormValues>
        form={form}
        layout="vertical"
        initialValues={{
          os: defaultOs?.value,
          format_data_disk: false,
        }}
        onFinish={handleFinish}
      >
        <Form.Item name="os" hidden rules={[{ required: true, message: "请选择重装镜像" }]}>
          <Input />
        </Form.Item>

        <div className="mb-6 rounded-lg border border-[#f0f0f0] bg-white p-4">
          <div className="mb-3 flex items-center justify-between gap-3">
            <Text strong>操作系统</Text>
            {selectedOs ? <Text type="secondary">{selectedOs.label}</Text> : null}
          </div>
          <div className="flex h-72 gap-4 overflow-hidden">
            <div className="flex w-36 shrink-0 flex-col gap-2 overflow-y-auto">
              {groupedOptions.map((group) => {
                const active = selectedFamily === group.family
                return (
                  <button
                    key={group.family}
                    type="button"
                    disabled={actionDisabled || submitting}
                    onClick={() => selectFamily(group.family)}
                    className={`flex items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition-all ${
                      active
                        ? "border-[#91caff] bg-[#e6f4ff] text-[#1677ff]"
                        : "border-transparent text-[#595959] hover:bg-[#f5f5f5]"
                    } ${actionDisabled || submitting ? "cursor-not-allowed opacity-60" : ""}`}
                  >
                    <OsIcon name={group.family} size={20} active={active} />
                    <span className="truncate">{group.family}</span>
                  </button>
                )
              })}
            </div>

            <div className="w-px shrink-0 bg-[#f0f0f0]" />

            <div className="flex min-w-0 flex-1 flex-col gap-2 overflow-y-auto pr-1">
              {visibleOptions.map((option) => {
                const active = selectedOsId === option.value
                return (
                  <button
                    key={option.value}
                    type="button"
                    disabled={actionDisabled || submitting}
                    onClick={() => selectOs(option)}
                    className={`flex items-center justify-between gap-3 rounded-lg border px-3 py-2 text-left text-sm transition-all ${
                      active
                        ? "border-[#91caff] bg-[#e6f4ff] text-[#1677ff] shadow-sm"
                        : "border-transparent text-[#595959] hover:bg-[#f5f5f5]"
                    } ${actionDisabled || submitting ? "cursor-not-allowed opacity-60" : ""}`}
                  >
                    <span className="flex min-w-0 items-center gap-2">
                      <OsIcon name={option.label} size={18} active={active} />
                      <span className="truncate">{option.label}</span>
                    </span>
                    {active ? <CheckCircle2 className="h-4 w-4 shrink-0" /> : null}
                  </button>
                )
              })}

              {selectedFamilyOptions.length > PAGE_SIZE ? (
                <button
                  type="button"
                  disabled={actionDisabled || submitting}
                  onClick={() => setShowAll((value) => !value)}
                  className="flex w-full items-center gap-2 rounded-lg border border-transparent px-3 py-2 text-left text-sm font-medium text-[#595959] transition-all hover:bg-[#f5f5f5] disabled:cursor-not-allowed disabled:opacity-60"
                >
                  {showAll ? "收起" : `显示更多（${selectedFamilyOptions.length - PAGE_SIZE} 个）`}
                </button>
              ) : null}
            </div>
          </div>
        </div>

        <Form.Item name="format_data_disk" label="格式化数据盘" valuePropName="checked">
          <Switch checkedChildren="格式化" unCheckedChildren="保留" disabled={actionDisabled || submitting} />
        </Form.Item>

        {formatDataDisk ? (
          <Alert
            type="error"
            showIcon
            message="已选择格式化数据盘"
            description="提交重装后，数据盘内容也会被清空。"
            style={{ marginBottom: 18 }}
          />
        ) : null}

        <Form.Item style={{ marginBottom: 0 }}>
          <Button
            danger
            type="primary"
            htmlType="submit"
            icon={<ReloadOutlined />}
            loading={submitting}
            disabled={actionDisabled}
          >
            提交重装
          </Button>
        </Form.Item>
      </Form>
    </Space>
  )
}
