import { apiClient } from "./client";

export interface GitRepository {
  id: string;
  name: string;
  path: string;
  project_id: string;
  owner_id: string;
  is_mirror: boolean;
  remote_url: string | null;
  ssh_key_id: string | null;
  last_push: string | null;
  created_at: string | null;
}

export interface GitRepositoryCreate {
  name: string;
  remote_url?: string;
  force_original_url?: boolean;
  ssh_key_id?: string;
}

export interface URLParseResult {
  original_url: string;
  base_url: string | null;
  is_valid_clone_url: boolean;
  needs_parsing: boolean;
  host: string | null;
  message: string;
  error_code: string | null;
}

export async function parseGitUrl(url: string): Promise<URLParseResult> {
  const response = await apiClient.post("/repositories/parse-url", { url });
  return response.data;
}

export async function listRepositories(projectId?: string): Promise<GitRepository[]> {
  if (projectId) {
    const response = await apiClient.get<GitRepository[]>(
      `/projects/${projectId}/repositories`
    );
    return response.data;
  }
  // List all user repositories (including external)
  const response = await apiClient.get<GitRepository[]>("/repositories");
  return response.data;
}

export async function listAllUserRepositories(): Promise<GitRepository[]> {
  const response = await apiClient.get<GitRepository[]>("/repositories");
  return response.data;
}

export async function createRepository(
  projectId: string,
  data: GitRepositoryCreate
): Promise<GitRepository> {
  const response = await apiClient.post(`/projects/${projectId}/repositories`, data);
  return response.data;
}

export async function createExternalRepository(
  data: GitRepositoryCreate
): Promise<GitRepository> {
  const response = await apiClient.post<GitRepository>("/repositories", data);
  return response.data;
}

export async function deleteRepository(projectId: string, repoId: string): Promise<void> {
  await apiClient.delete(`/projects/${projectId}/repositories/${repoId}`);
}

export async function updateRepositorySshKey(
  projectId: string,
  repoId: string,
  sshKeyId: string | null
): Promise<GitRepository> {
  const response = await apiClient.patch(
    `/projects/${projectId}/repositories/${repoId}/ssh-key`,
    { ssh_key_id: sshKeyId }
  );
  return response.data;
}

export interface Branch {
  name: string;
  is_default: boolean;
  last_commit: string | null;
}

export interface BranchesResponse {
  branches: Branch[];
  default_branch: string;
}

export async function listRepositoryBranches(
  projectId: string,
  repoId: string
): Promise<BranchesResponse> {
  const response = await apiClient.get(
    `/projects/${projectId}/repositories/${repoId}/branches`
  );
  return response.data;
}

export interface CommitHistoryEntry {
  hash: string;
  short_hash: string;
  message: string;
  author_name: string;
  author_email: string;
  author_date: string;
  refs: string[];
  graph_symbol: string;
  graph_depth: number;
}

export interface CommitHistoryResponse {
  commits: CommitHistoryEntry[];
  branches: string[];
  tags: string[];
}

export async function getRepositoryHistory(
  projectId: string,
  repoId: string,
  branch?: string,
  limit?: number
): Promise<CommitHistoryResponse> {
  const searchParams = new URLSearchParams();
  if (branch) searchParams.set("branch", branch);
  if (limit) searchParams.set("limit", String(limit));
  const queryString = searchParams.toString();
  const params = queryString ? `?${queryString}` : "";
  const response = await apiClient.get(`/projects/${projectId}/repositories/${repoId}/history${params}`);
  return response.data;
}

export interface CommitDetail {
  hash: string;
  short_hash: string;
  message: string;
  author_name: string;
  author_email: string;
  author_date: string;
  committer_name: string;
  committer_email: string;
  committer_date: string;
  stats: {
    additions: number;
    deletions: number;
    files_changed: number;
  };
  diff: string;
  parents: string[];
}

export async function getCommitDetail(
  projectId: string,
  repoId: string,
  commitHash: string
): Promise<CommitDetail> {
  const response = await apiClient.get(
    `/projects/${projectId}/repositories/${repoId}/commits/${commitHash}`
  );
  return response.data;
}

// Git Control API

export interface GitStatus {
  branch: string;
  modified: string[];
  added: string[];
  deleted: string[];
  untracked: string[];
  renamed: string[];
  ahead: number;
  behind: number;
}

export async function getRepositoryStatus(
  projectId: string,
  repoId: string
): Promise<GitStatus> {
  const response = await apiClient.get(
    `/projects/${projectId}/repositories/${repoId}/status`
  );
  return response.data;
}

export async function createBranch(
  projectId: string,
  repoId: string,
  name: string,
  baseBranch: string = "HEAD"
): Promise<{ message: string; branch: string }> {
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/branches`,
    { name, base_branch: baseBranch }
  );
  return response.data;
}

export async function deleteBranch(
  projectId: string,
  repoId: string,
  branchName: string,
  force: boolean = false
): Promise<{ message: string }> {
  const response = await apiClient.delete(
    `/projects/${projectId}/repositories/${repoId}/branches/${branchName}?force=${force}`
  );
  return response.data;
}

export async function checkoutBranch(
  projectId: string,
  repoId: string,
  branch: string
): Promise<{ message: string; branch: string }> {
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/checkout`,
    { branch }
  );
  return response.data;
}

export interface CommitResponse {
  commit_hash: string;
  message: string;
}

export async function commitChanges(
  projectId: string,
  repoId: string,
  message: string,
  files?: string[]
): Promise<CommitResponse> {
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/commit`,
    { message, files }
  );
  return response.data;
}

export async function fetchRepository(
  projectId: string,
  repoId: string
): Promise<{ message: string }> {
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/fetch`
  );
  return response.data;
}

export async function pullRepository(
  projectId: string,
  repoId: string,
  branch?: string
): Promise<{ message: string }> {
  const params = branch ? `?branch=${branch}` : "";
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/pull${params}`
  );
  return response.data;
}

export async function pushRepository(
  projectId: string,
  repoId: string,
  branch?: string
): Promise<{ message: string }> {
  const params = branch ? `?branch=${branch}` : "";
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/push${params}`
  );
  return response.data;
}

export interface MergeResponse {
  commit_hash: string;
  message: string;
}

export async function mergeBranches(
  projectId: string,
  repoId: string,
  sourceBranch: string,
  targetBranch?: string,
  message?: string
): Promise<MergeResponse> {
  const response = await apiClient.post(
    `/projects/${projectId}/repositories/${repoId}/merge`,
    { source_branch: sourceBranch, target_branch: targetBranch, message }
  );
  return response.data;
}
