"use client";

import { useCallback, useEffect, useState } from "react";
import { createClient, getBrowserUserId } from "@/lib/supabase/client";
import type { Project } from "@/types";
import { logProjectActivity } from "@/lib/project-activity";
import { logTeamAudit } from "@/lib/team-audit";
import { emitWebhookEvent } from "@/lib/developers/client";
import { useWorkspaceStore } from "@/stores/workspace-store";

export function useProjects() {
  const [projects, setProjects] = useState<Project[]>([]);
  const [loading, setLoading] = useState(true);
  const [userId, setUserId] = useState<string | null>(null);
  const supabase = createClient();
  const activeTeamId = useWorkspaceStore((state) => state.activeTeamId);
  const initialized = useWorkspaceStore((state) => state.initialized);

  useEffect(() => {
    void getBrowserUserId().then(setUserId).catch(() => setUserId(null));
  }, []);

  async function requireCurrentUserId() {
    const currentUserId = userId || (await getBrowserUserId());
    if (currentUserId && currentUserId !== userId) {
      setUserId(currentUserId);
    }
    return currentUserId;
  }

  async function createProjectApprovalNotification(input: {
    recipientId: string | null | undefined;
    actorId: string;
    teamId: string | null;
    projectId: string;
    title: string;
    body: string;
    details: Record<string, unknown>;
  }) {
    if (!input.recipientId || input.recipientId === input.actorId) return;

    const { error } = await supabase.from("notifications").insert({
      user_id: input.recipientId,
      actor_id: input.actorId,
      team_id: input.teamId,
      kind: "project_approval",
      title: input.title,
      body: input.body,
      link: `/projects/${input.projectId}`,
      details: {
        project_id: input.projectId,
        ...input.details,
      },
    });

    if (error) {
      console.error("Failed to create project approval notification", error);
    }
  }

  const fetchProjects = useCallback(async () => {
    if (!initialized) return;

    setLoading(true);

    let query = supabase
      .from("projects")
      .select("*")
      .order("sort_order")
      .order("created_at", { ascending: false });

    query = activeTeamId
      ? query.eq("team_id", activeTeamId)
      : query.is("team_id", null);

    const { data } = await query;

    setProjects(data || []);
    setLoading(false);
  }, [activeTeamId, initialized, supabase]);

  useEffect(() => {
    if (!initialized) return;

    async function loadProjects() {
      await fetchProjects();
    }
    void loadProjects();
  }, [fetchProjects, initialized]);

  async function createProject(input: {
    name: string;
    color: string;
    icon: string;
    description?: string;
    goal?: string;
    goal_id?: string | null;
    approver_id?: string | null;
    approval_status?: Project["approval_status"];
    approval_notes?: string;
    health?: "on_track" | "at_risk" | "stuck";
  }) {
    const currentUserId = await requireCurrentUserId();
    if (!currentUserId) throw new Error("Not authenticated");

    const { data, error } = await supabase
      .from("projects")
      .insert({ ...input, user_id: currentUserId, team_id: activeTeamId })
      .select()
      .single();
    if (error) throw error;

    if (data.approver_id && data.approval_status === "pending_approval") {
      await createProjectApprovalNotification({
        recipientId: data.approver_id,
        actorId: currentUserId,
        teamId: activeTeamId,
        projectId: data.id,
        title: `Approval requested for ${data.name}`,
        body:
          data.approval_notes ||
          "Please review this project and decide whether it is ready to move forward.",
        details: {
          approval_status: data.approval_status,
        },
      });
    }

    await logProjectActivity(supabase, {
      userId: currentUserId,
      projectId: data.id,
      entityType: "project",
      entityId: data.id,
      action: "project_created",
      title: data.name,
      details: {
        approval_status: data.approval_status,
        approver_id: data.approver_id,
      },
    });
    await logTeamAudit(supabase, {
      teamId: activeTeamId,
      actorId: currentUserId,
      action: "project_created",
      entityType: "project",
      entityId: data.id,
      title: data.name,
      details: {
        approval_status: data.approval_status,
        approver_id: data.approver_id,
      },
    });
    void emitWebhookEvent({
      teamId: activeTeamId,
      eventType: "project.created",
      data: {
        project: data,
      },
    });
    setProjects((prev) => [...prev, data]);
    return data as Project;
  }

  async function updateProject(
    id: string,
    input: Partial<{
      name: string;
      color: string;
      icon: string;
      description: string;
      goal: string;
      goal_id: string | null;
      approver_id: string | null;
      approval_status: Project["approval_status"];
      approval_requested_at: string | null;
      approved_at: string | null;
      approval_notes: string;
      health: "on_track" | "at_risk" | "stuck";
    }>
  ) {
    const currentUserId = await requireCurrentUserId();
    if (!currentUserId) throw new Error("Not authenticated");

    let existing = projects.find((project) => project.id === id) || null;
    if (!existing) {
      const { data: existingProject } = await supabase
        .from("projects")
        .select("*")
        .eq("id", id)
        .single();
      existing = (existingProject as Project | null) || null;
    }

    const nextApproverId =
      "approver_id" in input ? input.approver_id ?? null : existing?.approver_id ?? null;
    let nextApprovalStatus =
      typeof input.approval_status === "string"
        ? input.approval_status
        : existing?.approval_status || "not_required";
    const approvalUpdates: Partial<{
      approval_status: Project["approval_status"];
      approval_requested_at: string | null;
      approved_at: string | null;
      approval_notes: string;
    }> = {};

    if ("approver_id" in input && nextApproverId !== existing?.approver_id) {
      if (!nextApproverId) {
        nextApprovalStatus = "not_required";
        approvalUpdates.approval_status = "not_required";
        approvalUpdates.approval_requested_at = null;
        approvalUpdates.approved_at = null;
        approvalUpdates.approval_notes = "";
      } else if (input.approval_status === undefined) {
        nextApprovalStatus = "not_required";
        approvalUpdates.approval_status = "not_required";
        approvalUpdates.approval_requested_at = null;
        approvalUpdates.approved_at = null;
      }
    }

    if (!nextApproverId) {
      nextApprovalStatus = "not_required";
      approvalUpdates.approval_status = "not_required";
      approvalUpdates.approval_requested_at = null;
      approvalUpdates.approved_at = null;
    } else if (nextApprovalStatus === "pending_approval") {
      approvalUpdates.approval_status = nextApprovalStatus;
      approvalUpdates.approval_requested_at =
        existing?.approval_status !== "pending_approval"
          ? new Date().toISOString()
          : existing.approval_requested_at;
      approvalUpdates.approved_at = null;
    } else if (
      nextApprovalStatus === "approved" ||
      nextApprovalStatus === "changes_requested"
    ) {
      approvalUpdates.approval_status = nextApprovalStatus;
      approvalUpdates.approved_at = new Date().toISOString();
    } else {
      approvalUpdates.approval_status = "not_required";
      approvalUpdates.approval_requested_at = null;
      approvalUpdates.approved_at = null;
    }

    const nextInput = {
      ...input,
      ...approvalUpdates,
    };

    const { data, error } = await supabase
      .from("projects")
      .update(nextInput)
      .eq("id", id)
      .select()
      .single();
    if (error) throw error;

    const approvalAction =
      existing?.approval_status !== nextApprovalStatus && nextApprovalStatus
        ? nextApprovalStatus === "pending_approval"
          ? "project_approval_requested"
          : nextApprovalStatus === "approved"
          ? "project_approved"
          : nextApprovalStatus === "changes_requested"
          ? "project_changes_requested"
          : "project_updated"
        : null;
    const action = approvalAction || "project_updated";

    await logProjectActivity(supabase, {
      userId: currentUserId,
      projectId: id,
      entityType: "project",
      entityId: id,
      action,
      title: data.name,
      details:
        approvalAction
          ? {
              from_approval_status: existing?.approval_status,
              to_approval_status: nextApprovalStatus,
              approver_id: nextApproverId,
            }
          : nextInput,
    });
    await logTeamAudit(supabase, {
      teamId: activeTeamId,
      actorId: currentUserId,
      action,
      entityType: "project",
      entityId: id,
      title: data.name,
      details:
        approvalAction
          ? {
              from_approval_status: existing?.approval_status,
              to_approval_status: nextApprovalStatus,
              approver_id: nextApproverId,
            }
          : nextInput,
    });

    if (approvalAction === "project_approval_requested" && nextApproverId) {
      await createProjectApprovalNotification({
        recipientId: nextApproverId,
        actorId: currentUserId,
        teamId: activeTeamId,
        projectId: id,
        title: `Approval requested for ${data.name}`,
        body:
          (nextInput.approval_notes as string | undefined) ||
          "Please review this project and decide whether it is ready to move forward.",
        details: {
          approval_status: nextApprovalStatus,
        },
      });
    }

    if (
      (approvalAction === "project_approved" ||
        approvalAction === "project_changes_requested") &&
      existing
    ) {
      await createProjectApprovalNotification({
        recipientId: existing.user_id,
        actorId: currentUserId,
        teamId: activeTeamId,
        projectId: id,
        title:
          approvalAction === "project_approved"
            ? `Project approved: ${data.name}`
            : `Changes requested: ${data.name}`,
        body:
          (nextInput.approval_notes as string | undefined) ||
          (approvalAction === "project_approved"
            ? "Your project was approved."
            : "An approver requested changes before sign-off."),
        details: {
          approval_status: nextApprovalStatus,
          approver_id: nextApproverId,
        },
      });
    }

    void emitWebhookEvent({
      teamId: activeTeamId,
      eventType: "project.updated",
      data: {
        action,
        project: data,
        previous_project: existing,
      },
    });
    setProjects((prev) => prev.map((p) => (p.id === id ? data : p)));
    return data as Project;
  }

  async function deleteProject(id: string) {
    const currentUserId = await requireCurrentUserId();
    if (!currentUserId) throw new Error("Not authenticated");
    const existing = projects.find((project) => project.id === id);
    const { error } = await supabase.from("projects").delete().eq("id", id);
    if (error) throw error;
    await logProjectActivity(supabase, {
      userId: currentUserId,
      projectId: id,
      entityType: "project",
      entityId: id,
      action: "project_deleted",
      title: existing?.name || "Project deleted",
    });
    await logTeamAudit(supabase, {
      teamId: activeTeamId,
      actorId: currentUserId,
      action: "project_deleted",
      entityType: "project",
      entityId: id,
      title: existing?.name || "Project deleted",
    });
    void emitWebhookEvent({
      teamId: activeTeamId,
      eventType: "project.deleted",
      data: {
        project_id: id,
        project: existing || null,
      },
    });
    setProjects((prev) => prev.filter((p) => p.id !== id));
  }

  return { projects, loading, createProject, updateProject, deleteProject, refetch: fetchProjects };
}
