package gm_services

import (
	"bytes"
	"encoding/json"
	"fmt"
	"gadmin/config"
)

type ChapterInfo struct {
	UserId     int64  `json:"user_id" gorm:"column:user_id"` //用户id
	ChapterId  int32  `json:"chapter_id" gorm:"column:chapter_id"`
	Difficulty int32  `json:"difficulty" gorm:"column:difficulty"`       //困难度
	Pass       bool   `json:"pass"`                                      //是否通关
	MaxRoomId  int32  `json:"maxRoomId" gorm:"column:room_id"`           //最大探索度
	EventAt    int32  `json:"event_at" gorm:"column:event_at;not null" ` //埋点事件触发的时间
	Extra      string `json:"-" gorm:"column:extra" `                    //相关参数
	PassCount  int32  `json:"pass_count"`                                //通关次数
	FailCount  int32  `json:"fail_count"`                                //失败次数
}

//
// QueryPlayerChapter
//  @Description: 获取普通关卡进度信息
//  @param playerId 用户Id
//  @return []ChapterInfo 进度信息
//  @return int
//
func QueryPlayerChapter(playerId int64) ([]*ChapterInfo, int) {
	var playerRoomInfos []*ChapterInfo
	var sqlInfo bytes.Buffer
	sqlTemp := `(SELECT 
t.user_id, 
t.chapter_id,
max( t.room_id ) AS 'room_id', 
ANY_VALUE ( t.difficulty ) AS difficulty, 
ANY_VALUE ( event_at ) AS event_at, 
ANY_VALUE ( extra ) AS extra 
FROM 
chapter_logs_%d t 
WHERE
t.event_id = 11
AND t.extra LIKE '%%\"type\":%%'
AND t.user_id = %d)`

	for i := 0; i < 18; i++ {
		info := fmt.Sprintf(sqlTemp, i, playerId)
		sqlInfo.WriteString(info)
		if i != 17 {
			sqlInfo.WriteString(" UNION ")
		}
	}
	sqlInfo.WriteString(" ORDER BY user_id")
	sqlTemp = sqlInfo.String()
	config.DB.Raw(sqlTemp).Scan(&playerRoomInfos)

	if len(playerRoomInfos) > 0 && playerRoomInfos[0].UserId != playerId {
		playerRoomInfos = append(playerRoomInfos[:0], playerRoomInfos[1:]...)
	}

	for i := range playerRoomInfos {
		if playerRoomInfos[i].UserId != playerId {
			continue
		}
		dataTemp := playerRoomInfos[i]
		isPass := playerPass(dataTemp.Extra)
		playerRoomInfos[i].Pass = isPass
	}

	activeInfo := queryActiveChapterInfo(playerId)
	playerRoomInfos = append(playerRoomInfos, activeInfo...)

	return playerRoomInfos, len(playerRoomInfos)
}

//
// QueryActiveChapterInfo
//  @Description: 获取活动关卡进度信息（101,102,103）
//  @param chapterId 关卡Id
//  @param startDate 开始时间（时间戳）
//  @param endDate 结束时间（时间戳）
//  @return []*ChapterInfo 进度信息
//  @return int
//
func queryActiveChapterInfo(playerId int64) []*ChapterInfo {
	var playerRoomInfos []ChapterInfo
	sqlTemp := `(SELECT
t.chapter_id,
ANY_VALUE ( t.difficulty ) AS difficulty,
ANY_VALUE ( event_at ) AS event_at,
ANY_VALUE ( extra ) AS extra,
ANY_VALUE ( user_id ) AS user_id 
FROM
	chapter_logs_%d t 
WHERE
	t.event_id = 11 
	AND t.extra LIKE '%%"type":%%' 
	AND t.user_id = %d 
	AND LENGTH( t.user_id ) >= 1 
	)`
	var sqlInfo bytes.Buffer
	for i := 101; i < 104; i++ {
		infoTemp := fmt.Sprintf(sqlTemp, i, playerId)
		sqlInfo.WriteString(infoTemp)
		if i != 103 {
			sqlInfo.WriteString(" UNION ALL ")
		}
	}
	sqlInfo.WriteString("ORDER BY chapter_id")
	sqlTemp = sqlInfo.String()
	config.DB.Raw(sqlTemp).Scan(&playerRoomInfos)

	var result []*ChapterInfo
	lastChapterId := int32(-1)
	for _, info := range playerRoomInfos {
		if info.ChapterId == 0 {
			continue
		}
		if lastChapterId != info.ChapterId {
			infoTemp := &ChapterInfo{ChapterId: info.ChapterId,
				Difficulty: info.Difficulty}
			result = append(result, infoTemp)
		}
		passChapter := playerPass(info.Extra)
		if passChapter {
			result[len(result)-1].PassCount++
		} else {
			result[len(result)-1].FailCount++
		}

		lastChapterId = info.ChapterId
	}
	return result
}

//
//  playerPass
//  @Description: 玩家是否通过关卡
//  @param extraInfo 相关参数
//  @return bool 是否通关
//
func playerPass(extraInfo string) bool {
	type passType struct {
		Type int `json:"type"` //-1死亡结算；主动退出结算 1通关结算
	}
	var passTypeTemp passType
	json.Unmarshal([]byte(extraInfo), &passTypeTemp)
	return passTypeTemp.Type == 1
}
