package qznn

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/sirupsen/logrus"
	"gogs.daxia.dev/huanan/pkg.daxia.dev/db"
	"gogs.daxia.dev/huanan/pkg.daxia.dev/time_utils"
	"gorm.io/gorm"
	gameQZ "nn.daxia.dev/game/qznn"
	"nn.daxia.dev/gameproto"
	"nn.daxia.dev/handler/api"
	"nn.daxia.dev/model"
	"nn.daxia.dev/nxd"
)

type GetRecordListReq struct {
	Page     int `json:"page"`
	PageSize int `json:"page_size"`
	DayRange int `json:"day_range"`
}

type GetOpenRecordListReq struct {
	RoomID   int `josn:"room_id"`
	Page     int `json:"page"`
	PageSize int `json:"page_size"`
	DayRange int `json:"day_range"`
}

type ReadyReq struct {
}

type UnReadyReq struct {
}

type ChooseMasterReq struct {
	Mul int
}

type ChooseMulReq struct {
	Mul int
}

type OpenReq struct {
}

type ConnectReq struct {
}

type DisconnectReq struct {
}

func Ready(req api.PerformReq) error {
	var err error
	userModel := req.UserModel

	readyReq := ReadyReq{}
	err = json.Unmarshal(req.Msg, &readyReq)
	if err != nil {
		logrus.Error(err)
		return err
	}

	gameInstance := gameQZ.GetInstance()
	err = gameInstance.Ready(int32(userModel.ID))
	if err != nil {
		logrus.Error(err)

		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), nil)
	return nil
}

func UnReady(req api.PerformReq) error {
	var err error
	userModel := req.UserModel

	unReadyReq := UnReadyReq{}
	err = json.Unmarshal(req.Msg, &unReadyReq)
	if err != nil {
		logrus.Error(err)
		return err
	}

	gameInstance := gameQZ.GetInstance()
	err = gameInstance.UnReady(int32(userModel.ID))
	if err != nil {
		logrus.Error(err)

		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), nil)
	return nil
}

func ChooseMaster(req api.PerformReq) error {
	var err error
	userModel := req.UserModel

	chooseMasterReq := ChooseMasterReq{}
	err = json.Unmarshal(req.Msg, &chooseMasterReq)
	if err != nil {
		logrus.Error(err)
		return err
	}

	gameInstance := gameQZ.GetInstance()
	err = gameInstance.ChooseMaster(int32(userModel.ID), int32(chooseMasterReq.Mul))
	if err != nil {
		logrus.Error(err)

		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), nil)
	return nil
}

func ChooseMul(req api.PerformReq) error {
	var err error
	userModel := req.UserModel

	chooseMulReq := ChooseMulReq{}
	err = json.Unmarshal(req.Msg, &chooseMulReq)
	if err != nil {
		logrus.Error(err)
		return err
	}

	gameInstance := gameQZ.GetInstance()
	err = gameInstance.ChooseMul(int32(userModel.ID), int32(chooseMulReq.Mul))
	if err != nil {
		logrus.Error(err)

		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), nil)
	return nil
}

func Open(req api.PerformReq) error {
	var err error
	userModel := req.UserModel

	openReq := OpenReq{}
	err = json.Unmarshal(req.Msg, &openReq)
	if err != nil {
		logrus.Error(err)
		return err
	}

	gameInstance := gameQZ.GetInstance()
	err = gameInstance.OpenCard(int32(userModel.ID))
	if err != nil {
		logrus.Error(err)

		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), nil)
	return nil
}

func GetRecordList(req api.PerformReq) error {
	var err error

	userModel := req.UserModel

	getRecordListReq := GetRecordListReq{}
	err = json.Unmarshal(req.Msg, &getRecordListReq)
	if err != nil {
		logrus.Error(err)
		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	orderModelList := make([]model.GameOrder, 0)
	recordRespList := make([]*gameproto.GameRecordItem, 0)
	total := int64(0)
	page := getRecordListReq.Page
	pageSize := getRecordListReq.PageSize

	queryDB := db.GetDB().Model(model.GameOrder{}).Where("user_id = ? and is_draw = 1", userModel.ID)

	var startIssue time.Time
	var endIssue time.Time

	tz := time_utils.GetCNZone()
	timeNow := time_utils.GetZeroTime(time.Now())

	switch getRecordListReq.DayRange {
	case 1:
		startIssue, _ = time.ParseInLocation("2006-01-02 15:04:05", timeNow.Format("2006-01-02")+" 00:00:00", tz)
		endIssue, _ = time.ParseInLocation("2006-01-02 15:04:05", timeNow.Format("2006-01-02")+" 23:59:59", tz)
	case 2:
		timeYesterday := timeNow.Add(-1 * time.Hour * 24)
		startIssue, _ = time.ParseInLocation("2006-01-02 15:04:05", timeYesterday.Format("2006-01-02")+" 00:00:00", tz)
		endIssue, _ = time.ParseInLocation("2006-01-02 15:04:05", timeYesterday.Format("2006-01-02")+" 23:59:59", tz)
	case 3:
		startIssue = time_utils.GetFirstDateOfWeek(timeNow).In(tz)
		endIssue = time_utils.GetLastDateOfWeek(timeNow).In(tz)
	case 4:
		startIssue = time_utils.GetFirstDateOfMonth(timeNow).In(tz)
		endIssue = time_utils.GetLastDateOfMonth(timeNow).In(tz)
	default:
		return errors.New("day range 错误")
	}

	err = queryDB.
		Where("created_at >= ? and created_at <= ?", startIssue, endIssue).
		Count(&total).Error

	if err != nil {
		err = errors.New("内部错误(Q101)")

		logrus.Error(err)
		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	if total == 0 {
		nxd.SuccessResponse(req.Once, uint32(userModel.ID), &gameproto.GameRecordResp{
			Total:      int32(total),
			RecordList: recordRespList,
		})
		return nil
	}

	err = queryDB.Offset((page - 1) * pageSize).
		Limit(pageSize).
		Order("id desc").
		Scan(&orderModelList).
		Error

	if err == gorm.ErrRecordNotFound {
		nxd.SuccessResponse(req.Once, uint32(userModel.ID), &gameproto.GameRecordResp{
			Total:      int32(total),
			RecordList: recordRespList,
		})
		return nil
	}

	if err != nil {
		err = errors.New("内部错误(Q102)")

		logrus.Error(err)
		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	for _, orderModel := range orderModelList {
		recordRespList = append(recordRespList, &gameproto.GameRecordItem{
			CreatedAt:  orderModel.CreatedAt.Unix(),
			RoomID:     int64(orderModel.RoomID),
			RoomType:   int32(orderModel.RoomType),
			Issue:      orderModel.Issue,
			OpenNumber: orderModel.OpenNumber,
			BaseAmount: orderModel.BaseAmount.StringFixed(2),
			IsDraw:     int32(orderModel.IsDraw),
			DrawTime:   orderModel.DrawTime.Unix(),
			IsMaster:   int32(orderModel.IsMaster),
			MasterMul:  int32(orderModel.MasterMul),
			Mul:        int32(orderModel.Mul),
			IsWin:      int32(orderModel.IsWin),
			WinAmount:  orderModel.WinAmount.StringFixed(2),
		})
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), &gameproto.GameRecordResp{
		Total:      int32(total),
		RecordList: recordRespList,
	})
	return nil
}

func GetOpenRecordList(req api.PerformReq) error {
	var err error

	userModel := req.UserModel

	getOpenRecordListReq := GetOpenRecordListReq{}
	err = json.Unmarshal(req.Msg, &getOpenRecordListReq)
	if err != nil {
		logrus.Error(err)
		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	openLogModelList := make([]model.GameOpenLogQP, 0)
	openLogRespList := make([]*gameproto.GameOpenRecordItem, 0)
	total := int64(0)
	page := getOpenRecordListReq.Page
	pageSize := getOpenRecordListReq.PageSize
	roomID := getOpenRecordListReq.RoomID

	queryDB := db.GetDB().Model(model.GameOpenLogQP{}).Where("user_id = ? and is_open = 1", userModel.ID)

	var startTime time.Time
	var endTime time.Time

	tz := time_utils.GetCNZone()
	timeNow := time.Now().In(tz)

	switch getOpenRecordListReq.DayRange {
	case 1:
		startTime, _ = time.ParseInLocation("2006-01-02 15:04:05", timeNow.Format("2006-01-02")+" 00:00:00", tz)
		endTime, _ = time.ParseInLocation("2006-01-02 15:04:05", timeNow.Format("2006-01-02")+" 23:59:59", tz)
	case 2:
		timeYesterday := timeNow.Add(-1 * time.Hour * 24)
		startTime, _ = time.ParseInLocation("2006-01-02 15:04:05", timeYesterday.Format("2006-01-02")+" 00:00:00", tz)
		endTime, _ = time.ParseInLocation("2006-01-02 15:04:05", timeYesterday.Format("2006-01-02")+" 23:59:59", tz)
	case 3:
		startTime = time_utils.GetFirstDateOfWeek(timeNow)
		endTime = time_utils.GetLastDateOfWeek(timeNow)
	case 4:
		startTime = time_utils.GetFirstDateOfMonth(timeNow)
		endTime = time_utils.GetLastDateOfMonth(timeNow)
	default:
		return errors.New("day range 错误")
	}

	err = queryDB.
		Where("open_time >= ? and open_time <= ? and room_id = ?", startTime, endTime, roomID).
		Count(&total).Error

	if err != nil {
		err = errors.New("内部错误(Q101)")

		logrus.Error(err)
		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	if total == 0 {
		nxd.SuccessResponse(req.Once, uint32(userModel.ID), &gameproto.GameOpenRecordResp{
			Total:          int32(total),
			OpenRecordList: openLogRespList,
		})
		return nil
	}

	err = queryDB.Offset((page - 1) * pageSize).
		Limit(pageSize).
		Order("id desc").
		Scan(&openLogModelList).
		Error

	if err == gorm.ErrRecordNotFound {
		nxd.SuccessResponse(req.Once, uint32(userModel.ID), &gameproto.GameOpenRecordResp{
			Total:          int32(total),
			OpenRecordList: openLogRespList,
		})
		return nil
	}

	if err != nil {
		err = errors.New("内部错误(Q102)")

		logrus.Error(err)
		nxd.FailedResponse(req.Once, uint32(userModel.ID), err.Error())
		return err
	}

	for _, openLogModel := range openLogModelList {
		openLogRespList = append(openLogRespList, &gameproto.GameOpenRecordItem{
			RoomID:      int64(openLogModel.RoomID),
			RoomType:    openLogModel.RoomType,
			Issue:       openLogModel.Issue,
			OpenNumber1: openLogModel.OpenNumber1,
			OpenNumber2: openLogModel.OpenNumber2,
			OpenNumber3: openLogModel.OpenNumber3,
			OpenNumber4: openLogModel.OpenNumber4,
			OpenNumber5: openLogModel.OpenNumber5,
			OpenTime:    openLogModel.OpenTime.Unix(),
			Hash:        openLogModel.Hash,
		})
	}

	nxd.SuccessResponse(req.Once, uint32(userModel.ID), &gameproto.GameOpenRecordResp{
		Total:          int32(total),
		OpenRecordList: openLogRespList,
	})
	return nil
}
