"use client";

import { useMemo, useState, useCallback } from "react";
import type { AxiosError } from "axios";
import { useCartStore } from "@/store/cartStore";
import { useAuthStore } from "@/store/authStore";
import { lockSeatApi } from "@/api/client";

// ─── Types ────────────────────────────────────────────────────────────────────

type SeatStatus = "AVAILABLE" | "SOLD" | "LOCKED";
type SeatType = "VIP" | "STD";

interface SeatData {
  id: number;
  x: number;
  y: number;
  row: number;
  number: number;
  sector: string;
  type: SeatType;
  status: SeatStatus;
  price: number;
}

// ─── Layout constants ─────────────────────────────────────────────────────────

const CX = 200;
const CY = 192;

const OCTAGON_R = 58;

/** Three concentric seat rings around the octagon. */
const RING_CONFIG = [
  { radius: 90,  count: 22, sector: "VIP",  type: "VIP" as SeatType, rowNum: 1, price: 12500 },
  { radius: 122, count: 32, sector: "A",    type: "STD" as SeatType, rowNum: 2, price: 5000  },
  { radius: 157, count: 42, sector: "B",    type: "STD" as SeatType, rowNum: 3, price: 2500  },
] as const;

// ─── Deterministic seat status (stable across re-renders) ─────────────────────

function deterministicStatus(id: number): SeatStatus {
  // Knuth multiplicative hash → spread across 100
  const v = ((id * 2654435761) >>> 0) % 100;
  if (v < 56) return "AVAILABLE";
  if (v < 80) return "SOLD";
  return "LOCKED";
}

// ─── Seat geometry ────────────────────────────────────────────────────────────

function generateSeats(): SeatData[] {
  const seats: SeatData[] = [];
  let globalId = 0;

  for (const ring of RING_CONFIG) {
    for (let i = 0; i < ring.count; i++) {
      // Distribute evenly, starting from top (−π/2)
      const angle = (i / ring.count) * 2 * Math.PI - Math.PI / 2;
      const deg = ((angle * 180) / Math.PI + 360) % 360;

      // Aisle gaps at 0° (top) and 180° (bottom) — each ~10° wide
      if (deg < 6 || deg > 354) continue;
      if (deg > 174 && deg < 186) continue;

      globalId++;
      seats.push({
        id: globalId,
        x: Math.round((CX + ring.radius * Math.cos(angle)) * 10) / 10,
        y: Math.round((CY + ring.radius * Math.sin(angle)) * 10) / 10,
        row: ring.rowNum,
        number: i + 1,
        sector: ring.sector,
        type: ring.type,
        status: deterministicStatus(globalId),
        price: ring.price,
      });
    }
  }
  return seats;
}

/** Computed once at module load — deterministic, no side effects. */
const SEATS: SeatData[] = generateSeats();

// ─── Octagon polygon points ───────────────────────────────────────────────────

function octagonPoints(cx: number, cy: number, r: number): string {
  return Array.from({ length: 8 }, (_, i) => {
    // +π/8 offset → flat-top octagon (horizontal top/bottom edges)
    const a = (i / 8) * 2 * Math.PI + Math.PI / 8;
    return `${cx + r * Math.cos(a)},${cy + r * Math.sin(a)}`;
  }).join(" ");
}

// ─── Seat color helpers ───────────────────────────────────────────────────────

function seatFill(seat: SeatData, effectiveStatus: SeatStatus, isSelected: boolean): string {
  if (isSelected) return "#E32636";
  if (effectiveStatus === "SOLD") return "#2D3748";
  if (effectiveStatus === "LOCKED") return "#D97706";
  return seat.type === "VIP" ? "#8B5CF6" : "#0891B2";
}

function seatStroke(seat: SeatData, effectiveStatus: SeatStatus, isSelected: boolean): string {
  if (isSelected) return "#FF6B7A";
  if (effectiveStatus === "SOLD") return "#4B5563";
  if (effectiveStatus === "LOCKED") return "#F59E0B";
  return seat.type === "VIP" ? "#C084FC" : "#38BDF8";
}

// ─── Component ────────────────────────────────────────────────────────────────

export default function OctagonSeatMap() {
  const { seats: cartSeats, addSeat, removeSeat } = useCartStore();
  const selectedIds = useMemo(() => new Set(cartSeats.map((s) => s.seatId)), [cartSeats]);

  // Local status overrides: applied after a 409 response to immediately mark seat as LOCKED
  const [localStatuses, setLocalStatuses] = useState<Record<number, SeatStatus>>({});

  // ID of seat currently awaiting API response — prevents multiple concurrent requests
  const [pendingId, setPendingId] = useState<number | null>(null);

  // Toast notification state (two-part so text stays during fade-out)
  const [toastMessage, setToastMessage] = useState("");
  const [toastVisible, setToastVisible] = useState(false);

  const showToast = useCallback((message: string) => {
    setToastMessage(message);
    setToastVisible(true);
    setTimeout(() => setToastVisible(false), 3500);
  }, []);

  const handleSeatClick = useCallback(
    async (seat: SeatData) => {
      const effectiveStatus = localStatuses[seat.id] ?? seat.status;
      if (effectiveStatus !== "AVAILABLE") return;

      // Block all clicks while another request is in flight
      if (pendingId !== null) return;

      // Deselect: remove from cart without API call (lock expires via Redis TTL)
      if (selectedIds.has(seat.id)) {
        removeSeat(seat.id);
        return;
      }

      const userId = useAuthStore.getState().user?.id ?? 1;
      setPendingId(seat.id);

      try {
        await lockSeatApi(seat.id, userId);

        // ✅ 200 OK — seat is ours, add to cart
        addSeat({
          seatId: seat.id,
          sector: seat.sector,
          row: seat.row,
          number: seat.number,
          price: seat.price,
        });
      } catch (err) {
        const axiosErr = err as AxiosError;

        // Mark seat as LOCKED locally so it becomes visually unavailable immediately
        setLocalStatuses((prev) => ({ ...prev, [seat.id]: "LOCKED" }));

        if (axiosErr.response?.status === 409) {
          // ⚡ Race condition — someone else grabbed the seat
          showToast("Извините, это место только что заняли");
        } else {
          showToast("Ошибка сети. Попробуйте ещё раз");
        }
      } finally {
        setPendingId(null);
      }
    },
    [localStatuses, pendingId, selectedIds, addSeat, removeSeat, showToast]
  );

  return (
    <div className="relative w-full px-2">
      {/* ── Toast notification ── */}
      <div
        className={`absolute top-1 left-0 right-0 z-10 flex justify-center pointer-events-none transition-all duration-300 ${
          toastVisible ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-1"
        }`}
        aria-live="polite"
        aria-atomic="true"
      >
        <div className="flex items-center gap-2 bg-[#1C1C1E] border border-[#E32636]/50 text-white text-[12px] font-medium px-4 py-2 rounded-full shadow-xl">
          <span className="w-2 h-2 rounded-full bg-[#E32636] flex-shrink-0" />
          {toastMessage}
        </div>
      </div>

      <svg
        viewBox="0 0 400 384"
        className="w-full"
        aria-label="Схема зала"
        role="img"
        style={{ cursor: pendingId !== null ? "wait" : undefined }}
      >
        <defs>
          {/* Arena radial gradient */}
          <radialGradient id="arena-bg" cx="50%" cy="50%" r="50%">
            <stop offset="0%"   stopColor="#131328" />
            <stop offset="100%" stopColor="#080812" />
          </radialGradient>

          {/* Neon glow for selected seats */}
          <filter id="glow-red" x="-80%" y="-80%" width="260%" height="260%">
            <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>

          {/* Subtle glow for available seats */}
          <filter id="glow-soft" x="-50%" y="-50%" width="200%" height="200%">
            <feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>

          {/* Cage glow for octagon border */}
          <filter id="glow-cage" x="-20%" y="-20%" width="140%" height="140%">
            <feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>
        </defs>

        {/* ── Outer arena ellipse ── */}
        <ellipse
          cx={CX} cy={CY}
          rx={186} ry={168}
          fill="url(#arena-bg)"
          stroke="#1E3A5F"
          strokeWidth="2"
        />
        {/* Neon outer rim */}
        <ellipse
          cx={CX} cy={CY}
          rx={186} ry={168}
          fill="none"
          stroke="#2DD4BF"
          strokeWidth="1"
          opacity="0.35"
        />

        {/* ── Inner floor area ── */}
        <ellipse
          cx={CX} cy={CY}
          rx={146} ry={128}
          fill="#0B0B1E"
          stroke="#1E293B"
          strokeWidth="1"
        />

        {/* ── Sector divider lines (subtle, from inner ellipse outward) ── */}
        {[0, 90, 180, 270].map((deg) => {
          const rad = (deg * Math.PI) / 180;
          const x1 = CX + 148 * Math.cos(rad);
          const y1 = CY + 130 * Math.sin(rad);
          const x2 = CX + 182 * Math.cos(rad);
          const y2 = CY + 165 * Math.sin(rad);
          return (
            <line
              key={deg}
              x1={x1} y1={y1}
              x2={x2} y2={y2}
              stroke="#1E293B"
              strokeWidth="1"
            />
          );
        })}

        {/* ── Octagon cage border (glow layer) ── */}
        <polygon
          points={octagonPoints(CX, CY, OCTAGON_R)}
          fill="none"
          stroke="#38BDF8"
          strokeWidth="4"
          opacity="0.25"
          filter="url(#glow-cage)"
        />
        {/* Octagon fill */}
        <polygon
          points={octagonPoints(CX, CY, OCTAGON_R)}
          fill="#05050F"
          stroke="#38BDF8"
          strokeWidth="1.5"
        />

        {/* Octagon inner cage cross-lines */}
        {[0, 1, 2, 3].map((i) => {
          const a1 = (i / 8) * 2 * Math.PI + Math.PI / 8;
          const a2 = ((i + 4) / 8) * 2 * Math.PI + Math.PI / 8;
          return (
            <line
              key={i}
              x1={CX + (OCTAGON_R - 6) * Math.cos(a1)}
              y1={CY + (OCTAGON_R - 6) * Math.sin(a1)}
              x2={CX + (OCTAGON_R - 6) * Math.cos(a2)}
              y2={CY + (OCTAGON_R - 6) * Math.sin(a2)}
              stroke="#1E3A5F"
              strokeWidth="0.8"
              opacity="0.5"
            />
          );
        })}

        {/* Stage label */}
        <text
          x={CX} y={CY + 5}
          textAnchor="middle"
          dominantBaseline="middle"
          fill="#64748B"
          fontSize="13"
          fontWeight="600"
          letterSpacing="1"
        >
          Stage
        </text>

        {/* ── Sector labels ── */}
        <text x={CX}       y={CY - 136} textAnchor="middle" fill="#94A3B8" fontSize="9" fontWeight="500">Сектор C</text>
        <text x={CX}       y={CY + 148} textAnchor="middle" fill="#94A3B8" fontSize="9" fontWeight="500">Сектор B</text>
        <text x={CX - 162} y={CY + 5}   textAnchor="middle" fill="#94A3B8" fontSize="9" fontWeight="500">VIP</text>
        <text x={CX + 162} y={CY + 5}   textAnchor="middle" fill="#94A3B8" fontSize="9" fontWeight="500">A2</text>

        {/* ── Seat dots ── */}
        {SEATS.map((seat) => {
          const effectiveStatus = localStatuses[seat.id] ?? seat.status;
          const isSelected = selectedIds.has(seat.id);
          const isPending = pendingId === seat.id;
          const isClickable = effectiveStatus === "AVAILABLE" && !isSelected && pendingId === null;
          const r = seat.type === "VIP" ? 5 : 4.2;

          return (
            <circle
              key={seat.id}
              cx={seat.x}
              cy={seat.y}
              r={r}
              fill={isPending ? "#94A3B8" : seatFill(seat, effectiveStatus, isSelected)}
              stroke={isPending ? "#CBD5E1" : seatStroke(seat, effectiveStatus, isSelected)}
              strokeWidth={isSelected ? 1.5 : isPending ? 1.2 : 0.8}
              opacity={effectiveStatus === "SOLD" ? 0.45 : isPending ? 0.7 : 1}
              cursor={
                isPending ? "wait"
                : isClickable || isSelected ? "pointer"
                : "not-allowed"
              }
              className={isPending ? "animate-pulse" : undefined}
              filter={
                isSelected
                  ? "url(#glow-red)"
                  : effectiveStatus === "AVAILABLE" && !isPending
                  ? "url(#glow-soft)"
                  : undefined
              }
              onClick={() => { void handleSeatClick(seat); }}
              role={isClickable || isSelected ? "button" : undefined}
              aria-label={
                isClickable
                  ? `${seat.sector} Ряд ${seat.row} Место ${seat.number} — ${seat.price.toLocaleString("ru-RU")} ₽`
                  : undefined
              }
            >
              <title>
                {seat.sector} • Ряд {seat.row} • Место {seat.number}
                {isPending
                  ? " (обработка…)"
                  : effectiveStatus === "SOLD"
                  ? " (Занято)"
                  : effectiveStatus === "LOCKED"
                  ? " (Удержано)"
                  : ` — ${seat.price.toLocaleString("ru-RU")} ₽`}
              </title>
            </circle>
          );
        })}

        {/* Transparent overlay that blocks all SVG clicks while a request is in flight */}
        {pendingId !== null && (
          <rect
            x={0} y={0}
            width={400} height={384}
            fill="transparent"
            cursor="wait"
            style={{ pointerEvents: "all" }}
          />
        )}
      </svg>
    </div>
  );
}
