"use client";

import {
  Check,
  Copy,
  Database,
  MapPin,
  Radio,
  X
} from "lucide-react";
import Image from "next/image";
import type { ComponentType } from "react";
import { useEffect, useRef, useState } from "react";
import {
  MAP_FOCUS_SURFACE_CLASS_NAME,
  MAP_MAJOR_PANEL_RADIUS_CLASS_NAME
} from "@/features/map/core/components/map-control-styles";
import { showMapNotice } from "@/features/map/core/components/notice";
import { cn } from "@/lib/utils";
import { SCADA_ICON_PATHS } from "../map/scada";
import type { WaterNetworkSourceId } from "../map/sources";
import type { DetailFeature } from "../types";
import {
  formatFeaturePropertyValue,
  getFeaturePanelModel,
  type FeaturePanelBadgeTone
} from "../utils/feature-properties";
import {
  ConduitFeatureIcon,
  JunctionFeatureIcon,
  OrificeFeatureIcon,
  OutfallFeatureIcon,
  PumpFeatureIcon,
  type DrainageFeatureIconProps
} from "./drainage-feature-icons";

type FeaturePopoverProps = {
  feature: DetailFeature | null;
  onClose: () => void;
};

const FEATURE_LAYER_META: Record<
  WaterNetworkSourceId,
  {
    icon: ComponentType<DrainageFeatureIconProps>;
    label: string;
    headerClassName: string;
    labelClassName: string;
    iconClassName: string;
  }
> = {
  conduits: { icon: ConduitFeatureIcon, label: "管渠", headerClassName: "bg-teal-50/70", labelClassName: "text-teal-800", iconClassName: "bg-teal-700 text-white ring-teal-900/10" },
  junctions: { icon: JunctionFeatureIcon, label: "检查井", headerClassName: "bg-blue-50/70", labelClassName: "text-blue-800", iconClassName: "bg-sky-700 text-white ring-sky-900/10" },
  orifices: { icon: OrificeFeatureIcon, label: "孔口", headerClassName: "bg-slate-50/70", labelClassName: "text-slate-700", iconClassName: "bg-slate-600 text-white ring-slate-900/10" },
  outfalls: { icon: OutfallFeatureIcon, label: "排放口", headerClassName: "bg-blue-50/70", labelClassName: "text-blue-800", iconClassName: "bg-slate-700 text-white ring-slate-900/10" },
  pumps: { icon: PumpFeatureIcon, label: "泵", headerClassName: "bg-teal-50/70", labelClassName: "text-teal-800", iconClassName: "bg-cyan-800 text-white ring-cyan-950/10" },
  scada: { icon: JunctionFeatureIcon, label: "SCADA 测点", headerClassName: "bg-blue-50/70", labelClassName: "text-blue-800", iconClassName: "bg-blue-700 text-white ring-blue-900/10" }
};

const BADGE_CLASS_NAMES: Record<FeaturePanelBadgeTone, string> = {
  active: "bg-emerald-50 text-emerald-700 ring-emerald-600/15",
  inactive: "bg-slate-100 text-slate-600 ring-slate-500/15",
  warning: "bg-orange-50 text-orange-700 ring-orange-600/15",
  critical: "bg-red-50 text-red-700 ring-red-600/15",
  info: "bg-blue-50 text-blue-700 ring-blue-600/15"
};

const BADGE_DOT_CLASS_NAMES: Record<FeaturePanelBadgeTone, string> = {
  active: "bg-emerald-500",
  inactive: "bg-slate-400",
  warning: "bg-orange-500",
  critical: "bg-red-500",
  info: "bg-blue-500"
};

export function FeaturePopover({ feature, onClose }: FeaturePopoverProps) {
  const [copiedId, setCopiedId] = useState<string | null>(null);
  const copyResetTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => () => {
    if (copyResetTimeoutRef.current) {
      clearTimeout(copyResetTimeoutRef.current);
    }
  }, []);

  if (!feature) {
    return null;
  }

  const panelModel = getFeaturePanelModel(feature.layer, feature.properties, feature.id);
  const layerMeta = FEATURE_LAYER_META[feature.layer];
  const LayerIcon = layerMeta.icon;
  const copied = copiedId === panelModel.id;
  const canCopy = panelModel.id !== "暂无";

  const handleCopyId = async () => {
    try {
      if (!navigator.clipboard) {
        throw new Error("Clipboard API unavailable");
      }

      await navigator.clipboard.writeText(panelModel.id);
      setCopiedId(panelModel.id);

      if (copyResetTimeoutRef.current) {
        clearTimeout(copyResetTimeoutRef.current);
      }

      copyResetTimeoutRef.current = setTimeout(() => setCopiedId(null), 1500);
    } catch {
      showMapNotice({
        tone: "error",
        title: "无法复制编号",
        message: "请手动选择编号后复制。"
      });
    }
  };

  if (feature.layer === "scada") {
    return (
      <ScadaFeaturePopover
        feature={feature}
        copied={copied}
        canCopy={canCopy}
        onCopy={() => void handleCopyId()}
        onClose={onClose}
      />
    );
  }

  return (
    <aside
      className={cn(
        "pointer-events-auto absolute left-1/2 top-[92px] z-20 w-[min(380px,calc(100vw-24px))] -translate-x-1/2 overflow-hidden",
        MAP_FOCUS_SURFACE_CLASS_NAME,
        MAP_MAJOR_PANEL_RADIUS_CLASS_NAME
      )}
    >
      <header className={cn("px-4 pb-3 pt-4", layerMeta.headerClassName)}>
        <div className="grid grid-cols-[48px_minmax(0,1fr)_auto] items-start gap-3">
          <span className={cn("grid h-12 w-12 place-items-center rounded-full ring-1", layerMeta.iconClassName)} aria-hidden="true">
            <LayerIcon size={24} />
          </span>

          <div className="min-w-0">
            <div className="flex min-w-0 flex-nowrap items-center gap-1.5">
              <span className={cn("min-w-0 truncate text-xs font-semibold", layerMeta.labelClassName)}>{layerMeta.label}</span>
              {panelModel.badge ? (
                <span className={cn("inline-flex shrink-0 items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-semibold leading-4 ring-1 ring-inset", BADGE_CLASS_NAMES[panelModel.badge.tone])}>
                  <span className={cn("h-1.5 w-1.5 rounded-full", BADGE_DOT_CLASS_NAMES[panelModel.badge.tone])} aria-hidden="true" />
                  {panelModel.badge.label}
                </span>
              ) : null}
            </div>
            <h3 className="mt-1 truncate text-base font-semibold text-slate-950">{feature.title}</h3>
            <p className="mt-0.5 truncate text-xs text-slate-600 tabular-nums">编号 {panelModel.id}</p>
          </div>

          <div className="flex items-center gap-0.5">
            {canCopy ? (
              <button type="button" aria-label={copied ? "编号已复制" : "复制编号"} title={copied ? "编号已复制" : "复制编号"} onClick={() => void handleCopyId()} className="relative grid h-10 w-10 shrink-0 place-items-center rounded-xl text-slate-500 transition-[background-color,color,transform] duration-150 [@media(hover:hover)]:hover:bg-white/70 [@media(hover:hover)]:hover:text-slate-950 active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600/25">
                <Copy size={15} aria-hidden="true" className={cn("absolute transition-[opacity,transform] duration-150", copied ? "scale-90 opacity-0" : "scale-100 opacity-100")} />
                <Check size={16} aria-hidden="true" className={cn("absolute text-emerald-600 transition-[opacity,transform] duration-150", copied ? "scale-100 opacity-100" : "scale-90 opacity-0")} />
              </button>
            ) : null}
            <button type="button" aria-label="关闭要素信息" title="关闭要素信息" onClick={onClose} className="grid h-10 w-10 shrink-0 place-items-center rounded-xl text-slate-500 transition-[background-color,color,transform] duration-150 [@media(hover:hover)]:hover:bg-white/70 [@media(hover:hover)]:hover:text-slate-950 active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600/25">
              <X size={16} aria-hidden="true" />
            </button>
          </div>
        </div>
      </header>

      <div className="px-4 py-3">
        {panelModel.attributes.length > 0 ? (
          <>
            <div className="mb-2 flex items-center gap-2 text-xs font-semibold text-slate-500">
              <Database size={14} aria-hidden="true" />
              设施属性
            </div>
            <dl className="surface-reading divide-y divide-slate-100 rounded-xl px-3">
              {panelModel.attributes.map((entry) => (
                <div key={entry.key} className="grid min-h-10 grid-cols-[96px_minmax(0,1fr)] items-baseline gap-3 py-2.5">
                  <dt className="text-xs font-medium leading-5 text-slate-500">{entry.label}</dt>
                  <dd className={cn("break-words text-right text-sm font-semibold leading-5 text-slate-800 tabular-nums", entry.value === "暂无" && "font-medium text-slate-400")}>
                    {entry.value}
                  </dd>
                </div>
              ))}
            </dl>
          </>
        ) : (
          <p className="py-3 text-center text-sm text-slate-500">暂无可展示属性</p>
        )}
      </div>

      <span className="sr-only" aria-live="polite">
        {copied ? "编号已复制" : ""}
      </span>
    </aside>
  );
}

type ScadaFeaturePopoverProps = {
  feature: DetailFeature;
  copied: boolean;
  canCopy: boolean;
  onCopy: () => void;
  onClose: () => void;
};

function ScadaFeaturePopover({ feature, copied, canCopy, onCopy, onClose }: ScadaFeaturePopoverProps) {
  const properties = feature.properties;
  const presentation = getScadaPresentation(properties.device_type_id);
  const active = properties.active === true || String(properties.active).toLowerCase() === "true";
  const pointId = formatFeaturePropertyValue("point_external_id", properties.point_external_id ?? feature.id);
  const attributes = [
    ["设备编号", formatFeaturePropertyValue("device_external_id", properties.device_external_id)],
    ["关联检查井", formatFeaturePropertyValue("junction_id", properties.junction_id)],
    ["同步时间", formatFeaturePropertyValue("synced_at", properties.synced_at)]
  ];

  return (
    <aside
      className={cn(
        "pointer-events-auto absolute left-1/2 top-[92px] z-20 w-[min(380px,calc(100vw-24px))]",
        MAP_FOCUS_SURFACE_CLASS_NAME,
        "-translate-x-1/2 overflow-hidden",
        MAP_MAJOR_PANEL_RADIUS_CLASS_NAME
      )}
    >
      <header className={cn("px-4 pb-3 pt-4", presentation.headerClassName)}>
        <div className="grid grid-cols-[48px_minmax(0,1fr)_auto] items-start gap-3">
          <Image src={presentation.iconPath} alt="" width={48} height={48} className="drop-shadow-sm" />
          <div className="min-w-0">
            <div className="flex min-w-0 flex-nowrap items-center gap-1.5">
              <span className={cn("min-w-0 truncate text-xs font-semibold", presentation.labelClassName)} title={formatFeaturePropertyValue("device_type_name", properties.device_type_name)}>
                {formatFeaturePropertyValue("device_type_name", properties.device_type_name)}
              </span>
              <span className={cn(
                "inline-flex shrink-0 items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-semibold ring-1 ring-inset",
                active ? "bg-emerald-500/10" : "bg-slate-500/10",
                active ? "text-emerald-700 ring-emerald-600/20" : "text-slate-600 ring-slate-500/20"
              )}>
                <span className={cn("h-1.5 w-1.5 rounded-full", active ? "bg-emerald-500" : "bg-slate-400")} />
                {active ? "在线" : "离线"}
              </span>
            </div>
            <h3 className="mt-1 truncate text-base font-semibold text-slate-950">
              {formatFeaturePropertyValue("point_name", properties.point_name)}
            </h3>
            <p className="mt-0.5 truncate text-xs text-slate-600 tabular-nums">测点 {pointId}</p>
          </div>
          <div className="flex items-center gap-0.5">
            {canCopy ? (
              <button type="button" aria-label={copied ? "测点编号已复制" : "复制测点编号"} title={copied ? "测点编号已复制" : "复制测点编号"} onClick={onCopy} className="relative grid h-10 w-10 place-items-center rounded-xl text-slate-500 transition-[background-color,color,transform] duration-150 [@media(hover:hover)]:hover:bg-white/70 [@media(hover:hover)]:hover:text-slate-950 active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600/25">
                <Copy size={15} aria-hidden="true" className={cn("absolute transition-[opacity,transform] duration-150", copied ? "scale-90 opacity-0" : "scale-100 opacity-100")} />
                <Check size={16} aria-hidden="true" className={cn("absolute text-emerald-600 transition-[opacity,transform] duration-150", copied ? "scale-100 opacity-100" : "scale-90 opacity-0")} />
              </button>
            ) : null}
            <button type="button" aria-label="关闭 SCADA 测点信息" title="关闭 SCADA 测点信息" onClick={onClose} className="grid h-10 w-10 place-items-center rounded-xl text-slate-500 transition-[background-color,color,transform] duration-150 [@media(hover:hover)]:hover:bg-white/70 [@media(hover:hover)]:hover:text-slate-950 active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600/25">
              <X size={16} aria-hidden="true" />
            </button>
          </div>
        </div>
      </header>

      <div className="px-4 py-3">
        <div className="mb-2 flex items-center gap-2 text-xs font-semibold text-slate-500">
          <Radio size={14} aria-hidden="true" />
          设备与关联信息
        </div>
        <dl className="surface-reading divide-y divide-slate-100 rounded-xl px-3">
          {attributes.map(([label, value]) => (
            <div key={label} className="grid min-h-10 grid-cols-[92px_minmax(0,1fr)] items-baseline gap-3 py-2.5">
              <dt className="text-xs font-medium text-slate-500">{label}</dt>
              <dd className={cn("break-words text-right text-sm font-semibold text-slate-800 tabular-nums", value === "暂无" && "font-medium text-slate-400")}>{value}</dd>
            </div>
          ))}
        </dl>

        <div className="surface-reading mt-3 grid grid-cols-[18px_1fr] gap-2 rounded-xl px-3 py-2.5 text-xs leading-5 text-slate-600">
          <MapPin size={15} className="mt-0.5 text-slate-500" aria-hidden="true" />
          <p>当前点位由管网节点空间均匀采样生成，用于空间展示，不代表设备真实安装坐标。</p>
        </div>
        <div className="mt-2 flex items-center gap-2 px-1 text-xs text-slate-400">
          <Database size={13} aria-hidden="true" />
          当前图层仅提供设备元数据，暂未接入实时测值与历史曲线
        </div>
      </div>
      <span className="sr-only" aria-live="polite">{copied ? "测点编号已复制" : ""}</span>
    </aside>
  );
}

function getScadaPresentation(rawTypeId: unknown) {
  const typeId = Number(rawTypeId);
  if (typeId === 72) return { iconPath: SCADA_ICON_PATHS.waterQuality, headerClassName: "bg-teal-50/70", labelClassName: "text-teal-800" };
  if (typeId === 58) return { iconPath: SCADA_ICON_PATHS.radarLevel, headerClassName: "bg-blue-50/70", labelClassName: "text-blue-800" };
  if (typeId === 45) return { iconPath: SCADA_ICON_PATHS.ultrasonicFlow, headerClassName: "bg-orange-50/70", labelClassName: "text-orange-800" };
  return { iconPath: SCADA_ICON_PATHS.unknown, headerClassName: "bg-slate-50/70", labelClassName: "text-slate-700" };
}
