import {
    Bell,
    CheckCircle2,
    Info,
    TriangleAlert,
    X,
    Trash2,
} from "lucide-react";
import { createPortal } from "react-dom";
import { useEffect, useId, useMemo, useRef, useState } from "react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import type { SignalAlertEvent } from "@/components/trading/SignalEventMarkerOverlay";
import type { MarketType } from "@/lib/market";

type AlertPosition = {
    right: number;
    top?: number;
    bottom?: number;
    maxHeight: number;
};

export type TradingAlert = {
    id: string;
    type:
        | SignalAlertEvent
        | "direction_changed"
        | "refreshed"
        | "calculation_failed";
    severity: "info" | "success" | "warning" | "error";
    title: string;
    message: string;
    symbol: string;
    interval: string;
    market?: MarketType;
    provider?: string;
    mode: string;
    direction?: string | null;
    timestamp: number;
    /** Unix timestamp in seconds for the candle/event position on the chart. */
    chartTime?: number | null;
    /** Price captured at the chart event for focus/marker placement. */
    chartPrice?: number | null;
    snapshotId?: string | null;
};

interface AlertCenterProps {
    alerts: TradingAlert[];
    onDismiss: (id: string) => void;
    onClear: () => void;
    onFocus?: (alert: TradingAlert) => void;
}

const severityIcon = {
    info: Info,
    success: CheckCircle2,
    warning: TriangleAlert,
    error: TriangleAlert,
};

export default function AlertCenter({
    alerts,
    onDismiss,
    onClear,
    onFocus,
}: AlertCenterProps) {
    const [open, setOpen] = useState(false);
    const [position, setPosition] = useState<AlertPosition | null>(null);
    const containerRef = useRef<HTMLDivElement | null>(null);
    const triggerRef = useRef<HTMLButtonElement | null>(null);
    const panelRef = useRef<HTMLDivElement | null>(null);
    const dialogId = useId();
    const unread = alerts.length;

    const sorted: TradingAlert[] = useMemo(
        () => [...alerts].sort((a, b) => b.timestamp - a.timestamp),
        [alerts],
    );

    useEffect(() => {
        if (typeof document === "undefined" || !open) return;

        const updatePosition = () => {
            const trigger = triggerRef.current;
            if (!trigger) return;
            const rect = trigger.getBoundingClientRect();
            const viewportPadding = 8;
            const spaceBelow = Math.max(
                160,
                window.innerHeight - rect.bottom - viewportPadding * 2,
            );
            const spaceAbove = Math.max(160, rect.top - viewportPadding * 2);
            const placeAbove = spaceBelow < 300 && spaceAbove > spaceBelow;

            setPosition({
                right: Math.max(
                    viewportPadding,
                    window.innerWidth - rect.right,
                ),
                ...(placeAbove
                    ? {
                          bottom:
                              window.innerHeight - rect.top + viewportPadding,
                      }
                    : { top: rect.bottom + viewportPadding }),
                maxHeight: Math.min(
                    400,
                    Math.floor(placeAbove ? spaceAbove : spaceBelow),
                ),
            });
        };

        updatePosition();
        window.addEventListener("resize", updatePosition);
        window.addEventListener("scroll", updatePosition, true);

        const onPointerDown = (event: PointerEvent) => {
            const target = event.target;
            if (!(target instanceof Node)) return;
            if (
                !containerRef.current?.contains(target) &&
                !panelRef.current?.contains(target)
            ) {
                setOpen(false);
            }
        };
        const onKeyDown = (event: KeyboardEvent) => {
            if (event.key === "Escape") {
                setOpen(false);
                triggerRef.current?.focus();
            }
        };

        document.addEventListener("pointerdown", onPointerDown);
        document.addEventListener("keydown", onKeyDown);
        return () => {
            window.removeEventListener("resize", updatePosition);
            window.removeEventListener("scroll", updatePosition, true);
            document.removeEventListener("pointerdown", onPointerDown);
            document.removeEventListener("keydown", onKeyDown);
        };
    }, [open]);

    const panel =
        open && position && typeof document !== "undefined"
            ? createPortal(
                  <div
                      ref={panelRef}
                      id={dialogId}
                      role="dialog"
                      aria-label="Market analysis alerts"
                      aria-modal="false"
                      className="fixed z-100 flex w-[min(92vw,380px)] flex-col overflow-hidden rounded-xl border border-border bg-card shadow-2xl"
                      style={{
                          right: position.right,
                          top: position.top,
                          bottom: position.bottom,
                          maxHeight: position.maxHeight,
                      }}
                  >
                      <div className="flex shrink-0 items-center justify-between border-b border-border px-4 py-3">
                          <div className="min-w-0">
                              <p className="text-sm font-semibold text-foreground">
                                  Alert Center
                              </p>
                              <p className="text-[11px] text-muted-foreground">
                                  Signal and market events for this workspace.
                              </p>
                          </div>
                          {alerts.length > 0 && (
                              <Button
                                  type="button"
                                  variant="ghost"
                                  size="sm"
                                  className="ml-2 shrink-0 gap-1.5 text-xs"
                                  onClick={onClear}
                              >
                                  <Trash2 className="h-3.5 w-3.5" />
                                  Clear
                              </Button>
                          )}
                      </div>
                      <div className="min-h-0 flex-1 overflow-y-auto p-2">
                          {sorted.length === 0 ? (
                              <div className="px-4 py-10 text-center">
                                  <Bell className="mx-auto h-6 w-6 text-muted-foreground/60" />
                                  <p className="mt-2 text-sm font-medium text-foreground">
                                      No alerts yet
                                  </p>
                                  <p className="mt-1 text-xs text-muted-foreground">
                                      New signal events will appear here.
                                  </p>
                              </div>
                          ) : (
                              sorted.map((alert) => {
                                  const Icon = severityIcon[alert.severity];
                                  return (
                                      <div
                                          key={alert.id}
                                          className="group rounded-lg p-3 hover:bg-muted/40"
                                      >
                                          <div className="flex gap-3">
                                              <Icon
                                                  className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground"
                                                  aria-hidden="true"
                                              />
                                              <button
                                                  type="button"
                                                  className="min-w-0 flex-1 text-left"
                                                  onClick={() => {
                                                      onFocus?.(alert);
                                                      setOpen(false);
                                                  }}
                                              >
                                                  <div className="flex flex-wrap items-center gap-1.5">
                                                      <span className="text-xs font-semibold text-foreground">
                                                          {alert.title}
                                                      </span>
                                                      <Badge
                                                          variant="outline"
                                                          className="px-1.5 py-0 text-[9px] uppercase"
                                                      >
                                                          {alert.mode}
                                                      </Badge>
                                                      {alert.direction && (
                                                          <Badge
                                                              variant="outline"
                                                              className="px-1.5 py-0 text-[9px] uppercase"
                                                          >
                                                              {alert.direction}
                                                          </Badge>
                                                      )}
                                                  </div>
                                                  <p className="mt-1 text-[11px] leading-relaxed text-muted-foreground">
                                                      {alert.message}
                                                  </p>
                                                  <p className="mt-1 text-[10px] text-muted-foreground/70">
                                                      {alert.symbol} ·{" "}
                                                      {alert.interval} ·{" "}
                                                      {alert.market ===
                                                      "futures"
                                                          ? "Futures"
                                                          : "Spot"}{" "}
                                                      ·{" "}
                                                      {(
                                                          alert.provider ??
                                                          "binance"
                                                      ).toUpperCase()}{" "}
                                                      ·{" "}
                                                      {new Date(
                                                          alert.timestamp,
                                                      ).toLocaleTimeString([], {
                                                          hour: "2-digit",
                                                          minute: "2-digit",
                                                          second: "2-digit",
                                                      })}
                                                  </p>
                                              </button>
                                              <button
                                                  type="button"
                                                  className="rounded-md p-1 text-muted-foreground opacity-70 hover:bg-muted hover:text-foreground"
                                                  aria-label={`Dismiss ${alert.title}`}
                                                  onClick={() =>
                                                      onDismiss(alert.id)
                                                  }
                                              >
                                                  <X className="h-3.5 w-3.5" />
                                              </button>
                                          </div>
                                      </div>
                                  );
                              })
                          )}
                      </div>
                  </div>,
                  document.body,
              )
            : null;

    return (
        <div ref={containerRef} className="relative">
            <Button
                ref={triggerRef}
                type="button"
                variant="outline"
                size="sm"
                className="relative gap-2"
                aria-expanded={open}
                aria-controls={dialogId}
                aria-haspopup="dialog"
                onClick={() => setOpen((value) => !value)}
            >
                <Bell className="h-4 w-4" />
                <span className="hidden sm:inline">Alerts</span>
                {unread > 0 && (
                    <span className="min-w-4 rounded-full bg-primary px-1 text-[10px] leading-4 text-primary-foreground">
                        {Math.min(unread, 99)}
                    </span>
                )}
            </Button>
            {panel}
        </div>
    );
}
