"use client";

import { createContext, useContext, useState, useCallback } from "react";
import { toast } from "sonner";

import type { ProjectDTO } from "@/types/project";
import {
  createProject,
  renameProject as renameProjectAction,
  deleteProject as deleteProjectAction,
} from "@/lib/actions/projects";

interface ProjectsContextValue {
  projects: ProjectDTO[];
  addProject: (title: string) => Promise<ProjectDTO | undefined>;
  renameProject: (projectId: string, title: string) => Promise<void>;
  removeProject: (projectId: string) => Promise<boolean>;
}

const ProjectsContext = createContext<ProjectsContextValue | null>(null);

/**
 * Holds the signed-in user's project list, fetched once in the (app)
 * layout and kept live from there -- the sidebar's expandable "Projects"
 * section and the /projects page both read from this same instance, so
 * creating/renaming/deleting a project in one place shows up in the other
 * immediately, with no extra round-trip.
 */
export function ProjectsProvider({
  initialProjects,
  children,
}: {
  initialProjects: ProjectDTO[];
  children: React.ReactNode;
}) {
  const [projects, setProjects] = useState(initialProjects);

  const addProject = useCallback(async (title: string) => {
    try {
      const project = await createProject(title);
      setProjects((prev) => [...prev, project]);
      return project;
    } catch {
      toast.error("Couldn't create project. Try again.");
      return undefined;
    }
  }, []);

  const renameProject = useCallback(async (projectId: string, title: string) => {
    let prevState: ProjectDTO[] = [];
    setProjects((prev) => {
      prevState = prev;
      return prev.map((p) => (p.id === projectId ? { ...p, title } : p));
    });
    try {
      await renameProjectAction(projectId, title);
    } catch {
      setProjects(prevState);
      toast.error("Couldn't rename project. Try again.");
    }
  }, []);

  const removeProject = useCallback(async (projectId: string) => {
    let prevState: ProjectDTO[] = [];
    setProjects((prev) => {
      prevState = prev;
      return prev.filter((p) => p.id !== projectId);
    });
    const result = await deleteProjectAction(projectId);
    if (result?.error) {
      setProjects(prevState);
      toast.error(result.error);
      return false;
    }
    return true;
  }, []);

  return (
    <ProjectsContext.Provider value={{ projects, addProject, renameProject, removeProject }}>
      {children}
    </ProjectsContext.Provider>
  );
}

export function useProjects() {
  const ctx = useContext(ProjectsContext);
  if (!ctx) throw new Error("useProjects must be used within a ProjectsProvider");
  return ctx;
}
