import { decryptSecret } from "@/lib/ai/crypto";
import type {
  GitHubConnectionConfig,
  GitHubRepository,
} from "@/types";

const GITHUB_API_BASE = "https://api.github.com";

interface GitHubUserResponse {
  login: string;
  html_url: string;
}

interface GitHubRepositoryResponse {
  id: number;
  name: string;
  full_name: string;
  html_url: string;
  private: boolean;
  default_branch: string | null;
  owner?: {
    login?: string;
  } | null;
}

interface GitHubIssueResponse {
  number: number;
  title: string;
  html_url: string;
  state: string;
}

async function githubRequest<T>(
  token: string,
  path: string,
  init?: RequestInit
): Promise<T> {
  const response = await fetch(`${GITHUB_API_BASE}${path}`, {
    ...init,
    headers: {
      Accept: "application/vnd.github+json",
      Authorization: `Bearer ${token}`,
      "User-Agent": "Mindavio-GitHub/1.0",
      "X-GitHub-Api-Version": "2022-11-28",
      ...(init?.headers || {}),
    },
    cache: "no-store",
  });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(errorText || "GitHub request failed");
  }

  return (await response.json()) as T;
}

export function parseGitHubConfig(config: Record<string, unknown>): GitHubConnectionConfig {
  return {
    connectedLogin: typeof config.connectedLogin === "string" ? config.connectedLogin : null,
    connectedUrl: typeof config.connectedUrl === "string" ? config.connectedUrl : null,
    repoOwner: typeof config.repoOwner === "string" ? config.repoOwner : null,
    repoName: typeof config.repoName === "string" ? config.repoName : null,
    repoFullName: typeof config.repoFullName === "string" ? config.repoFullName : null,
  };
}

export async function getGitHubViewer(token: string) {
  return githubRequest<GitHubUserResponse>(token, "/user");
}

export async function listGitHubRepositories(token: string): Promise<GitHubRepository[]> {
  const repos = await githubRequest<GitHubRepositoryResponse[]>(
    token,
    "/user/repos?per_page=100&sort=updated&affiliation=owner,collaborator,organization_member"
  );

  return repos.map((repo) => ({
    id: repo.id,
    name: repo.name,
    full_name: repo.full_name,
    owner_login: repo.owner?.login || repo.full_name.split("/")[0] || "",
    html_url: repo.html_url,
    private: repo.private,
    default_branch: repo.default_branch,
  }));
}

export async function createGitHubIssue(input: {
  token: string;
  owner: string;
  repo: string;
  title: string;
  body: string;
}) {
  return githubRequest<GitHubIssueResponse>(
    input.token,
    `/repos/${encodeURIComponent(input.owner)}/${encodeURIComponent(input.repo)}/issues`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: input.title,
        body: input.body,
      }),
    }
  );
}

export async function getGitHubIssue(input: {
  token: string;
  owner: string;
  repo: string;
  issueNumber: number;
}) {
  return githubRequest<GitHubIssueResponse>(
    input.token,
    `/repos/${encodeURIComponent(input.owner)}/${encodeURIComponent(input.repo)}/issues/${input.issueNumber}`
  );
}

export async function updateGitHubIssue(input: {
  token: string;
  owner: string;
  repo: string;
  issueNumber: number;
  state: "open" | "closed";
}) {
  return githubRequest<GitHubIssueResponse>(
    input.token,
    `/repos/${encodeURIComponent(input.owner)}/${encodeURIComponent(input.repo)}/issues/${input.issueNumber}`,
    {
      method: "PATCH",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        state: input.state,
      }),
    }
  );
}

export function decryptGitHubToken(secretEncrypted: string) {
  return decryptSecret(secretEncrypted);
}
