import React, { useContext, useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import { gitIsStarred, gitIsWatched, projectRepos } from "@/client";
import { ProjectProvider } from "@/contexts";
import type { ProjectRepositoryItem } from "@/client";

/** Enriched repo info combining ProjectRepositoryItem with star/watch status */
export interface RepoInfo {
  /** Project namespace (= project_name) */
  namespace: string;
  /** Repository name */
  repo_name: string;
  /** Repository uid */
  uid: string;
  description?: string | null;
  default_branch: string;
  is_private: boolean;
  commit_count: number;
  branch_count: number;
  tag_count: number;
  star_count: number;
  watch_count: number;
  last_commit_at?: string | null;
  /** Whether the current user has starred this repo */
  is_star: boolean;
  /** Whether the current user is watching this repo */
  is_watch: boolean;
  /** SSH clone URL */
  ssh_clone_url: string;
  /** HTTPS clone URL */
  https_clone_url: string;
  /** Whether AI auto-review is enabled for this repo */
  ai_code_review_enabled: boolean;
}

export const RepositoryContext = React.createContext<RepoInfo | null>(null);

export const RepositoryContextProvider = ({
  children,
  namespace,
  repoName,
}: {
  children: React.ReactNode;
  namespace: string;
  repoName: string;
}) => {
  // Fetch the repo list for this project to get repo metadata
  const { data: reposData, isLoading: reposLoading } = useQuery({
    queryKey: ["projectRepos", namespace],
    queryFn: async () => {
      const resp = await projectRepos({ path: { project_name: namespace } });
      return resp.data?.data ?? null;
    },
    staleTime: 5 * 60 * 1000,
    enabled: !!namespace,
  });

  const repoItem = useMemo(
    () => reposData?.items?.find((r: ProjectRepositoryItem) => r.repo_name === repoName) ?? null,
    [reposData, repoName],
  ) as ProjectRepositoryItem | null;

  // Fetch star status
  const { data: starCountResp } = useQuery({
    queryKey: ["repoStar", namespace, repoName],
    queryFn: async () => {
      const resp = await gitIsStarred({ path: { namespace, repo: repoName } });
      return resp.data?.data;
    },
    staleTime: 30 * 1000,
    retry: false,
    enabled: !!namespace && !!repoName,
  });

  // Fetch watch status
  const { data: watchCountResp } = useQuery({
    queryKey: ["repoWatch", namespace, repoName],
    queryFn: async () => {
      const resp = await gitIsWatched({ path: { namespace, repo: repoName } });
      return resp.data?.data;
    },
    staleTime: 30 * 1000,
    retry: false,
    enabled: !!namespace && !!repoName,
  });

  const repo: RepoInfo | null = useMemo(() => {
    if (!repoItem) return null;
    return {
      namespace,
      repo_name: repoItem.repo_name,
      uid: repoItem.uid,
      description: repoItem.description,
      default_branch: repoItem.default_branch,
      is_private: repoItem.is_private,
      commit_count: repoItem.commit_count,
      branch_count: repoItem.branch_count,
      tag_count: repoItem.tag_count,
      star_count: repoItem.star_count,
      watch_count: repoItem.watch_count,
      last_commit_at: repoItem.last_commit_at,
      is_star: Boolean(starCountResp),
      is_watch: Boolean(watchCountResp),
      ssh_clone_url: repoItem.ssh_clone_url,
      https_clone_url: repoItem.https_clone_url,
      ai_code_review_enabled: repoItem.ai_code_review_enabled,
    };
  }, [repoItem, namespace, starCountResp, watchCountResp]);

  if (reposLoading) return null;

  return (
    <ProjectProvider projectName={namespace}>
      <RepositoryContext.Provider value={repo}>{children}</RepositoryContext.Provider>
    </ProjectProvider>
  );
};

export function useRepo(): RepoInfo {
  const ctx = useContext(RepositoryContext);
  if (!ctx) throw new Error("useRepo must be used within RepositoryContextProvider");
  return ctx;
}
