package teen

import (
	"fmt"
	"server/game"
	"server/game/room"
	"server/msg"
	"server/user"
	"strconv"
	"time"

	"github.com/name5566/leaf/log"
)

// 看牌
func seen(room *room.Room, sitPos int32) {
	log.Debug("看牌的位置: %d", room.RoundSitPos)
	player := room.GetPlayerBySitPos(sitPos)
	player.IsSeen = true
	var seenCards []*msg.ReqCard
	//如果是机器人返回空的看牌
	if player.IsRobot {
		seenCards = make([]*msg.ReqCard, 0)
	} else {
		seenCards = room.GetPlayerBySitPos(sitPos).HandCards
	}
	SendRoundMsgToAll(room, &msg.ReqRound{
		Round:       int32(room.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_SEEN, SeenCards: convertToMsgCardList(seenCards)},
		UserId:      room.GetPlayerBySitPos(sitPos).GetUserId(),
	})
	log.Debug("玩家看破sitPos", sitPos)
	log.Debug("玩家看破", seenCards)

}

// 弃牌
func packed(room *room.Room, sitPos int32) {
	player := room.GetPlayerBySitPos(sitPos)
	player.IsPacked = true
	SendRoundMsgToAll(room, &msg.ReqRound{
		Round:       int32(room.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_PACKED},
		UserId:      room.GetPlayerBySitPos(sitPos).GetUserId(),
	})
	if isOnlyOne, sp := room.IsOnlyOneNotPacked(); isOnlyOne {

		// 如果所有玩家都弃牌，判定当前座位玩家获胜
		room.PlayerWin(sp)

		winPlayer := room.GetPlayerBySitPos(sp)
		// 结算
		if winPlayer.IsRobot {
			// 机器人 也要加减分.暂时先放
		} else {
			user.AddUserPoint(room.GameRound.TotalBet, winPlayer.Id)
			UserInfo := user.GetUserInfoById(winPlayer.Id)
			// 同步用户信息
			SendUserInfoMsg(room, &msg.ReqUserInfo{
				UserId: winPlayer.Id,
				Points: int32(UserInfo.Points),
			})
		}

		sendResult(room, sp)

		time.Sleep(5 * time.Second)
		log.Debug("弃牌的位置startNextRound: %d")
		startNextRound(room)
	} else {
		log.Debug("弃牌的位置: %d", room.RoundSitPos)
		room.SetNextRound()
		checkRoomStatus(room)
	}
}

// 跟注
func chaal(room *room.Room, sitPos int32, betAmount int32) {

	// 判断金额是否正常
	if betAmount > room.GameRound.ResBet.MaxCheelBet || betAmount < room.GameRound.ResBet.MinCheelBet {
		log.Debug("Bet amount %d is out of valid range. Min: %d, Max: %d", betAmount, room.GameRound.ResBet.MinCheelBet, room.GameRound.ResBet.MaxCheelBet)
		betAmount = room.GameRound.ResBet.MaxCheelBet
	}
	UserId := room.GetPlayerBySitPos(sitPos).GetUserId()
	if room.GetPlayerBySitPos(sitPos).IsRobot {
		// 机器人
	} else {
		// 判断积分是否足够

		UserInfo := user.GetUserInfoById(UserId)
		if UserInfo.Points < betAmount {
			log.Debug("chaal User %s has insufficient points. Current points: %d", UserId, UserInfo.Points)
			// 告诉他充值
			room.GetPlayerBySitPos(sitPos).Agent.WriteMsg(&msg.ReqInsufficientPoints{
				UserId:          UserInfo.Id,
				RequiredAmount:  int32(betAmount),
				AvailableAmount: UserInfo.Points,
				GameId:          "teen_patti",
			})
		}
		// 扣除用户金币
		user.DecreaseUserPoint(betAmount, UserId)
		// 同步用户金币
		SendUserInfoMsg(room, &msg.ReqUserInfo{
			UserId: UserId,
			Points: int32(UserInfo.Points),
		})
	}
	// 用户的金额是否大于下注金额
	room.SetNextRound()
	room.AddBet(betAmount)
	//
	// 动态修改下注金额
	room.UpdateResBet(betAmount, getRoomChaalLimmit(room.ConfId))

	SendRoundMsgToAll(room, &msg.ReqRound{
		Round:       int32(room.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_CHAAL},
		UserId:      UserId,
	})

	checkRoomStatus(room)
	game.Module.Skeleton.AfterFunc(time.Microsecond*500, func() {
		sendRoomBet(room)
	})
}

// blind跟注
func blind(room *room.Room, sitPos int32, betAmount int32) {
	// 判断金额是否正常
	if betAmount > room.GameRound.ResBet.MaxBlindBet || betAmount < room.GameRound.ResBet.MinBlindBet {
		log.Debug("Bet amount %d is out of valid range. MinBlindBet: %d, MaxBlindBet: %d", betAmount, room.GameRound.ResBet.MinBlindBet, room.GameRound.ResBet.MaxBlindBet)

		// 金额不对 直接弃牌
		betAmount = room.GameRound.ResBet.MaxBlindBet
	}
	UserId := room.GetPlayerBySitPos(sitPos).GetUserId()
	UserInfo := user.GetUserInfoById(UserId)
	room.SetNextRound()
	room.AddBet(betAmount)

	// 动态修改下注金额
	room.UpdateResBet(betAmount, getRoomChaalLimmit(room.ConfId))

	SendRoundMsgToAll(room, &msg.ReqRound{
		Round:       int32(room.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_BLIND},
		UserId:      UserId,
	})
	if room.GetPlayerBySitPos(sitPos).IsRobot {
		// 机器人
	} else {
		if UserInfo.Points < betAmount {
			log.Debug("blind User %s has insufficient points. Current points: %d", UserId, UserInfo.Points)
			// 告诉他充值
			room.GetPlayerBySitPos(sitPos).Agent.WriteMsg(&msg.ReqInsufficientPoints{
				UserId:          UserInfo.Id,
				RequiredAmount:  int32(betAmount),
				AvailableAmount: UserInfo.Points,
				GameId:          "teen_patti",
			})
		}
		// 扣除用户金币
		user.DecreaseUserPoint(betAmount, UserId)
		// 同步用户金币
		SendUserInfoMsg(room, &msg.ReqUserInfo{
			UserId: UserId,
			Points: int32(UserInfo.Points),
		})
	}

	checkRoomStatus(room)
	game.Module.Skeleton.AfterFunc(time.Microsecond*500, func() {
		sendRoomBet(room)
	})
}

// 底注
func ante(room *room.Room, sitPos int32, betAmount int32) {
	room.AddBet(betAmount)
	UserId := room.GetPlayerBySitPos(sitPos).GetUserId()
	SendRoundMsgToAll(room, &msg.ReqRound{
		Round:       int32(room.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_ANTE},
		UserId:      UserId,
	})
	if room.GetPlayerBySitPos(sitPos).IsRobot {
		// 机器人
	} else {
		// 扣除用户金币
		user.DecreaseUserPoint(betAmount, UserId)
		// 同步用户金币
		UserInfo := user.GetUserInfoById(UserId)
		SendUserInfoMsg(room, &msg.ReqUserInfo{
			UserId: UserId,
			Points: int32(UserInfo.Points),
		})
	}
	game.Module.Skeleton.AfterFunc(time.Microsecond*500, func() {
		sendRoomBet(room)
	})
}

func checkSiteShow(r *room.Room, sitPos int32) bool {
	// 条件1: 当前玩家是否弃牌
	currentPlayer := r.GetPlayerBySitPos(sitPos)
	log.Debug("现在的座位号1", sitPos)
	if currentPlayer == nil {
		log.Debug("currentPlayer Player with SitPos %d not found.", sitPos)
		return false
	}

	if currentPlayer.IsPacked {
		log.Debug("Player %s has packed, cannot show cards.", currentPlayer.Id)
		return false
	}

	// 条件2: 剩余有效玩家大于等于 3 人
	activePlayers := 0
	for _, player := range r.Players {
		if player != nil && !player.IsPacked { // 只计算没有弃牌的玩家
			activePlayers++
		}
	}

	if activePlayers < 3 {
		log.Debug("Not enough active players (less than 3). Cannot show cards.")
		return false
	}
	// 条件3. 上一位玩家是否看牌
	// 获取上一个玩家
	previousSitPos := getRoomSitPos(r, sitPos, -1)
	log.Debug("上一位玩家的座位号checkSiteShow", previousSitPos)

	previousPlayer := r.GetPlayerBySitPos(previousSitPos)
	if previousPlayer == nil {
		log.Debug("previousPlayer1 Player with SitPos %d not found.", previousSitPos)
		return false
	}

	// 判断当前玩家和目标玩家是否都已看牌
	if !previousPlayer.IsSeen || !currentPlayer.IsSeen {
		log.Debug("Either player %s or previous player %s has not seen their cards.", currentPlayer.Id, previousPlayer.Id)
		return false
	}

	// 如果满足以上条件，则返回 true
	log.Debug("Player ture %s can show cards.", currentPlayer.Id)
	return true
}
func site_show(r *room.Room, sitPos int32, betAmount int32) {
	// 检查是否符合条件
	if !checkSiteShow(r, sitPos) {
		// 	return
	}
	// notifyPlayerAction(r, int32(sitPos), msg.PlayerOptType_OPT_CHAAL)

	ante(r, sitPos, betAmount)
	// 扣除用户金币
	UserId := r.GetPlayerBySitPos(sitPos).GetUserId()
	if r.GetPlayerBySitPos(sitPos).IsRobot {
		updateRobotPoints(UserId, betAmount, false)
		// 机器人
	} else {
		// 扣除用户金币
		user.DecreaseUserPoint(betAmount, UserId)
		// 同步用户金币
		UserInfo := user.GetUserInfoById(UserId)
		SendUserInfoMsg(r, &msg.ReqUserInfo{
			UserId: UserId,
			Points: int32(UserInfo.Points),
		})
	}

	UserInfo := user.GetUserInfoById(UserId)
	// // 同步用户信息
	SendUserInfoMsg(r, &msg.ReqUserInfo{
		UserId: UserId,
		Points: int32(UserInfo.Points),
		RoomId: r.Id,
	})
	// 获取上一个玩家
	previousSitPos := getRoomSitPos(r, sitPos, -1)

	log.Debug("发起比牌的玩家座位号", sitPos)
	log.Debug("接受比牌选项玩家的座位号", previousSitPos)

	SendRoundMsgToAll(r, &msg.ReqRound{
		Round:       int32(r.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_SITESHOW},
		UserId:      r.GetPlayerBySitPos(sitPos).Id,
	})

	notifyPlayerAction(r, int32(previousSitPos), msg.PlayerOptType_OPT_SELECTSITESHOW)

}

// 不同意,直接通知下一位玩家操作
func RefuseSiteShow(r *room.Room, sitPos int32) {

	// // 不同意
	SendRoundMsgToAll(r, &msg.ReqRound{
		Round:       int32(r.Round),
		RoundSitPos: int32(sitPos),
		PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_REFUSESITESHOW},
		UserId:      r.GetPlayerBySitPos(sitPos).GetUserId(),
	})
	r.SetNextRound()
	checkRoomStatus(r)
}

// 如果同意,处理比牌请求
func AgreeSiteShow(r *room.Room, sitPos int32) {
	// // 检查是否符合条件
	// if !checkSiteShow(r, sitPos) {
	// 	log.Debug("Player %d cannot show cards, conditions not met.", sitPos)
	// 	return
	// }
	// 获取比牌双方: 当前玩家和下家
	currentPlayer := r.GetPlayerBySitPos(sitPos)
	if currentPlayer == nil {
		log.Debug("Player with SitPos %d not found.", sitPos)
		return
	}

	// 获取下家座位
	previousSitPos := getRoomSitPos(r, sitPos, 1)
	previousPlayer := r.GetPlayerBySitPos(previousSitPos)
	if previousPlayer == nil {
		log.Debug("Next player with SitPos %d not found.", previousPlayer)
		return
	}

	// 比较玩家的手牌
	players := []*room.Player{currentPlayer, previousPlayer}
	winPlayer := compareCards(players) // 假设 compareCards 函数已经比较手牌并返回胜者

	if winPlayer != nil {
		// 胜者继续牌局
		// 输的玩家弃牌
		var loserPlayer *room.Player
		if winPlayer == currentPlayer {
			loserPlayer = previousPlayer // 当前玩家赢，上一位玩家是输家
		} else {
			loserPlayer = currentPlayer // 上一位玩家赢，当前玩家是输家
		}
		// 输的玩家弃牌
		loserPlayer.IsPacked = true
		log.Debug("Player %s has packed, they lose the showdown.", loserPlayer.Id)
		// 发送比牌结果
		SendRoundMsgToAll(r, &msg.ReqRound{
			Round:       int32(r.Round),
			RoundSitPos: int32(currentPlayer.SitPos),
			PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_AGREESITESHOW},
			UserId:      currentPlayer.Id,
		})
		// 赢家和输家互相可见手牌
		for _, player := range []*room.Player{currentPlayer, previousPlayer} {
			if player.Agent == nil {
				continue
			}
			var seenCards []*msg.ReqCard
			var opponent *room.Player

			if player.Id == currentPlayer.Id {
				opponent = previousPlayer
				seenCards = convertToMsgCardList(previousPlayer.HandCards) // 赢家看到输家的手牌
			} else {
				opponent = currentPlayer
				seenCards = convertToMsgCardList(currentPlayer.HandCards) // 输家看到赢家的手牌
			}
			log.Debug("AgreeSiteShow seenCards", seenCards)
			// 发送消息给当前玩家，告诉 TA 他的对手是谁，并展示对手的手牌
			player.Agent.WriteMsg(&msg.SiteShowResult{
				Round:       int32(r.Round),
				RoundSitPos: int32(opponent.SitPos), // **座位号改为对手的**
				SeenCards:   seenCards,              // 只展示对手的手牌
				UserId:      opponent.Id,            // **UserId 也是对手的**
			})
		}
		packed(r, loserPlayer.SitPos)

	} else {
		log.Error("到这就错误了SiteShowResult")
	}

	// 处理结果
	// r.SetNextRound()
	// checkRoomStatus(r)
}

// 检查是否可以亮牌
func checkShow(r *room.Room, sitPos int32) bool {
	// 当前玩家是否弃牌
	currentPlayer := r.GetPlayerBySitPos(sitPos)
	if currentPlayer == nil {
		log.Debug("Player with SitPos %d not found.", sitPos)
		return false
	}

	// 如果玩家已弃牌，不能亮牌
	if currentPlayer.IsPacked {
		log.Debug("Player %s has packed, cannot show cards.", currentPlayer.Id)
		return false
	}

	// 判断剩余有效玩家人数
	activePlayers := 0
	for _, player := range r.Players {
		if player != nil && !player.IsPacked { // 只计算没有弃牌的玩家
			activePlayers++
		}
	}

	// 如果剩余有效玩家是两名，则允许亮牌
	if activePlayers == 2 {
		log.Debug("There are two players left, showing cards is allowed.")
		return true
	}

	log.Debug("There are not two players left, cannot show cards.")
	return false
}

// 亮牌
func show(r *room.Room, sitPos int32) {
	// 判断金额是否正常

	betAmount := r.GameRound.ResBet.MinCheelBet
	ante(r, sitPos, betAmount)
	// 检查是否可以亮牌
	if !checkShow(r, sitPos) {
		log.Debug("Player %d cannot show cards, conditions not met.", sitPos)
		return
	}
	// 扣除用户金币
	UserId := r.GetPlayerBySitPos(sitPos).GetUserId()
	UserInfo := user.GetUserInfoById(UserId)
	if r.GetPlayerBySitPos(sitPos).IsRobot {
		updateRobotPoints(UserId, betAmount, false)
		// 机器人
	} else {
		if UserInfo.Points < betAmount && UserInfo.Points > 0 {
			betAmount = UserInfo.Points
		}
		// 扣除用户金币
		user.DecreaseUserPoint(betAmount, UserId)
		// 同步用户金币
		SendUserInfoMsg(r, &msg.ReqUserInfo{
			UserId: UserId,
			Points: int32(UserInfo.Points),
		})
	}

	// 同步用户信息
	SendUserInfoMsg(r, &msg.ReqUserInfo{
		UserId: UserId,
		Points: int32(UserInfo.Points),
	})
	// 亮牌的玩家
	players := r.Players
	temp := make([]*room.Player, 0)

	// 只处理没有弃牌的玩家
	for _, player := range players {
		if !player.IsPacked {
			temp = append(temp, player)
			// 向所有玩家发送亮牌的消息
			SendRoundMsgToAll(r, &msg.ReqRound{
				Round:       int32(r.Round),
				RoundSitPos: int32(player.SitPos),
				PlayerOpt:   &msg.PlayerOpt{OptType: msg.PlayerOptType_OPT_SHOW, SeenCards: convertToMsgCardList(player.HandCards)},
				UserId:      r.GetPlayerBySitPos(player.SitPos).GetUserId(),
			})
		}
	}

	// 比较玩家的手牌，决定胜利者
	winPlayer := compareCards(temp)
	if winPlayer != nil {
		r.PlayerWin(winPlayer.SitPos)
		sendResult(r, winPlayer.SitPos)
		// 加分

		log.Debug("SHOWUserId", UserId)
		// 胜的玩家是否是机器人
		if winPlayer.IsRobot {
			// 机器人暂时不处理
		} else {
			user.AddUserPoint(r.GameRound.TotalBet, winPlayer.Id)

			UserInfo := user.GetUserInfoById(winPlayer.Id)
			// 同步用户信息
			SendUserInfoMsg(r, &msg.ReqUserInfo{
				UserId: winPlayer.Id,
				Points: int32(UserInfo.Points),
			})
		}
	} else {
		log.Error("所有玩家都弃牌了")
	}

	// 等待一定时间后开始下一回合
	time.Sleep(5 * time.Second)
	startNextRound(r)
}

// 超时取消操作
func cancelOptTimeout(player *room.Player, sitPos int32) {
	eventID := fmt.Sprintf("player_%s_opt_%s", player.Id, sitPos)
	timerMgr.RemoveEvent(eventID)
}

// 房间状态检测
func checkRoomStatus(r *room.Room) {
	if r.Status == room.RoomStatusEnd {
	} else {
		log.Debug("checkRoomStatus:下一个操作的玩家座位：%d", r.RoundSitPos)
		game.Module.Skeleton.AfterFunc(time.Second*1, func() {
			notifyPlayerAction(r, int32(r.RoundSitPos), msg.PlayerOptType_OPT_SELECT)
		})
	}

}
func getRoomChaalLimmit(ConfId string) int32 {
	for _, betInfo := range GameConfig.RoomList {
		if betInfo.ConfId == ConfId {
			// 获取房间的最低买入金额
			chaalLimmit, err := strconv.Atoi(betInfo.ChaalLimmit)
			if err != nil {
				log.Error("Invalid chaalLimmit value: %v", chaalLimmit)
			}
			return int32(chaalLimmit)
		}
	}
	return 0
}
