package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"sec-cycle-scan/common"
	"sec-cycle-scan/model"
	"sec-cycle-scan/utils"
	"time"
)

func GetRepoList(organization string, repoCount int) ([]model.RepoResp, error) {

	var res []model.RepoResp

	if repoCount == 0 {
		return res, nil
	}

	hc := &utils.HConfig{
		Timeout: 10 * time.Second,
	}
	httpClient := hc.NewHTTPClient()

	pageSize := 100
	total := repoCount/pageSize + 1

	for i := 1; i <= total; i++ {
		// 构建请求 URL
		url := fmt.Sprintf("https://api.github.com/orgs/%s/repos?page=%d&per_page=%d", organization, i, pageSize)
		headers := make(map[string]string)

		token := common.CONFIG.System.GitToken
		headers["Authorization"] = "Bearer " + token
		headers["Accept"] = "application/vnd.github+json"
		resp, err := httpClient.Get(url, headers)
		if err != nil {
			return res, err
		}

		var repos []model.RepoResp

		if err = json.Unmarshal(resp, &repos); err != nil {
			return res, err
		}
		res = append(res, repos...)
	}

	return res, nil
}

func GetRepoCount(organization string) (int, error) {

	hc := &utils.HConfig{
		Timeout: 10 * time.Second,
	}
	httpClient := hc.NewHTTPClient()

	// 构建请求 URL
	url := fmt.Sprintf("https://api.github.com/orgs/%s", organization)
	headers := make(map[string]string)

	token := common.CONFIG.System.GitToken
	
	headers["Authorization"] = "Bearer " + token
	headers["Accept"] = "application/vnd.github+json"
	resp, err := httpClient.Get(url, headers)
	if err != nil {
		return 0, err
	}

	var r model.RepoCountResp
	if err = json.Unmarshal(resp, &r); err != nil {
		return 0, err
	}

	return r.PublicRepos + r.TotalPrivateRepos, nil
}

func GitDownload(repoLink string, branch string, dir string) error {
	//_ = utils.ClearDirectory(dir)
	gitDir := dir + "/" + ".git"
	exists := directoryExists(gitDir)
	if exists {
		if err := GitPull(repoLink, dir); err != nil {
			return err
		}
		return nil
	} else {
		_ = createDirectory(dir)
	}

	timeOut := 15 * 60 * 1000
	//env := append(os.Environ(),
	//	fmt.Sprintf("GIT_ASKPASS=%s", os.DevNull),
	//	fmt.Sprintf("GIT_TERMINAL_PROMPT=1"),
	//	fmt.Sprintf("GIT_TOKEN=%s", common.CONFIG.System.GitToken),
	//)

	var env []string

	args := []string{"clone", "-b", branch, repoLink, dir}

	exitCode, _, stderr, killed := utils.RunCommandWithTimeout(timeOut, dir, "git", env, args...)

	if killed || exitCode != 0 {
		return errors.New(fmt.Sprintf("Failed to pull code from Git. repo: %s  err: %s exitCode: %d ", repoLink, stderr, exitCode))
	}

	return nil
}

func GitPull(repoLink string, dir string) error {
	_ = utils.ClearDirectory(dir)
	timeOut := 10 * 60 * 1000
	//env := append(os.Environ(),
	//	fmt.Sprintf("GIT_ASKPASS=%s", os.DevNull),
	//	fmt.Sprintf("GIT_TERMINAL_PROMPT=1"),
	//	fmt.Sprintf("GIT_TOKEN=%s", common.CONFIG.System.GitToken),
	//)
	var env []string

	args := []string{"pull"}

	exitCode, _, stderr, killed := utils.RunCommandWithTimeout(timeOut, dir, "git", env, args...)

	if killed || exitCode != 0 {
		return errors.New(fmt.Sprintf("Git Pull command fails to execute. repo: %s  err: %s exitCode: %d ", repoLink, stderr, exitCode))
	}

	return nil
}

func directoryExists(dirPath string) bool {
	_, err := os.Stat(dirPath)
	if os.IsNotExist(err) {
		return false
	}
	return true
}

func createDirectory(dirPath string) error {
	err := os.MkdirAll(dirPath, 0755) // 设置目录权限，0755 表示 rwxr-xr-x
	if err != nil {
		return err
	}
	return nil
}
