import { logger } from "../logger/index.mjs";
import { getDBClient } from "../utils/mongoDB/connectDB.mjs";
import { configurationFilesCandidates } from "@intlayer/config";
import { ObjectId } from "mongodb";

//#region src/services/bitbucket.service.ts
const BITBUCKET_API_URL = "https://api.bitbucket.org/2.0";
const BITBUCKET_AUTH_URL = "https://bitbucket.org/site/oauth2";
/**
* Get Bitbucket (Atlassian) authorization URL for OAuth flow
*/
const getAuthorizationUrl = (redirectUri) => {
	const clientId = process.env.ATLASSIAN_CLIENT_ID;
	if (!clientId) throw new Error("Bitbucket/Atlassian Client ID is not configured");
	return `${BITBUCKET_AUTH_URL}/authorize?${new URLSearchParams({
		client_id: clientId,
		response_type: "code",
		state: "bitbucket_oauth"
	}).toString()}`;
};
/**
* Exchange Bitbucket authorization code for access token
*/
const exchangeCodeForToken = async (code) => {
	const clientId = process.env.ATLASSIAN_CLIENT_ID;
	const clientSecret = process.env.ATLASSIAN_CLIENT_SECRET;
	if (!clientId || !clientSecret) throw new Error("Bitbucket OAuth credentials are not configured");
	try {
		const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
		const response = await fetch(`${BITBUCKET_AUTH_URL}/access_token`, {
			method: "POST",
			headers: {
				"Content-Type": "application/x-www-form-urlencoded",
				Authorization: `Basic ${credentials}`
			},
			body: new URLSearchParams({
				grant_type: "authorization_code",
				code
			})
		});
		if (!response.ok) throw new Error(`Bitbucket token exchange failed: ${response.statusText}`);
		const data = await response.json();
		if (data.error) throw new Error(`Bitbucket token error: ${data.error_description}`);
		return data.access_token;
	} catch (error) {
		logger.error("Error exchanging Bitbucket code for token:", error);
		throw error;
	}
};
/**
* Get user's Bitbucket repositories
*/
const getUserRepositories = async (accessToken) => {
	try {
		const userResponse = await fetch(`${BITBUCKET_API_URL}/user`, { headers: {
			Authorization: `Bearer ${accessToken}`,
			Accept: "application/json"
		} });
		if (!userResponse.ok) throw new Error(`Failed to fetch Bitbucket user: ${userResponse.statusText}`);
		const reposResponse = await fetch(`${BITBUCKET_API_URL}/repositories?role=member&sort=-updated_on&pagelen=100`, { headers: {
			Authorization: `Bearer ${accessToken}`,
			Accept: "application/json"
		} });
		if (!reposResponse.ok) throw new Error(`Failed to fetch Bitbucket repositories: ${reposResponse.statusText}`);
		return (await reposResponse.json()).values || [];
	} catch (error) {
		logger.error("Error fetching Bitbucket repositories:", error);
		throw error;
	}
};
/**
* Check if valid intlayer configuration files exist in a Bitbucket repository (Recursively).
* Returns an array of file paths found.
*/
const checkIntlayerConfig = async (accessToken, workspace, repoSlug, branch = "main") => {
	try {
		const response = await fetch(`${BITBUCKET_API_URL}/repositories/${workspace}/${repoSlug}/src/${encodeURIComponent(branch)}/?max_depth=10&pagelen=10000`, { headers: {
			Authorization: `Bearer ${accessToken}`,
			Accept: "application/json"
		} });
		if (!response.ok) {
			if (response.status === 404) return [];
			throw new Error(`Failed to fetch repository tree: ${response.statusText}`);
		}
		return ((await response.json()).values || []).filter((item) => {
			if (item.type !== "commit_file") return false;
			return configurationFilesCandidates.some((candidate) => item.path.endsWith(candidate));
		}).map((item) => item.path);
	} catch (error) {
		if (error.status === 404) return [];
		logger.error("Error checking intlayer configuration on Bitbucket:", error);
		return [];
	}
};
/**
* Get repository file contents from Bitbucket and decode it
*/
const getRepositoryFileContents = async (accessToken, workspace, repoSlug, path, branch = "main") => {
	try {
		const response = await fetch(`${BITBUCKET_API_URL}/repositories/${workspace}/${repoSlug}/src/${encodeURIComponent(branch)}/${encodeURIComponent(path)}`, { headers: {
			Authorization: `Bearer ${accessToken}`,
			Accept: "application/json"
		} });
		if (!response.ok) {
			if (response.status === 404) return null;
			throw new Error(`Failed to fetch file contents: ${response.statusText}`);
		}
		return await response.text();
	} catch (error) {
		if (error.status === 404) return null;
		logger.error("Error fetching Bitbucket file contents:", error);
		throw error;
	}
};
/**
* Get Bitbucket access token from user's linked account (Atlassian)
*/
const getBitbucketTokenFromUser = async (userId) => {
	try {
		const db = getDBClient().db();
		let account = await db.collection("account").findOne({
			userId,
			providerId: "atlassian"
		});
		if (!account && ObjectId.isValid(userId)) account = await db.collection("account").findOne({
			userId: new ObjectId(userId),
			providerId: "atlassian"
		});
		if (!account) account = await db.collection("accounts").findOne({
			userId,
			providerId: "atlassian"
		});
		if (!account && ObjectId.isValid(userId)) account = await db.collection("accounts").findOne({
			userId: new ObjectId(userId),
			providerId: "atlassian"
		});
		if (!account) return null;
		return account.accessToken || account.access_token || null;
	} catch (error) {
		logger.error("Error retrieving Bitbucket token from DB:", error);
		return null;
	}
};
/**
* Check if a Bitbucket pipeline file exists
*/
const checkPipelineFileExists = async (accessToken, workspace, repoSlug, filename = "bitbucket-pipelines.yml", branch = "main") => {
	try {
		const response = await fetch(`${BITBUCKET_API_URL}/repositories/${workspace}/${repoSlug}/src/${encodeURIComponent(branch)}/${encodeURIComponent(filename)}`, { headers: {
			Authorization: `Bearer ${accessToken}`,
			Accept: "application/json"
		} });
		if (response.status === 404) return false;
		if (!response.ok) throw new Error(`Failed to check file existence: ${response.statusText}`);
		return true;
	} catch (error) {
		if (error.status === 404) return false;
		logger.error("Error checking pipeline file existence:", error);
		throw error;
	}
};
/**
* Create or update a Bitbucket pipeline file
* Note: Bitbucket API doesn't support direct file creation via API v2.0
* This function returns false for allowAutoPush, requiring manual installation
*/
const createPipelineFile = async (accessToken, workspace, repoSlug, filename = "bitbucket-pipelines.yml", content, branch = "main", message = "Add Intlayer CI pipeline") => {
	throw new Error("Bitbucket API does not support automatic file creation. Please manually add the pipeline file to your repository.");
};

//#endregion
export { checkIntlayerConfig, checkPipelineFileExists, createPipelineFile, exchangeCodeForToken, getAuthorizationUrl, getBitbucketTokenFromUser, getRepositoryFileContents, getUserRepositories };
//# sourceMappingURL=bitbucket.service.mjs.map