package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

// 仓库配置
var repositories = []string{
	"https://www.sinxmiao.cn/taynpg/transm",
}

const downloadDir = "./downloads/" // 下载路径

// Release 结构体用于解析 API 返回的 JSON 数据
type Release struct {
	TagName   string  `json:"tag_name"`
	CreatedAt string  `json:"created_at"`
	Assets    []Asset `json:"assets"`
}

// Asset 结构体用于解析每个发行版的附件信息
type Asset struct {
	Name               string `json:"name"`
	BrowserDownloadURL string `json:"browser_download_url"`
}

func main() {
	// 选择仓库
	repo := chooseRepository(repositories)
	apiURL := convertToAPIURL(repo)

	// 获取所有版本信息
	releases, err := fetchReleases(apiURL)
	if err != nil {
		fmt.Printf("获取发行版信息失败: %v\n", err)
		return
	}

	// 打印版本信息并选择版本
	release := chooseRelease(releases)

	// 打印附件信息并选择附件
	asset := chooseAsset(release)

	// 创建下载目录
	if err := os.MkdirAll(downloadDir, os.ModePerm); err != nil {
		fmt.Printf("创建下载目录失败: %v\n", err)
		return
	}

	// 下载选择的附件
	fmt.Printf("开始下载: %s\n", asset.Name)
	if err := downloadFile(asset.BrowserDownloadURL, filepath.Join(downloadDir, asset.Name)); err != nil {
		fmt.Printf("下载失败: %v\n", err)
	} else {
		fmt.Printf("下载完成: %s\n", asset.Name)
	}
}

// chooseRepository 选择仓库
func chooseRepository(repositories []string) string {
	for {
		fmt.Println("可用的仓库:")
		for i, repo := range repositories {
			fmt.Printf("[%d] %s\n", i+1, repo[strings.LastIndex(repo, "/")+1:])
		}
		fmt.Print("请选择一个仓库 (输入编号): ")

		var choice int
		_, err := fmt.Scan(&choice)
		if err == nil && choice > 0 && choice <= len(repositories) {
			return repositories[choice-1]
		}
		fmt.Println("无效的选择,请重新输入。")
	}
}

// convertToAPIURL 将仓库链接转换为 API 地址
func convertToAPIURL(repo string) string {
	// 将仓库链接转换为 Gitea API 地址
	return strings.Replace(repo, "https://www.sinxmiao.cn", "https://www.sinxmiao.cn/api/v1/repos", 1) + "/releases"
}

// fetchReleases 获取所有版本信息
func fetchReleases(apiURL string) ([]Release, error) {
	resp, err := http.Get(apiURL)
	if err != nil {
		return nil, fmt.Errorf("请求 API 失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("API 响应状态码: %d", resp.StatusCode)
	}

	var releases []Release
	if err := json.NewDecoder(resp.Body).Decode(&releases); err != nil {
		return nil, fmt.Errorf("解析 JSON 失败: %v", err)
	}

	// 按创建时间排序
	sort.Slice(releases, func(i, j int) bool {
		return releases[i].CreatedAt < releases[j].CreatedAt
	})

	return releases, nil
}

// chooseRelease 打印版本信息并选择版本
func chooseRelease(releases []Release) *Release {
	for {
		fmt.Println("可用的版本:")
		for i, release := range releases {
			fmt.Printf("[%d] %s (%s)\n", i+1, release.TagName, release.CreatedAt)
		}
		fmt.Print("请选择一个版本 (输入编号): ")

		var choice int
		_, err := fmt.Scan(&choice)
		if err == nil && choice > 0 && choice <= len(releases) {
			return &releases[choice-1]
		}
		fmt.Println("无效的选择,请重新输入。")
	}
}

// chooseAsset 打印附件信息并选择附件
func chooseAsset(release *Release) *Asset {
	for {
		fmt.Println("可用的附件:")
		for i, asset := range release.Assets {
			fmt.Printf("[%d] %s\n", i+1, asset.Name)
		}
		fmt.Print("请选择一个附件 (输入编号): ")

		var choice int
		_, err := fmt.Scan(&choice)
		if err == nil && choice > 0 && choice <= len(release.Assets) {
			return &release.Assets[choice-1]
		}
		fmt.Println("无效的选择,请重新输入。")
	}
}

// downloadFile 下载文件到指定路径
func downloadFile(url, filePath string) error {
	resp, err := http.Get(url)
	if err != nil {
		return fmt.Errorf("请求下载链接失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("下载链接响应状态码: %d", resp.StatusCode)
	}

	// 创建文件
	out, err := os.Create(filePath)
	if err != nil {
		return fmt.Errorf("创建文件失败: %v", err)
	}
	defer out.Close()

	// 写入文件
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return fmt.Errorf("保存文件失败: %v", err)
	}

	return nil
}