import axios from "axios";
import {
	GithubRepository,
	GithubRepositoriesSchema,
	DeployKeysSchema,
	ListWebhooksResponseSchema,
	DeployKeys,
} from "config";

export class GithubClient {
	private token: string;

	constructor(token: string) {
		this.token = token;
	}

	private getHeaders() {
		return {
			Authorization: `Bearer ${this.token}`,
			Accept: "application/vnd.github.v3+json",
			"X-GitHub-Api-Version": "2022-11-28",
		};
	}

	async getRepositories(): Promise<GithubRepository[]> {
		const response = await axios.get("https://api.github.com/user/repos", {
			headers: this.getHeaders(),
		});
		return GithubRepositoriesSchema.parse(response.data);
	}

	async addDeployKey(repoPath: string, key: string) {
		const sshUrl = repoPath;
		const repoOwnerAndName = sshUrl.replace("git@github.com:", "").replace(".git", "");
		let existingKeys: DeployKeys = [];
		const response = await axios.get(`https://api.github.com/repos/${repoOwnerAndName}/keys`, {
			headers: this.getHeaders(),
		});
		const parsedResult = DeployKeysSchema.safeParse(response.data);
		if (parsedResult.success) {
			existingKeys = parsedResult.data;
		} else {
			console.error("Failed to parse existing deploy keys:", parsedResult.error);
		}
		const keyToAddParts = key.trim().split(" ");
		const mainKeyPartToAdd = keyToAddParts.length > 1 ? keyToAddParts.slice(0, 2).join(" ") : key.trim();
		const keyAlreadyExists = existingKeys.some((existingKeyObj) => {
			const existingKeyParts = existingKeyObj.key.trim().split(" ");
			const mainExistingKeyPart =
				existingKeyParts.length > 1 ? existingKeyParts.slice(0, 2).join(" ") : existingKeyObj.key.trim();
			return mainExistingKeyPart === mainKeyPartToAdd;
		});
		if (keyAlreadyExists) {
			return;
		}
		await axios.post(
			`https://api.github.com/repos/${repoOwnerAndName}/keys`,
			{
				title: "dodo",
				key: key,
				read_only: true,
			},
			{
				headers: this.getHeaders(),
			},
		);
	}

	async removeDeployKey(repoPath: string, key: string) {
		const sshUrl = repoPath;
		const repoOwnerAndName = sshUrl.replace("git@github.com:", "").replace(".git", "");
		const response = await axios.get(`https://api.github.com/repos/${repoOwnerAndName}/keys`, {
			headers: this.getHeaders(),
		});
		const result = DeployKeysSchema.safeParse(response.data);
		if (!result.success) {
			console.error("Failed to parse deploy keys response for removal:", result.error);
			// Depending on desired robustness, you might throw an error or return early.
			// For now, if parsing fails, we can't identify keys to remove.
			throw new Error("Failed to parse deploy keys response during removal process");
		}

		// Extract the main part of the key we intend to remove
		const keyToRemoveParts = key.trim().split(" ");
		const mainKeyPartToRemove = keyToRemoveParts.length > 1 ? keyToRemoveParts.slice(0, 2).join(" ") : key.trim();

		const deployKeysToDelete = result.data.filter((existingKeyObj) => {
			const existingKeyParts = existingKeyObj.key.trim().split(" ");
			const mainExistingKeyPart =
				existingKeyParts.length > 1 ? existingKeyParts.slice(0, 2).join(" ") : existingKeyObj.key.trim();
			return mainExistingKeyPart === mainKeyPartToRemove;
		});

		if (deployKeysToDelete.length === 0) {
			console.log(
				`No deploy key matching '${mainKeyPartToRemove.substring(0, 50)}...' found in repo ${repoOwnerAndName} for removal.`,
			);
			return;
		}

		await Promise.all(
			deployKeysToDelete.map((deployKey) => {
				console.log(
					`Removing deploy key ID ${deployKey.id} ('${deployKey.key.substring(0, 50)}...') from repo ${repoOwnerAndName}`,
				);
				return axios.delete(`https://api.github.com/repos/${repoOwnerAndName}/keys/${deployKey.id}`, {
					headers: this.getHeaders(),
				});
			}),
		);
		console.log(
			`Successfully initiated removal of ${deployKeysToDelete.length} matching deploy key(s) from ${repoOwnerAndName}.`,
		);
	}

	async addPushWebhook(repoPath: string, callbackAddress: string): Promise<boolean> {
		const repoOwnerAndName = repoPath.replace("git@github.com:", "").replace(".git", "");
		const resp = await axios.post(
			`https://api.github.com/repos/${repoOwnerAndName}/hooks`,
			{
				name: "web",
				active: true,
				events: ["push"],
				config: {
					url: callbackAddress,
					content_type: "json",
				},
			},
			{
				headers: this.getHeaders(),
			},
		);
		return resp.status === 201;
	}

	async removePushWebhook(repoPath: string, callbackAddress: string): Promise<boolean> {
		const repoOwnerAndName = repoPath.replace("git@github.com:", "").replace(".git", "");
		const listHooksUrl = `https://api.github.com/repos/${repoOwnerAndName}/hooks`;
		try {
			const response = await axios.get(listHooksUrl, {
				headers: this.getHeaders(),
			});
			const parsedHooks = ListWebhooksResponseSchema.safeParse(response.data);
			if (!parsedHooks.success) {
				throw new Error(`Failed to parse webhooks list for ${repoOwnerAndName}`);
			}
			const results = await Promise.all(
				parsedHooks.data
					.filter((hook) => hook.config.url === callbackAddress && hook.events.includes("push"))
					.map(async (hook) => {
						const deleteHookUrl = `https://api.github.com/repos/${repoOwnerAndName}/hooks/${hook.id}`;
						const resp = await axios.delete(deleteHookUrl, { headers: this.getHeaders() });
						return resp.status === 204;
					}),
			);
			return results.reduce((acc, curr) => acc && curr, true);
			// eslint-disable-next-line @typescript-eslint/no-explicit-any
		} catch (error: any) {
			console.error(
				`Failed to list or remove webhooks for ${repoOwnerAndName}:`,
				error.response?.data || error.message,
			);
			throw error; // Re-throw to let the caller handle it
		}
	}
}
