"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { createClient, getBrowserUser } from "@/lib/supabase/client";
import type {
  Profile,
  ProjectGuest,
  ProjectGuestInvitation,
  ProjectGuestRole,
} from "@/types";

export function useProjectGuests(projectId?: string | null) {
  const [guests, setGuests] = useState<ProjectGuest[]>([]);
  const [invitations, setInvitations] = useState<ProjectGuestInvitation[]>([]);
  const [loading, setLoading] = useState(true);
  const [userId, setUserId] = useState<string | null>(null);
  const [userEmail, setUserEmail] = useState<string | null>(null);
  const supabase = createClient();

  useEffect(() => {
    void getBrowserUser()
      .then((user) => {
        setUserId(user?.id ?? null);
        setUserEmail(user?.email?.toLowerCase() ?? null);
      })
      .catch(() => {
        setUserId(null);
        setUserEmail(null);
      });
  }, []);

  const fetchGuests = useCallback(async () => {
    if (!projectId) {
      setGuests([]);
      setInvitations([]);
      setLoading(false);
      return;
    }

    setLoading(true);

    const [guestsRes, invitationsRes] = await Promise.all([
      supabase
        .from("project_guests")
        .select("*")
        .eq("project_id", projectId)
        .order("joined_at", { ascending: false }),
      supabase
        .from("project_guest_invitations")
        .select("*")
        .eq("project_id", projectId)
        .order("created_at", { ascending: false }),
    ]);

    const rawGuests = (guestsRes.data || []) as ProjectGuest[];
    const rawInvitations = (invitationsRes.data || []) as ProjectGuestInvitation[];

    let profilesById = new Map<string, Profile>();
    if (rawGuests.length > 0) {
      const profileIds = rawGuests.map((guest) => guest.user_id);
      const { data: profiles } = await supabase
        .from("profiles")
        .select("id, email, full_name, avatar_url, created_at, updated_at")
        .in("id", profileIds);

      profilesById = new Map(
        ((profiles || []) as Profile[]).map((profile) => [profile.id, profile])
      );
    }

    setGuests(
      rawGuests.map((guest) => ({
        ...guest,
        profile: profilesById.get(guest.user_id) || null,
      }))
    );
    setInvitations(rawInvitations);
    setLoading(false);
  }, [projectId, supabase]);

  useEffect(() => {
    const timer = window.setTimeout(() => {
      void fetchGuests();
    }, 0);

    return () => window.clearTimeout(timer);
  }, [fetchGuests]);

  const currentGuestRole = useMemo<ProjectGuestRole | null>(() => {
    if (!userId) return null;
    return guests.find((guest) => guest.user_id === userId)?.role || null;
  }, [guests, userId]);

  const incomingInvitation = useMemo(
    () =>
      userEmail
        ? invitations.find(
            (invitation) =>
              invitation.status === "pending" &&
              invitation.email.toLowerCase() === userEmail
          ) || null
        : null,
    [invitations, userEmail]
  );

  async function inviteGuest(input: {
    email: string;
    role: ProjectGuestRole;
    message?: string;
  }) {
    if (!projectId) throw new Error("Project missing");

    const res = await fetch("/api/projects/guests/invitations", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        projectId,
        email: input.email,
        role: input.role,
        message: input.message || "",
      }),
    });

    const payload = await res.json();
    if (!res.ok) {
      throw new Error(payload.error || "Invitation could not be created");
    }

    await fetchGuests();
    return payload as {
      invitation: ProjectGuestInvitation;
      inviteUrl: string;
      delivery: "email_sent" | "stored_only";
    };
  }

  async function revokeInvitation(invitationId: string) {
    const { error } = await supabase
      .from("project_guest_invitations")
      .update({ status: "revoked" })
      .eq("id", invitationId);

    if (error) throw error;
    await fetchGuests();
  }

  async function removeGuest(guestUserId: string) {
    const { error } = await supabase
      .from("project_guests")
      .delete()
      .eq("project_id", projectId)
      .eq("user_id", guestUserId);

    if (error) throw error;
    await fetchGuests();
  }

  return {
    guests,
    invitations,
    loading,
    userId,
    userEmail,
    currentGuestRole,
    incomingInvitation,
    inviteGuest,
    revokeInvitation,
    removeGuest,
    refetch: fetchGuests,
  };
}
