package scoresaber

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"strconv"
	"time"

	"git.lxtend.com/lixiangwuxian/qqbot/sqlite3"
	"git.lxtend.com/lixiangwuxian/qqbot/util"
	_ "github.com/mattn/go-sqlite3"
)

func init() {
	createBindTableSQL := `CREATE TABLE IF NOT EXISTS ssBind (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        qqid TEXT UNIQUE,
		ssid TEXT UNIQUE
    );`

	createScoreTableSQL := `CREATE TABLE IF NOT EXISTS ssData (
		id TEXT,
		name TEXT,
		country TEXT,
		pp REAL,
		rank INTEGER,
		country_rank INTEGER,
		total_score INTEGER,
		total_ranked_score INTEGER,
		average_ranked_accuracy REAL,
		total_play_count INTEGER,
		ranked_play_count INTEGER,
		replays_watched INTEGER,
		generated_time TEXT
	);`

	createRecordTableSQL := `CREATE TABLE IF NOT EXISTS ssRecordData (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		score_id INT,
		ss_id TEXT,
		name TEXT,
		country TEXT,
		song_name VARCHAR(255),
		song_sub_name VARCHAR(255),
		song_author_name VARCHAR(255),
		song_hash VARCHAR(64),
		cover_image TEXT,
		difficulty_raw VARCHAR(100),
		pp REAL,
		stars REAL,
		weight REAL,
		modifiers VARCHAR(255),
		multiplier REAL,
		rank INT,
		bad_cuts INT,
		missed_notes INT,
		max_combo INT,
		score INT,
		max_score INT,
		full_combo BOOLEAN,
		device_hmd VARCHAR(100),
		device_controller_left VARCHAR(100),
		device_controller_right VARCHAR(100),
		generated_time TEXT
	);`

	sqlite3.TryCreateTable(createBindTableSQL)
	sqlite3.TryCreateTable(createScoreTableSQL)
	sqlite3.TryCreateTable(createRecordTableSQL)
}

var SSQuery = &ssQuery{}

type ssQuery struct {
}

func (ss *ssQuery) BindSS(qqId string, ssId string) (reply string) {
	tx, err := sqlite3.GetTran()
	if err != nil {
		log.Print(err)
	}
	defer tx.Rollback()
	// ssId为数字
	if _, isNum := strconv.Atoi(ssId); isNum != nil {
		return "ssId格式错误,应当为一串数字(是您的scoresaber主页链接中的末尾数字部分,一般和您的steamID相同)"
	}
	data, err := FetchPlayerData(ssId)
	if data.ID == "" {
		if err != nil {
			return "请求出错，报错如下，如果确定命令没问题可以重新试试:" + err.Error()
		}
		return "未找到玩家,请检查ID后重试"
	}
	//去重
	if rows, err := tx.Query("SELECT ssid FROM ssBind WHERE qqid = ?", qqId); err == nil {
		if rows.Next() {
			var currentSsId string
			err := rows.Scan(&currentSsId)
			if err != nil {
				log.Print(err)
			}
			rows.Close()
			// 获取当前绑定账号的信息
			if currentData, err := FetchPlayerData(currentSsId); err == nil && currentData.ID != "" {
				return fmt.Sprintf("您已绑定至ss账号：%s,请先输入\"解绑ss\"解绑", currentData.Name)
			}
			return "您已绑定过ss账号,请先输入\"解绑ss\"解绑"
		} else {
			rows.Close()
		}
	}
	// 检查是否已绑定
	if rows, err := tx.Query("SELECT * FROM ssBind WHERE ssid = ?", ssId); err == nil {
		if rows.Next() {
			return "该ss账号已绑定至其他用户"
		}
		rows.Close()
	}
	_, err = tx.Exec("INSERT INTO ssBind(qqid, ssid) VALUES(?, ?)", qqId, ssId)
	if err != nil {
		return "绑定失败"
	}
	err = tx.Commit()
	if err != nil {
		return "无法提交事务"
	}
	return "和用户名为 " + data.Name + " 的用户绑定成功，同时也绑定了您的beatleader账号。输入\"查ss\"查看个人数据"
}

func (ss *ssQuery) UnbindSS(qqId string) (reply string) {
	tx, err := sqlite3.GetTran()
	if err != nil {
		log.Print(err)
	}
	defer tx.Rollback()
	//是否已绑定
	if rows, err := tx.Query("SELECT * FROM ssBind WHERE qqid = ?", qqId); err == nil {
		if !rows.Next() {
			return "您未绑定ss账号，输入\"绑定ss [ssId]\"绑定"
		}
		rows.Close()
	}
	_, err = tx.Exec("DELETE FROM ssBind WHERE qqid = ?", qqId)
	if err != nil {
		return "解绑失败"
	}
	err = tx.Commit()
	if err != nil {
		return "无法提交事务"
	}
	return "解绑成功，重新绑定请输入\"绑定ss [ssId]\""
}

func (ss *ssQuery) GetScore(qqId string) (currentData *PlayerDataLite, lastData *PlayerDataLite, err error) {
	db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
	tx, err := db.Beginx()
	if err != nil {
		log.Print(err)
		return nil, nil, err
	}
	defer tx.Rollback()

	ssId, err := GetSSID(qqId)
	if err != nil {
		return nil, nil, err
	}

	// 查询玩家数据
	data, err := FetchPlayerData(ssId)
	if data == nil && err == nil {
		return nil, nil, errors.New("查询出错，服务器返回了空数据")
	}
	if err != nil {
		log.Print(err)
		return nil, nil, err
	}
	// 构建 PlayerDataLite 结构体
	dataLite := PlayerDataLite{
		ID:                    data.ID,
		Name:                  data.Name,
		ProfilePicture:        data.ProfilePicture,
		Country:               data.Country,
		PP:                    data.PP,
		Rank:                  data.Rank,
		CountryRank:           data.CountryRank,
		TotalScore:            data.ScoreStats.TotalScore,
		TotalRankedScore:      data.ScoreStats.TotalRankedScore,
		AverageRankedAccuracy: data.ScoreStats.AverageRankedAccuracy,
		TotalPlayCount:        data.ScoreStats.TotalPlayCount,
		RankedPlayCount:       data.ScoreStats.RankedPlayCount,
		ReplaysWatched:        data.ScoreStats.ReplaysWatched,
		GeneratedTime:         time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
	}

	// 查询最近的玩家数据
	var lastDataLite PlayerDataLite
	err = tx.Get(&lastDataLite, "SELECT * FROM ssData WHERE id = ? ORDER BY generated_time DESC LIMIT 1", dataLite.ID)
	if err != nil && err != sql.ErrNoRows {
		log.Print(err)
		return nil, nil, err
	}

	// 如果有新的数据，则插入
	if lastDataLite.IsDiffFrom(dataLite) {
		_, err = tx.NamedExec(`INSERT INTO ssData (id, name, country, pp, rank, country_rank, total_score, 
			total_ranked_score, average_ranked_accuracy, total_play_count, ranked_play_count, replays_watched, generated_time)
			VALUES (:id, :name, :country, :pp, :rank, :country_rank, :total_score, 
			:total_ranked_score, :average_ranked_accuracy, :total_play_count, :ranked_play_count, :replays_watched, :generated_time)`, dataLite)
		if err != nil {
			log.Print(err)
			return nil, nil, err
		}

		// 提交事务
		err = tx.Commit()
		if err != nil {
			log.Print(err)
			return nil, nil, err
		}

		// 返回差异信息
		return &dataLite, &lastDataLite, nil
	}

	// 如果没有新数据，直接提交事务
	err = tx.Commit()
	if err != nil {
		log.Print(err)
		return nil, nil, err
	}

	// 返回当前数据的字符串表示
	return &dataLite, nil, nil
}

func (ss *ssQuery) GetScoreWithoutUpdate(qqId string) (currentData *PlayerDataLite, err error) {
	// 查询玩家数据
	ssId, err := GetSSID(qqId)
	if err != nil {
		return nil, err
	}
	data, err := FetchPlayerData(ssId)
	if err != nil {
		return nil, errors.New("查询出错，报错如下" + err.Error())
	}
	if data.ID == "" {
		return nil, errors.New("未找到玩家,请检查ID后重试")
	}
	dataLite := data.ToDataLite()
	// 返回当前数据的字符串表示
	return &dataLite, nil
}

func (ss *ssQuery) SaveRecord(cmdData CommandData) {
	db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
	tx, err := db.Beginx()
	if err != nil {
		log.Print(err)
		return
	}
	defer tx.Rollback()

	// 创建 RecordDataLite 结构体实例
	dataLite := RecordDataLite{
		ScoreID:               cmdData.Score.ID,
		SsID:                  cmdData.Score.LeaderboardPlayerInfo.ID,
		Name:                  cmdData.Score.LeaderboardPlayerInfo.Name,
		Country:               cmdData.Score.LeaderboardPlayerInfo.Country,
		SongName:              cmdData.Leaderboard.SongName,
		SongSubName:           cmdData.Leaderboard.SongSubName,
		SongAuthorName:        cmdData.Leaderboard.SongAuthorName,
		SongHash:              cmdData.Leaderboard.SongHash,
		SongId:                "",
		CoverImage:            cmdData.Leaderboard.CoverImage,
		DifficultyRaw:         cmdData.Leaderboard.Difficulty.DifficultyRaw,
		Stars:                 cmdData.Leaderboard.Stars,
		PP:                    cmdData.Score.Pp,
		Weight:                cmdData.Score.Weight,
		Modifiers:             cmdData.Score.Modifiers,
		Multiplier:            cmdData.Score.Multiplier,
		Rank:                  cmdData.Score.Rank,
		BadCuts:               cmdData.Score.BadCuts,
		Score:                 cmdData.Score.ModifiedScore,
		MaxScore:              cmdData.Leaderboard.MaxScore,
		MissedNotes:           cmdData.Score.MissedNotes,
		MaxCombo:              cmdData.Score.MaxCombo,
		FullCombo:             cmdData.Score.FullCombo,
		DeviceHmd:             "",
		DeviceControllerLeft:  "",
		DeviceControllerRight: "",
		GeneratedTime:         time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
	}

	// 检查设备信息并设置
	if cmdData.Score.DeviceHmd != nil {
		dataLite.DeviceHmd = *cmdData.Score.DeviceHmd
	}
	if cmdData.Score.DeviceControllerLeft != nil {
		dataLite.DeviceControllerLeft = *cmdData.Score.DeviceControllerLeft
	}
	if cmdData.Score.DeviceControllerRight != nil {
		dataLite.DeviceControllerRight = *cmdData.Score.DeviceControllerRight
	}

	// 使用 NamedExec 插入数据
	_, err = tx.NamedExec(`INSERT INTO ssRecordData 
		(score_id, ss_id, name, country, song_name, song_sub_name, song_author_name, 
		song_hash, cover_image, difficulty_raw, pp, stars, weight, modifiers, 
		multiplier,rank, bad_cuts, missed_notes, max_combo, score, max_score, 
		full_combo, device_hmd, device_controller_left, device_controller_right, 
		generated_time) 
		VALUES (:score_id, :ss_id, :name, :country, :song_name, :song_sub_name, 
		:song_author_name, :song_hash, :cover_image, :difficulty_raw, :pp, :stars, 
		:weight, :modifiers, :multiplier, :rank,:bad_cuts, :missed_notes, :max_combo, 
		:score, :max_score, :full_combo, :device_hmd, :device_controller_left, 
		:device_controller_right, :generated_time)`, dataLite)
	if err != nil {
		log.Print(err)
		return
	}

	// 提交事务
	err = tx.Commit()
	if err != nil {
		log.Print(err)
	}
}

func (ss *ssQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) {
	ssId, err := GetSSID(qqId)
	if err != nil {
		return nil, err
	}

	playerData, err := FetchPlayerData(ssId)
	if err != nil {
		return nil, err
	}
	//一页8条，超过8条则取两页
	historyUrl := "https://scoresaber.com/api/player/%s/scores?page=%d&sort=recent"
	var response struct {
		Data []struct {
			Score       Score       `json:"score"`
			Leaderboard Leaderboard `json:"leaderboard"`
		} `json:"playerScores"`
	}
	records := make([]RecordDataLite, 0)
	for i := range (count-1)/8 + 1 {
		fullUrl := fmt.Sprintf(historyUrl, ssId, i+1)
		resp, err := http.Get(fullUrl)
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}
		err = json.Unmarshal(body, &response)
		if err != nil {
			return nil, err
		}
		scores := response.Data
		for _, score := range scores {
			if len(records) >= count {
				break
			}
			record := RecordDataLite{
				ScoreID:               score.Score.ID,
				SsID:                  ssId,
				Name:                  playerData.Name,
				Country:               playerData.Country,
				SongName:              score.Leaderboard.SongName,
				SongSubName:           score.Leaderboard.SongSubName,
				SongAuthorName:        score.Leaderboard.SongAuthorName,
				SongHash:              score.Leaderboard.SongHash,
				SongId:                "",
				CoverImage:            score.Leaderboard.CoverImage,
				DifficultyRaw:         score.Leaderboard.Difficulty.DifficultyRaw,
				Stars:                 score.Leaderboard.Stars,
				PP:                    score.Score.Pp,
				Weight:                score.Score.Weight,
				Modifiers:             score.Score.Modifiers,
				Multiplier:            score.Score.Multiplier,
				Rank:                  score.Score.Rank,
				BadCuts:               score.Score.BadCuts,
				Score:                 score.Score.ModifiedScore,
				MaxScore:              score.Leaderboard.MaxScore,
				FullCombo:             score.Score.FullCombo,
				DeviceHmd:             "",
				DeviceControllerLeft:  "",
				DeviceControllerRight: "",
				GeneratedTime:         score.Score.TimeSet.Format("2006-01-02 15:04:05.999999999-07:00"),
			}
			// 检查设备信息并设置
			if score.Score.DeviceHmd != nil {
				record.DeviceHmd = *score.Score.DeviceHmd
			}
			if score.Score.DeviceControllerLeft != nil {
				record.DeviceControllerLeft = *score.Score.DeviceControllerLeft
			}
			if score.Score.DeviceControllerRight != nil {
				record.DeviceControllerRight = *score.Score.DeviceControllerRight
			}
			records = append(records, record)
		}
	}
	// 获取歌曲ID
	hashs := make([]string, 0)
	for _, record := range records {
		hashs = append(hashs, record.SongHash)
	}
	hashToSongId, err := util.GetSongIdsByHash(hashs)
	if err != nil {
		return nil, err
	}
	for i := range records {
		records[i].SongId = hashToSongId[records[i].SongHash]
	}
	return records, nil
}
