"use client";

import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from "react";
import Cookies from "js-cookie";
import { usePathname } from "next/navigation";
import { io, type Socket } from "socket.io-client";
import { useTenantClientWorkspace } from "@/features/client/use-tenant-client-workspace";
import { fetchWorkspaceComplaints } from "@/lib/complaints-api";
import { countUnread, loadSeenMap, saveSeenMap } from "@/lib/complaints-seen-storage";
import type { WorkspaceComplaint } from "@/lib/complaints-storage";

type Ctx = {
  /** Shared list — updates on socket `complaint:activity` and after mutations (all tabs stay in sync). */
  complaints: WorkspaceComplaint[];
  complaintsReady: boolean;
  unreadCount: number;
  markComplaintSeen: (complaintId: string, updatedAt: string) => void;
  refreshComplaints: () => Promise<void>;
};

const ComplaintsNotifyContext = createContext<Ctx>({
  complaints: [],
  complaintsReady: false,
  unreadCount: 0,
  markComplaintSeen: () => {},
  refreshComplaints: async () => {},
});

export function useComplaintsNotify() {
  return useContext(ComplaintsNotifyContext);
}

function isComplaintsListPath(pathname: string | null): boolean {
  if (!pathname) return false;
  const p = pathname.replace(/\/$/, "") || "/";
  return /\/(client|property)\/complaints$/.test(p);
}

export function ComplaintsNotifyProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  const ws = useTenantClientWorkspace();
  const clientKey = ws.effectiveClientKey;
  const tenantApiKey = ws.tenantApiKey;
  const tenantReady = ws.tenantReady;
  const userId = ws.me?._id ? String(ws.me._id) : "";

  const [complaints, setComplaints] = useState<WorkspaceComplaint[]>([]);
  const [complaintsReady, setComplaintsReady] = useState(false);
  const [seen, setSeen] = useState<Record<string, string>>({});

  useEffect(() => {
    if (!userId || !clientKey) return;
    setSeen(loadSeenMap(userId, clientKey));
  }, [userId, clientKey]);

  useEffect(() => {
    setComplaints([]);
    setComplaintsReady(false);
  }, [tenantApiKey]);

  const refreshComplaints = useCallback(async () => {
    if (!tenantReady || !tenantApiKey) return;
    try {
      const rows = await fetchWorkspaceComplaints(tenantApiKey);
      setComplaints(rows);
    } catch {
      setComplaints([]);
    } finally {
      setComplaintsReady(true);
    }
  }, [tenantReady, tenantApiKey]);

  useEffect(() => {
    void refreshComplaints();
  }, [refreshComplaints]);

  const markComplaintSeen = useCallback(
    (complaintId: string, updatedAt: string) => {
      if (!userId || !clientKey) return;
      setSeen((prev) => {
        const next = { ...prev, [complaintId]: updatedAt };
        saveSeenMap(userId, clientKey, next);
        return next;
      });
    },
    [userId, clientKey],
  );

  /** Opening the complaints page clears the sidebar indicator (all tickets considered seen). */
  useEffect(() => {
    if (!isComplaintsListPath(pathname) || !userId || !clientKey) return;
    if (complaints.length === 0) return;
    setSeen((prev) => {
      const next = { ...prev };
      for (const c of complaints) {
        next[c.id] = c.updatedAt;
      }
      saveSeenMap(userId, clientKey, next);
      return next;
    });
  }, [pathname, complaints, userId, clientKey]);

  useEffect(() => {
    if (!tenantReady || !clientKey || !userId) return;
    const apiUrl = process.env.NEXT_PUBLIC_API_URL || "";
    if (!apiUrl) return;

    const token = Cookies.get("token");
    if (!token) return;

    const socket: Socket = io(apiUrl, {
      path: "/socket.io",
      auth: { token },
      transports: ["websocket", "polling"],
    });

    const onConnect = () => {
      socket.emit("join-tenant", clientKey, (ack: { ok?: boolean; error?: string } | undefined) => {
        if (ack && ack.ok === false) {
          console.warn("join-tenant failed", ack.error);
        }
      });
    };

    socket.on("connect", onConnect);
    socket.on("complaint:activity", () => {
      void refreshComplaints();
    });

    return () => {
      socket.off("connect", onConnect);
      socket.removeAllListeners("complaint:activity");
      socket.disconnect();
    };
  }, [tenantReady, clientKey, userId, refreshComplaints]);

  const unreadCount = useMemo(
    () => countUnread(complaints, seen),
    [complaints, seen],
  );

  const value = useMemo(
    () => ({
      complaints,
      complaintsReady,
      unreadCount,
      markComplaintSeen,
      refreshComplaints,
    }),
    [complaints, complaintsReady, unreadCount, markComplaintSeen, refreshComplaints],
  );

  return (
    <ComplaintsNotifyContext.Provider value={value}>{children}</ComplaintsNotifyContext.Provider>
  );
}
