import { URLSearchParams } from 'url';
import axios, { AxiosInstance } from 'axios';
import { GitChangeType } from './common';
import { getExtensionContext } from './common/context';
import {
	IFileCommitResponse,
	ILineNoteForm,
	IListResponse,
	IMRCommentResp,
	IMRDetailMR,
	IMRDetailResponse,
} from './privateCodingApiType';

interface CommonResponse<T = Record<string, any>> {
	Response: {
		RequestId: string;
	} & T;
}

const getCodingDeployHost = (): string => getExtensionContext().globalState.get('codingDeployHost') || 'coding.net';

let CodingAPI: AxiosInstance;

let privateSessionInfo: {
	team: string;
	token: string;
	project?: string;
	depot?: string;
};

export const initCodingApi = ({
	teamName,
	token,
	project,
	depot,
}: {
	teamName: string;
	token: string;
	project?: string;
	depot?: string;
}) => {
	if (!!CodingAPI) return;

	CodingAPI = axios.create({
		baseURL: `https://${teamName}.${getCodingDeployHost()}`,
		timeout: 60000,
		headers: { Authorization: `${token}` },
	});

	privateSessionInfo = { team: teamName, token, project, depot };
};

const getApiPrefix = () => {
	const { team, project, depot } = privateSessionInfo;
	const projectApiPrefix = `https://${team}.${getCodingDeployHost()}/api/user/${team}/project/${project}`;
	return {
		projectApiPrefix,
		repoApiPrefix: `${projectApiPrefix}/depot/${depot}/git`,
	};
};

export const getCurrentUserInfo = () =>
	CodingAPI.post<{ id: number; name: string; avatar: string; global_key: string }>('api/me');

// 根据项目名称查询项目
export const describeProjectByName = async ({ projectName }: { projectName: string }) => {
	const res = await CodingAPI.post<
		CommonResponse<{
			Project: {
				Id: number;
				Name?: string;
				DisplayName?: string;
			};
		}>
	>('/open-api', {
		Action: 'DescribeProjectByName',
		ProjectName: projectName,
	});
	return res.data?.Response;
};

export const describeProjectDepotInfoList = async ({ projectId }: { projectId: number }) => {
	const res = await CodingAPI.post<
		CommonResponse<{
			DepotData: {
				Depots: {
					Name: string;
					HttpsUrl: string;
					SshUrl: string;
					WebUrl: string;
					Id: number;
					VcsType: 'git' | 'svn';
				}[];
			};
		}>
	>('/open-api', {
		Action: 'DescribeProjectDepotInfoList',
		ProjectId: projectId,
	});

	return res.data?.Response;
};

// 查询合并请求详情
export const describeMergeRequest = async ({ mergeId, depotId }: { mergeId: number; depotId: number }) => {
	const res = await CodingAPI.post<
		CommonResponse<{
			MergeRequestInfo: {
				Describe: string;
				Status: string;
				Title: string;
				TargetBranch: string;
				SourceBranch: string;
				CreatedAt: number;
				UpdatedAt: number;
			};
		}>
	>('/open-api', {
		Action: 'DescribeMergeRequest',
		MergeId: mergeId,
		DepotId: depotId,
	});

	return res.data.Response;
};

// 获取合并请求提交记录
export const describeMergeRequestCommits = async ({ mergeId, depotId }: { mergeId: number; depotId: number }) => {
	const res = await CodingAPI.post<CommonResponse>('/open-api', {
		Action: 'DescribeMergeRequestCommits',
		MergeId: mergeId,
		DepotId: depotId,
	});

	return res.data?.Response;
};

// 获取合并请求文件修改记录
export const mergeRequestFileDiff = async ({ mergeId, depotId }: { mergeId: number; depotId: number }) => {
	type MergeRequestFileDiffResponse = {
		MergeRequestFileDiff: {
			FileDiffs: {
				ChangeType: GitChangeType;
				Deletions: number;
				Insertions: number;
				ObjectId: string;
				Path: string;
			}[];
			Deletions: number;
			Insertions: number;
			OldSha: string;
			NewSha: string;
		};
	};

	const res = await CodingAPI.post<CommonResponse<MergeRequestFileDiffResponse>>('/open-api', {
		Action: 'DescribeMergeRequestFileDiff',
		MergeId: mergeId,
		depotId: depotId,
	});

	return res.data?.Response;
};

// 获取合并请求操作记录
export const describeMergeRequestLog = async ({ mergeId, depotId }: { mergeId: number; depotId: number }) => {
	type LogResponse = { Logs: { Id: number; Action: string; Name: string }[] };

	const res = await CodingAPI.post<CommonResponse<LogResponse>>('/open-api', {
		Action: 'DescribeMergeRequestLog',
		MergeId: mergeId,
		depotId: depotId,
	});

	return res.data?.Response;
};

interface ModifyMergeMrParams {
	depotId: number;
	mergeId: number;
	message?: string;
	isDelSourceBranch?: boolean;
	isFastForward?: boolean;
	squash?: boolean;
}

// 合入合并请求
export const modifyMergeMR = async ({
	mergeId,
	depotId,
	message = '',
	isDelSourceBranch = true,
	isFastForward = false,
	squash = false,
}: ModifyMergeMrParams) => {
	const res = await CodingAPI.post<CommonResponse>('/open-api', {
		Action: 'ModifyMergeMR',
		MergeId: mergeId,
		depotId: depotId,
		Message: message,
		IsDelSourceBranch: isDelSourceBranch,
		IsFastForward: isFastForward,
		Squash: squash,
	});

	return res.data?.Response;
};

// 关闭合并请求
export const modifyCloseMR = async ({ mergeId, depotId }: { mergeId: number; depotId: number }) => {
	const res = await CodingAPI.post<CommonResponse>('/open-api', {
		Action: 'ModifyCloseMR',
		DepotId: depotId,
		MergeId: mergeId,
	});

	return res.data?.Response;
};

// 查询某次提交的 diff 信息
export const describeGitCommitDiff = async ({
	depotId,
	commit,
	path,
}: {
	depotId: number;
	commit: string;
	path: string;
}) => {
	const res = await CodingAPI.post<
		CommonResponse<{
			Diffs: {
				Path: string;
				Content: string;
				Lines: { Index: number; LeftNo: number; Prefix: string; RightNo: number; Text: string }[];
				NewMode: string;
				OldMode: string;
				ChangeType: string;
				Insertions: number;
				Deletions: number;
			}[];
		}>
	>('/open-api', {
		Action: 'DescribeGitCommitDiff',
		DepotId: depotId,
		sha: commit,
		Path: path,
	});

	return res.data?.Response;
};

// 两次提交之间的文件差异
export const DescribeDifferentBetween2Commits = async ({
	depotId,
	source,
	target,
	path,
}: {
	depotId: number;
	source: string;
	target: string;
	path: string;
}) => {
	const res = await CodingAPI.post<
		CommonResponse<{
			DiffFileInfo: {
				DifferentLines: { Index: number; LeftNo: number; Prefix: string; RightNo: number; Text: string }[];
				Deletions: number;
				Insertions: number;
			};
		}>
	>('/open-api', {
		Action: 'DescribeDifferentBetween2Commits',
		DepotId: depotId,
		Source: source,
		Target: target,
		Path: path,
	});

	return res.data?.Response;
};

// 查询仓库默认分支
export const DescribeDepotDefaultBranch = async ({ team, project, depot }: { team: string, project: string, depot: string }) => {
	const res = await CodingAPI.post<CommonResponse<{ BranchName: string }>>('/open-api', {
		Action: 'DescribeDepotDefaultBranch',
		DepotPath: `${team}/${project}/${depot}`
	});

	return res.data?.Response;
};

// 获取 mr 评论信息，私有 API
export const _getMRComments = async ({ mergeId }: { mergeId: string | number }) => {
	try {
		const { repoApiPrefix } = getApiPrefix();

		const { data } = await CodingAPI.get<IMRCommentResp>(`${repoApiPrefix}/merge/${mergeId}/comments`);

		if (data.code) {
			return Promise.reject(data);
		}
		return data;
	} catch (err) {
		return Promise.reject(err);
	}
};

// 获取 mr 列表
export const _getMergeRequestList = async (params?: { page: number; status: string; PageSize: number }) => {
	const { status = 'open', page = 1, PageSize = 100 } = params ?? {};

	try {
		const { repoApiPrefix } = getApiPrefix();
		const { data } = await CodingAPI.get<IListResponse<IMRDetailMR>>(`${repoApiPrefix}/merges/query`, {
			params: {
				status,
				creators: '',
				mergers: '',
				reviewers: '',
				sort: 'action_at',
				labels: '',
				q: '',
				page,
				PageSize,
				sortDirection: 'DESC',
			},
		});
		return data;
	} catch (err) {
		return Promise.reject(err);
	}
};

export const _getMergeRequestInfo = async ({ mergeId }: { mergeId: number | string }) => {
	try {
		const { repoApiPrefix } = getApiPrefix();
		const { data } = await CodingAPI.get<IMRDetailResponse>(`${repoApiPrefix}/merge/${mergeId}/detail`);
		return data;
	} catch (err) {
		return Promise.reject(err);
	}
};

// 查询 文件 commit 信息
export const _getFileCommitDetail = async ({ file, commit }: { file: string; commit: string }) => {
	try {
		const { repoApiPrefix } = getApiPrefix();
		const { data } = await CodingAPI.get<IFileCommitResponse>(`${repoApiPrefix}/blob/${commit}/${file}`);
		return data;
	} catch (err) {
		return Promise.reject(err);
	}
};

// 回复评论
export const _postLineNote = async (params: ILineNoteForm) => {
	try {
		const { repoApiPrefix } = getApiPrefix();
		const { line } = params;
		const requestParams = { ...params, line_interval: `${line}-${line}` };
		// FIXME noteable_id
		// eslint-disable-next-line @typescript-eslint/ban-ts-comment
		// @ts-ignore
		const res = await CodingAPI.post(`${repoApiPrefix}/line_notes`, new URLSearchParams(requestParams));

		if (res.data.code) {
			return Promise.reject(res.data);
		}
		return res.data;
	} catch (e) {
		return Promise.reject(e);
	}
};
