import mongoose, { ConnectOptions } from "mongoose";
import Repository from "../core/Repository";
import config from "../config";
import AnonymizedRepositoryModel from "../core/model/anonymizedRepositories/anonymizedRepositories.model";
import AnonymousError from "../core/AnonymousError";
import AnonymizedPullRequestModel from "../core/model/anonymizedPullRequests/anonymizedPullRequests.model";
import PullRequest from "../core/PullRequest";
import AnonymizedGistModel from "../core/model/anonymizedGists/anonymizedGists.model";
import Gist from "../core/Gist";

export function getMongoUrl(): string {
  return (
    config.MONGODB_URI ||
    `mongodb://${config.DB_USERNAME}:${config.DB_PASSWORD}@${config.DB_HOSTNAME}:27017/production`
  );
}

export const database = mongoose.connection;

export let isConnected = false;

export async function connect() {
  mongoose.set("strictQuery", false);
  const options: ConnectOptions = {
    appName: "Anonymous GitHub Server",
    compressors: "zstd",
  };
  if (!config.MONGODB_URI) options.authSource = "admin";
  await mongoose.connect(getMongoUrl(), options);
  isConnected = true;

  return database;
}

export async function getRepository(repoId: string, _opts: {} = {}) {
  if (!repoId || repoId == "undefined") {
    throw new AnonymousError("repo_not_found", {
      object: repoId,
      httpStatus: 404,
    });
  }
  const data = await AnonymizedRepositoryModel.findOne({ repoId }).collation({
    locale: "en",
    strength: 2,
  });
  if (!data)
    throw new AnonymousError("repo_not_found", {
      object: repoId,
      httpStatus: 404,
    });
  return new Repository(data);
}
export async function getPullRequest(pullRequestId: string) {
  if (!pullRequestId || pullRequestId == "undefined") {
    throw new AnonymousError("pull_request_not_found", {
      object: pullRequestId,
      httpStatus: 404,
    });
  }
  const data = await AnonymizedPullRequestModel.findOne({
    pullRequestId,
  });
  if (!data)
    throw new AnonymousError("pull_request_not_found", {
      object: pullRequestId,
      httpStatus: 404,
    });
  return new PullRequest(data);
}
export async function getGist(gistId: string) {
  if (!gistId || gistId == "undefined") {
    throw new AnonymousError("gist_not_found", {
      object: gistId,
      httpStatus: 404,
    });
  }
  const data = await AnonymizedGistModel.findOne({
    gistId,
  });
  if (!data)
    throw new AnonymousError("gist_not_found", {
      object: gistId,
      httpStatus: 404,
    });
  return new Gist(data);
}
