package onexbet

import (
	"encoding/json"
	"fmt"
	"strings"

	webspider "gordenko.dev/dima/spider"

	"gordenko.dev/dima/flashscore"
)

var (
	// проверка на Contains
	bannedTennisChamps = []string{
		"Setka Cup",
		"Russia. Masters",
		"Russia. League Pro",
		"Daily Aqua Tour",
		"UTR Pro Tennis Series",
		"VS OPEN",
		"Daily Pro Tour",
		"Mountain Bay Open",
		"Russian River Cup",
	}

	bannedTennisPrefixes = []string{}
)

func TennisChampFilter(champName string) (_ bool) {
	for _, bannedChampName := range bannedHandballChamps {
		if strings.Contains(champName, bannedChampName) {
			return
		}
	}

	for _, bannedPrefix := range bannedHandballPrefixes {
		if strings.HasPrefix(champName, bannedPrefix) {
			return
		}
	}

	if flashscore.IsTennisDoublesChamp(champName) {
		return
	}

	fmt.Printf("CHAMP NAME IS OK: %s\n", champName)
	return true
}

/*
// Поля P и St - топ поля документа
// Tennis match status
// Подтверждено точно
"St": 2,

// Tennis Match Stat
// Счет по сетам
"P": [
      {
        "A": 7,
        "CSPP": [],
        "H": 5,
        "T": 11,
        "TI": "000000000000000000000000"
      },
      {
        "A": 4,
        "CSPP": [],
        "H": 6,
        "T": 12,
        "TI": "000000000000000000000000"
      },
      {
        "A": 4,
        "CSPP": [],
        "H": 6,
        "T": 13,
        "TI": "000000000000000000000000"
      },
      {
        "A": 6,
        "CSPP": [],
        "H": 4,
        "T": 14,
        "TI": "000000000000000000000000"
      },
      {
        "A": 6,
        "CSPP": [],
        "H": 2,
        "T": 15,
        "TI": "000000000000000000000000"
      }
    ],
*/

type matchResult struct {
	Periods []periodResult `json:"P"`
	Status  int            `json:"St"`
}

// Можно добавить поле T (код сета) для контроля.
// Коды сетов: 1й - 11, 2й - 12, 3й - 13, 4й - 14, 5й - 15
type periodResult struct {
	Code       int `json:"T"`
	HomePoints int `json:"H"`
	AwayPoints int `json:"A"`
}

// Для футбола и гандбола
var periodCode2PeriodNumberMapping = map[int]int{
	1: 1,
	3: 2,
}

var setCode2SetNumberMapping = map[int]int{
	11: 1,
	12: 2,
	13: 3,
	14: 4,
	15: 5,
}

func GetTennisMatchResult(statsMatchID string) (result TeamMatchResult, err error) {
	url := fmt.Sprintf(matchStatsURLPattern, statsMatchID)

	spider, err := webspider.NewSpider(nil)
	if err != nil {
		panic(err)
	}

	buf, err := spider.Get(url, nil)
	if err != nil {
		return
	}

	//fmt.Printf("%s\n", buf)

	var tmp matchResult

	err = json.Unmarshal(buf, &tmp)
	if err != nil {
		return
	}

	result.Status = tmp.Status
	result.ScoreByPeriods = make(map[int]PeriodScore)

	for _, set := range tmp.Periods {
		setNumber := setCode2SetNumberMapping[set.Code]
		if setNumber == 0 {
			continue
		}

		result.ScoreByPeriods[setNumber] = PeriodScore{
			HomePoints: set.HomePoints,
			AwayPoints: set.AwayPoints,
		}
	}

	return
}

///////////

// Все структуры с маленькой буквы - это служебные структуры для парсинга

// служебная структура для парсинга данных live матча
type tennisLiveMatchDataEnvelope struct {
	Error     string
	ErrorCode int64
	Success   bool // false, если матч закончен
	Value     tennisLiveMatchData
}

// поле BIG со списком matchID для других периодов встречается в JSON документах
// других периодов. То есть если запросить данные для 2-го сета по специальному ID,
// то в поле BIG будет список ID. Если же запросить документ для Regular Time, то
// поля BIG не будет, а будет SG (с коэффициентами для других периодов)
type tennisLiveMatchData struct {
	Markets []rawMarket `json:"GE"` // рынки
	// текущий счет, в том числе по геймам (только в Regular Time документе)
	Stats        statAndScore `json:"SC"`
	Sets         []tennisSet  `json:"SG"`
	StatsMatchID string       `json:"SGI"`
}

type tennisSet struct {
	SetNumber int         `json:"P"`
	Markets   []rawMarket `json:"GE"`
}

/*
type tennisStatsAndScore struct {
	CurrentSetNumber int           `json:"CP"`
	SetScore         scoreStruct   `json:"FS"` // счет по сетам
	GameScore        []periodScore `json:"PS"`
}
*/

type statAndScore struct {
	Score          scoreStruct   `json:"FS"`
	ScoreByPeriods []periodScore `json:"PS"`
	CurrentPeriod  int           `json:"CP"`
}

// public

func LoadTennisLiveMatchData(matchID string) (_ TeamLiveMatchData, isMatchFinished bool, err error) {
	url := fmt.Sprintf(liveMatchURLPattern, matchID)

	spider, err := webspider.NewSpider(nil)
	if err != nil {
		panic(err)
	}

	buf, err := spider.Get(url, nil)
	if err != nil {
		return
	}

	//fmt.Printf("buf: %s\n\n", buf)

	var env tennisLiveMatchDataEnvelope

	err = json.Unmarshal(buf, &env)
	if err != nil {
		err = fmt.Errorf("json.Unmarshal liveMatchDataEnvelope: %s", err)
		return
	}

	if !env.Success {
		isMatchFinished = true
		return
	}

	data := TeamLiveMatchData{
		MatchID:        matchID,
		ScoreByPeriods: make(map[int]Score),
		Periods:        make(map[int]Period),
	}

	// FULL TIME
	for _, market := range env.Value.Markets {
		switch market.MarketType {
		case tennisMarketWinner:

			winner := &Winner2Way{}

			for _, offers := range market.OffersList {
				if len(offers) > 0 {
					offer := offers[0]

					if offer.IsBlocked {
						continue
					}

					if offer.Side == 1 {
						// T=1
						winner.HasHome = true
						winner.Home = offer.Price
					} else if offer.Side == 3 {
						// T=3
						winner.HasAway = true
						winner.Away = offer.Price
					}
				}
			}

			data.Winner2Way = winner

		case tennisMarketTotal:
			data.Total, err = getTotal(market)
			if err != nil {
				err = fmt.Errorf("FT getTotal (tennis): %s", err)
				return
			}

		case tennisMarketHandicap:
			data.Handicap, err = getHandicap(market)
			if err != nil {
				err = fmt.Errorf("FT getHandicap (tennis): %s", err)
				return
			}
		}
	}

	// BY SETS

	for _, p := range env.Value.Sets {
		set := Period{
			PeriodNumber: p.SetNumber,
		}

		for _, market := range p.Markets {
			switch market.MarketType {

			case tennisMarketTotal:
				set.Total, err = getTotal(market)
				if err != nil {
					err = fmt.Errorf("SET %d getTotal (tennis): %s", p.SetNumber, err)
					return
				}

			case tennisMarketHandicap:
				set.Handicap, err = getHandicap(market)
				if err != nil {
					err = fmt.Errorf("SET %d getHandicap (tennis): %s", p.SetNumber, err)
					return
				}
			}
		}

		data.Periods[p.SetNumber] = set
	}

	// SCORE

	stat := env.Value.Stats

	if stat.CurrentPeriod == 0 {
		// ВАЖНО!
		// Если период не указан - поля нет в JSON, счета нет
		err = fmt.Errorf("Current score not found")
		return
	}

	data.CurrentPeriod = stat.CurrentPeriod

	data.Score.Home = stat.Score.HomeScore
	data.Score.Away = stat.Score.AwayScore

	for _, p := range stat.ScoreByPeriods {
		data.ScoreByPeriods[p.Period] = Score{
			Home: p.Score.HomeScore,
			Away: p.Score.AwayScore,
		}
	}
	//fmt.Printf("%s\n\n", buf)

	return data, false, nil
}
