package com.microservices.common.httpClient.domain;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.common.core.utils.html.EscapeUtil;
import lombok.Data;
import org.apache.http.client.utils.URIBuilder;

import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author otto
 */
@Data
public class GitLinkRequestUrl {
    private String path;
    private Boolean isOpen;
    private Boolean isAdmin;
    private String resultKey;

    protected static GitLinkRequestUrl getGitLinkRequestUrl(boolean isOpen, String path, String resultKey) {
        GitLinkRequestUrl gitLinkRequestUrl = new GitLinkRequestUrl();
        gitLinkRequestUrl.setIsOpen(isOpen);
        gitLinkRequestUrl.setIsAdmin(false);
        gitLinkRequestUrl.setPath(path);
        gitLinkRequestUrl.setResultKey(resultKey);
        return gitLinkRequestUrl;
    }

    public static GitLinkRequestUrl UPLOAD_ATTACHMENTS() {
        return getGitLinkRequestUrl("/api/attachments.json");
    }

    public static GitLinkRequestUrl DELETE_ATTACHMENTS(Object fileIdentifier) {
        String path = String.format("/api/attachments/%s.json", fileIdentifier);
        return getGitLinkRequestUrl(path);
    }

    protected static GitLinkRequestUrl getAdminGitLinkRequestUrl(String path) {
        GitLinkRequestUrl gitLinkRequestUrl = new GitLinkRequestUrl();
        gitLinkRequestUrl.setIsOpen(false);
        gitLinkRequestUrl.setIsAdmin(true);
        gitLinkRequestUrl.setPath(path);
        return gitLinkRequestUrl;
    }

    protected static GitLinkRequestUrl getGitLinkRequestUrl(String path) {
        return getGitLinkRequestUrl(false, path, null);
    }

    public static String GET_ATTACHMENTS(String gitlinkUrl, String fileId) {
        return EscapeUtil.removeExtraSlashOfUrl(String.format("%s/api/attachments/%s", gitlinkUrl, fileId));
    }

    public static GitLinkRequestUrl GET_LIST_BY_PAGES(String url, Integer page, Integer limit) {
        return getAdminGitLinkRequestUrl(String.format("%s?page=%d&limit=%d", url, page, limit));
    }

    /**
     * 获取用户信息
     */
    public static GitLinkRequestUrl USER(String username) {
        return getOpenGitLinkRequestUrl(String.format("/api/users/%s.json", username));
    }

    /**
     * 获取TOKEN
     */
    public static GitLinkRequestUrl GET_TOKEN() {
        return getOpenGitLinkRequestUrl("/oauth/token");
    }


    protected static GitLinkRequestUrl getGitLinkRequestUrl(String path, String resultKey) {
        return getGitLinkRequestUrl(false, path, resultKey);
    }

    protected static GitLinkRequestUrl getOpenGitLinkRequestUrl(String path) {
        return getGitLinkRequestUrl(true, path, null);
    }

    protected static GitLinkRequestUrl getOpenGitLinkRequestUrl(String path, String resultKey) {
        return getGitLinkRequestUrl(true, path, resultKey);
    }

    public static String buildUri(String url, Map<String, String> params) throws URISyntaxException {
        return ConcatenateParametersAfterUrl(url, params);
    }

    public static String buildUri(String url, JSONObject paramsObj) throws URISyntaxException {
        Map<String, String> params = converJSONObjectToParamsMap(paramsObj);
        return ConcatenateParametersAfterUrl(url, params);
    }

    /**
     * 在url后拼接参数
     *
     * @param url    eg: gitlink.org.cn/api/v1
     * @param paramKey    eg: push_whitelist_usernames[]
     * @param params eg: ["a"，"b"]
     * @return String  eg: gitlink.org.cn/api/v1?push_whitelist_usernames[]=a&push_whitelist_usernames[]=b
     */
    public static String concatenateParametersAfterUrl(String url, String paramKey, List<String> params) {
        if (params == null || params.isEmpty()) {
            return url;
        }
        StringBuilder sb = new StringBuilder(url);

        if (!url.contains("?")) {
            sb.append("?");
        } else if (!url.endsWith("&")) {
            sb.append("&");
        }

        for (String username : params) {
            sb.append(paramKey).append("=").append(username).append("&");
        }

        // 判断最后一个字符是否为"&"
        if(sb.charAt(sb.length() - 1) == '&') {
            sb.deleteCharAt(sb.length() - 1);
        }

        return sb.toString();
    }

    /**
     * 搜索用户列表
     */
    public static GitLinkRequestUrl USERS(String query) {
        return getOpenGitLinkRequestUrl(String.format("/api/users/list.json%s", query));
    }

    public static GitLinkRequestUrl LOGIN() {
        return getOpenGitLinkRequestUrl("/api/accounts/login.json");
    }

    public static GitLinkRequestUrl CREATE_FILE(String repoOwner, String repoIdentifier) {
        return getGitLinkRequestUrl(
                String.format("/api/%s/%s/create_file.json", repoOwner, repoIdentifier)
        );
    }

    public static GitLinkRequestUrl UPDATE_FILE(String repoOwner, String repoIdentifier) {
        return getGitLinkRequestUrl(
                String.format("/api/%s/%s/update_file.json", repoOwner, repoIdentifier)
        );
    }

    public static GitLinkRequestUrl DELETE_FILE(String repoOwner, String repoIdentifier, String filepath, String sha, String branchName) {
        return getGitLinkRequestUrl(
                String.format("/api/%s/%s/delete_file.json?filepath=%s&sha=%s&branch=%s", repoOwner, repoIdentifier, URLEncoder.encode(filepath), sha, branchName)
        );
    }

    public static GitLinkRequestUrl GET_FILE_SUB_ENTRIES(String repoOwner, String repoIdentifier, String filepath, String ref) {
        return getGitLinkRequestUrl(
                String.format("/api/%s/%s/sub_entries.json?filepath=%s&ref=%s&type=%s", repoOwner, repoIdentifier, URLEncoder.encode(filepath), ref, "file")
        );
    }

    /**
     * 将JSONObject转为Map<String,String>
     */
    private static Map<String, String> converJSONObjectToParamsMap(JSONObject issueTagsSearchParams) {
        return JSON.parseObject(issueTagsSearchParams.toJSONString(), new TypeReference<Map<String, String>>() {
        });
    }

    /**
     * 在url后拼接参数
     */
    private static String ConcatenateParametersAfterUrl(String url, Map<String, String> params) throws URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(url);
        if (params != null) {
            Set<Map.Entry<String, String>> entrySet = params.entrySet();
            for (Map.Entry<String, String> entry : entrySet) {
                if (StringUtils.isNotEmpty(entry.getValue())) {
                    uriBuilder.addParameter(entry.getKey(), entry.getValue());
                }
            }
        }
        return uriBuilder.build().toString();
    }
}
