package steamplaying

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"sync"
	"time"

	"git.lxtend.com/lixiangwuxian/qqbot/config"
	"git.lxtend.com/lixiangwuxian/qqbot/sqlite3"
	"golang.org/x/net/proxy"
)

var SteamAPIKey = ""
var ProxyAddr = ""

func init() {
	SteamAPIKey = config.ConfigManager.GetConfig().SteamApiKey
	ProxyAddr = config.ConfigManager.GetConfig().Management.ProxyAddr
}

func init() {
	createSteamUserTable := `CREATE TABLE IF NOT EXISTS steam_user (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		qqid TEXT,
		steamid TEXT UNIQUE
		);`
	createSteamUserForGroupTable := `CREATE TABLE IF NOT EXISTS steam_user_for_group (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		group_id TEXT,
		steamid TEXT
		);`
	sqlite3.TryCreateTable(createSteamUserTable)
	sqlite3.TryCreateTable(createSteamUserForGroupTable)
}

func bindSteamUser(qqid int64, steamid string) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	var steamUser []SteamUser
	err = tx.Select(&steamUser, "SELECT * FROM steam_user WHERE qqid = ?", qqid)
	if err != nil {
		return err
	}
	if len(steamUser) > 0 {
		return errors.New("已绑定")
	}
	_, err = tx.Exec("INSERT INTO steam_user (qqid, steamid) VALUES (:qqid, :steamid)", qqid, steamid)
	if err != nil {
		return err
	}
	err = tx.Commit()
	if err != nil {
		return err
	}
	return nil
}

func unbindSteamUser(qqid int64) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	_, err = tx.Exec("DELETE FROM steam_user WHERE qqid = ?", qqid)
	if err != nil {
		return err
	}
	err = tx.Commit()
	if err != nil {
		return err
	}
	return nil
}

func bindUserInGroup(groupID int64, steamid string) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	var steamUser []SteamUserForGroup
	err = tx.Select(&steamUser, "SELECT * FROM steam_user_for_group WHERE group_id = ? AND steamid = ?", groupID, steamid)
	if err != nil {
		return err
	}
	if len(steamUser) > 0 {
		return errors.New("已绑定")
	}
	_, err = tx.Exec("INSERT INTO steam_user_for_group (group_id, steamid) VALUES (:group_id, :steamid)", groupID, steamid)
	if err != nil {
		return err
	}
	err = tx.Commit()
	if err != nil {
		return err
	}
	return nil
}

func unbindUserInGroup(groupID int64, steamid string) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	_, err = tx.Exec("DELETE FROM steam_user_for_group WHERE group_id = ? AND steamid = ?", groupID, steamid)
	if err != nil {
		return err
	}
	err = tx.Commit()
	if err != nil {
		return err
	}
	return nil
}

func unbindUserInAllGroup(steamid string) error {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	_, err = tx.Exec("DELETE FROM steam_user_for_group WHERE steamid = ?", steamid)
	if err != nil {
		return err
	}
	err = tx.Commit()
	if err != nil {
		return err
	}
	return nil
}

func getSteamUser(qqid int64) (SteamUser, error) {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return SteamUser{}, err
	}
	defer tx.Rollback()
	var steamUser []SteamUser
	err = tx.Select(&steamUser, "SELECT * FROM steam_user WHERE qqid = ?", qqid)
	if err != nil || len(steamUser) == 0 {
		return SteamUser{}, err
	}
	return steamUser[0], nil
}

func getSteamUsersInGroup(groupID int64) ([]SteamUserForGroup, error) {
	// allUserInGroup, err := action.
	tx, err := sqlite3.GetTran()
	if err != nil {
		return nil, err
	}
	defer tx.Rollback()
	var steamUsers []SteamUserForGroup
	err = tx.Select(&steamUsers, "SELECT * FROM steam_user_for_group WHERE group_id = ?", groupID)
	if err != nil {
		return nil, err
	}
	return steamUsers, nil
}

func checkSteamGameStatus(steamID []string) (string, error) {
	if len(steamID) == 0 {
		return "疑似没人在玩游戏", nil
	}
	var glbErr error
	var writeMutex sync.Mutex
	var Players []PlayerSummary
	var wg sync.WaitGroup
	for step := 0; step < len(steamID)/100+1; step++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			url := "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s"
			fullSteamID := ""
			for i := step * 100; i < (step+1)*100 && i < len(steamID); i++ {
				fullSteamID += steamID[i] + ","
			}
			fullSteamID = fullSteamID[:len(fullSteamID)-1]
			url = fmt.Sprintf(url, SteamAPIKey, fullSteamID)

			dialer, _ := proxy.SOCKS5("tcp", ProxyAddr, nil, proxy.Direct)
			httpTransport := &http.Transport{
				Dial: func(network, addr string) (net.Conn, error) {
					return dialer.Dial(network, addr)
				},
			}
			client := &http.Client{
				Transport: httpTransport,
				Timeout:   10 * time.Second, // 设置请求超时时间
			}
			var resp *http.Response
			maxRetry := 5
			for i := 0; i < maxRetry; i++ {
				glbErr = nil
				var err error
				resp, err = client.Get(url)
				if err != nil {
					if i == maxRetry-1 {
						glbErr = errors.New("Get方法请求Steam API失败")
						return
					}
					continue
				}
				break
			}

			defer resp.Body.Close()
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				glbErr = err
				return
			}
			var userResponse GetPlayerSummariesResponse
			if err := json.Unmarshal(body, &userResponse); err != nil {
				glbErr = err
				return
			}
			writeMutex.Lock()
			Players = append(Players, userResponse.Response.Players...)
			writeMutex.Unlock()
		}()
	}
	wg.Wait()
	if glbErr != nil {
		return "", glbErr
	}
	gameStatusList := ""
	for _, userState := range Players {
		if userState.ToGameStatus() != "" {
			gameStatusList += userState.ToGameStatus() + "\n"
		}
	}
	if gameStatusList != "" {
		gameStatusList = gameStatusList[:len(gameStatusList)-1]
	} else {
		gameStatusList = "疑似没有人在玩游戏"
	}
	return gameStatusList, nil
}

func checkDiffSteamGameStatus(steamID []string, lastTimeStat map[string]string) (map[string]string, []PlayerSummary, error) {
	if len(steamID) == 0 {
		return nil, nil, nil
	}
	var glbErr error
	var writeMutex sync.Mutex
	var Players []PlayerSummary
	var wg sync.WaitGroup
	for step := 0; step < len(steamID)/100+1; step++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			url := "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s"
			fullSteamID := ""
			for i := step * 100; i < (step+1)*100 && i < len(steamID); i++ {
				fullSteamID += steamID[i] + ","
			}
			fullSteamID = fullSteamID[:len(fullSteamID)-1]
			url = fmt.Sprintf(url, SteamAPIKey, fullSteamID)

			dialer, _ := proxy.SOCKS5("tcp", ProxyAddr, nil, proxy.Direct)
			httpTransport := &http.Transport{
				Dial: func(network, addr string) (net.Conn, error) {
					return dialer.Dial(network, addr)
				},
			}
			client := &http.Client{
				Transport: httpTransport,
				Timeout:   10 * time.Second, // 设置请求超时时间
			}
			var resp *http.Response
			maxRetry := 5
			for i := 0; i < maxRetry; i++ {
				glbErr = nil
				var err error
				resp, err = client.Get(url)
				if err != nil {
					if i == maxRetry-1 {
						glbErr = errors.New("Get方法请求Steam API失败")
						return
					}
					continue
				}
				break
			}

			defer resp.Body.Close()
			body, err := io.ReadAll(resp.Body)
			if err != nil {
				glbErr = err
				return
			}
			var userResponse GetPlayerSummariesResponse
			if err := json.Unmarshal(body, &userResponse); err != nil {
				glbErr = err
				return
			}
			writeMutex.Lock()
			Players = append(Players, userResponse.Response.Players...)
			writeMutex.Unlock()
		}()
	}
	wg.Wait()
	if glbErr != nil {
		return nil, nil, glbErr
	}
	gameStatusListStr := map[string]string{}
	currentGameStatus := map[string]string{} // 用于记录当前所有玩家的游戏状态

	for _, userState := range Players {
		if userState.GameID != "" {
			currentGameStatus[userState.SteamID] = userState.GameID
			// 只有当玩家的游戏状态发生变化时才添加到通知列表
			if lastGameID, exists := lastTimeStat[userState.SteamID]; !exists || lastGameID != userState.GameID {
				if userState.ToGameStatus() != "" {
					gameStatusListStr[userState.SteamID] = userState.ToGameStatus()
				}
			}
		}
	}
	return gameStatusListStr, Players, nil
}

func checkSteamIDValid(steamID string) (bool, error) {
	url := "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s"
	url = fmt.Sprintf(url, SteamAPIKey, steamID)
	dialer, _ := proxy.SOCKS5("tcp", ProxyAddr, nil, proxy.Direct)
	httpTransport := &http.Transport{
		Dial: func(network, addr string) (net.Conn, error) {
			return dialer.Dial(network, addr)
		},
	}
	client := &http.Client{
		Transport: httpTransport,
		Timeout:   10 * time.Second, // 设置请求超时时间
	}
	resp, err := client.Get(url)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return false, err
	}
	var userResponse GetPlayerSummariesResponse
	if err := json.Unmarshal(body, &userResponse); err != nil {
		return false, err
	}
	if len(userResponse.Response.Players) == 0 {
		return false, nil
	}
	return true, nil
}

func getAllGroupID() ([]int64, error) {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return nil, err
	}
	defer tx.Rollback()
	var groupIDs []int64
	err = tx.Select(&groupIDs, "SELECT DISTINCT group_id FROM steam_user_for_group")
	if err != nil {
		return nil, err
	}
	return groupIDs, nil
}

func getAllSteamID() ([]string, error) {
	tx, err := sqlite3.GetTran()
	if err != nil {
		return nil, err
	}
	defer tx.Rollback()
	var steamIDs []string
	err = tx.Select(&steamIDs, "SELECT steamid FROM steam_user")
	if err != nil {
		return nil, err
	}
	return steamIDs, nil
}
