"use client";

import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";

interface ThreadTarget {
  channelId: string;
  parentId: string;
}

export interface AiSeed {
  context?: string;
  prompt?: string;
}

export type ModalKind = "create-channel" | "new-message" | "invite" | "channel-details" | "channel-members" | "create-workspace" | "callback" | "set-status" | "edit-profile";

export interface Toast {
  id: number;
  message: string;
  tone: "default" | "success" | "danger";
}

interface UiState {
  thread: ThreadTarget | null;
  openThread: (channelId: string, parentId: string) => void;
  closeThread: () => void;

  paletteOpen: boolean;
  setPaletteOpen: (v: boolean) => void;

  notifOpen: boolean;
  setNotifOpen: (v: boolean) => void;

  profileUserId: string | null;
  openProfile: (id: string) => void;
  closeProfile: () => void;

  themingOpen: boolean;
  setThemingOpen: (v: boolean) => void;

  huddleChannelId: string | null;
  startHuddle: (channelId: string) => void;
  endHuddle: () => void;

  aiPanel: AiSeed | null;
  openAi: (seed?: AiSeed) => void;
  closeAi: () => void;

  sidebarOpen: boolean;
  setSidebarOpen: (v: boolean) => void;

  // desktop sidebar collapse
  sidebarCollapsed: boolean;
  toggleSidebarCollapsed: () => void;

  // modals
  modal: ModalKind | null;
  modalArg?: string;
  openModal: (m: ModalKind, arg?: string) => void;
  closeModal: () => void;

  // toasts
  toasts: Toast[];
  toast: (message: string, tone?: Toast["tone"]) => void;
  dismissToast: (id: number) => void;
}

const Ctx = createContext<UiState | null>(null);

export function UiStateProvider({ children }: { children: React.ReactNode }) {
  const [thread, setThread] = useState<ThreadTarget | null>(null);
  const [paletteOpen, setPaletteOpen] = useState(false);
  const [notifOpen, setNotifOpen] = useState(false);
  const [profileUserId, setProfileUserId] = useState<string | null>(null);
  const [themingOpen, setThemingOpen] = useState(false);
  const [huddleChannelId, setHuddleChannelId] = useState<string | null>(null);
  const [aiPanel, setAiPanel] = useState<AiSeed | null>(null);
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const [modal, setModal] = useState<ModalKind | null>(null);
  const [modalArg, setModalArg] = useState<string | undefined>(undefined);
  const [toasts, setToasts] = useState<Toast[]>([]);
  const toastId = useRef(1);

  const openThread = useCallback((channelId: string, parentId: string) => setThread({ channelId, parentId }), []);
  const closeThread = useCallback(() => setThread(null), []);
  const openProfile = useCallback((id: string) => setProfileUserId(id), []);
  const closeProfile = useCallback(() => setProfileUserId(null), []);
  const startHuddle = useCallback((id: string) => setHuddleChannelId(id), []);
  const endHuddle = useCallback(() => setHuddleChannelId(null), []);
  const openAi = useCallback((seed?: AiSeed) => setAiPanel(seed ?? {}), []);
  const closeAi = useCallback(() => setAiPanel(null), []);
  const openModal = useCallback((m: ModalKind, arg?: string) => {
    setModal(m);
    setModalArg(arg);
  }, []);
  const closeModal = useCallback(() => {
    setModal(null);
    setModalArg(undefined);
  }, []);

  useEffect(() => {
    try {
      if (localStorage.getItem("lynkd.sidebarCollapsed") === "1") setSidebarCollapsed(true);
    } catch {
      /* ignore */
    }
  }, []);
  const toggleSidebarCollapsed = useCallback(() => {
    setSidebarCollapsed((v) => {
      const next = !v;
      try {
        localStorage.setItem("lynkd.sidebarCollapsed", next ? "1" : "0");
      } catch {
        /* ignore */
      }
      return next;
    });
  }, []);

  const dismissToast = useCallback((id: number) => setToasts((t) => t.filter((x) => x.id !== id)), []);
  const toast = useCallback((message: string, tone: Toast["tone"] = "default") => {
    const id = toastId.current++;
    setToasts((t) => [...t, { id, message, tone }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 3200);
  }, []);

  // ⌘/Ctrl+K opens palette; Escape closes the top-most open surface.
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setPaletteOpen((v) => !v);
        return;
      }
      if (e.key === "Escape") {
        // close the most transient surface first
        if (paletteOpen) return setPaletteOpen(false);
        if (modal) return closeModal();
        if (notifOpen) return setNotifOpen(false);
        if (profileUserId) return setProfileUserId(null);
        if (themingOpen) return setThemingOpen(false);
        if (aiPanel) return setAiPanel(null);
        if (thread) return setThread(null);
        if (sidebarOpen) return setSidebarOpen(false);
        if (huddleChannelId) return setHuddleChannelId(null);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [paletteOpen, modal, notifOpen, profileUserId, themingOpen, aiPanel, thread, sidebarOpen, huddleChannelId, closeModal]);

  const value = useMemo<UiState>(
    () => ({
      thread, openThread, closeThread,
      paletteOpen, setPaletteOpen,
      notifOpen, setNotifOpen,
      profileUserId, openProfile, closeProfile,
      themingOpen, setThemingOpen,
      huddleChannelId, startHuddle, endHuddle,
      aiPanel, openAi, closeAi,
      sidebarOpen, setSidebarOpen,
      sidebarCollapsed, toggleSidebarCollapsed,
      modal, modalArg, openModal, closeModal,
      toasts, toast, dismissToast,
    }),
    [thread, openThread, closeThread, paletteOpen, notifOpen, profileUserId, openProfile, closeProfile, themingOpen, huddleChannelId, startHuddle, endHuddle, aiPanel, openAi, closeAi, sidebarOpen, sidebarCollapsed, toggleSidebarCollapsed, modal, modalArg, openModal, closeModal, toasts, toast, dismissToast],
  );

  return <Ctx.Provider value={value}>{children}</Ctx.Provider>;
}

export function useUi(): UiState {
  const ctx = useContext(Ctx);
  if (!ctx) throw new Error("useUi must be used within <UiStateProvider>");
  return ctx;
}
