package model

import (
	"fmt"
	"strings"
)

func (s *Model) GetTeamZone(zoneID string) (_ *TeamZone, err error) {
	zone := TeamZone{
		ZoneID: zoneID,
	}

	found, err := s.qx.One(&zone)
	if err != nil {
		return
	}

	if !found {
		return
	}
	return &zone, nil
}

func (s *Model) GetTeamChamp(champID string) (_ *TeamChamp, err error) {
	champ := TeamChamp{
		ChampID: champID,
	}

	found, err := s.qx.One(&champ)
	if err != nil {
		return
	}

	if !found {
		return
	}
	return &champ, nil
}

func (s *Model) GetTeam(teamID string) (_ *Team, err error) {
	team := Team{
		TeamID: teamID,
	}

	found, err := s.qx.One(&team)
	if err != nil {
		return
	}

	if !found {
		return
	}
	return &team, nil
}

func (s *Model) GetTeamMatch(matchID string) (_ *TeamMatch, err error) {
	m := TeamMatch{
		MatchID: matchID,
	}

	found, err := s.qx.One(&m)
	if err != nil {
		return
	}

	if !found {
		return
	}

	return &m, nil
}

func (s *Model) AddTeamZone(req TeamZone) (err error) {
	if req.Name == "" {
		err = fix.Field(EmptyValue, "name")
		return
	}

	req.Name = strings.Title(strings.ToLower(req.Name))

	tx, err := s.qx.Tx()
	if err != nil {
		return
	}
	defer tx.Close(&err)

	_, err = tx.Insert(req)
	if err != nil {
		return
	}
	err = tx.Commit()
	return
}

func (s *Model) AddTeamChamp(req TeamChamp) (err error) {
	if req.Name == "" {
		err = fix.Field(EmptyValue, "name")
		return
	}

	tx, err := s.qx.Tx()
	if err != nil {
		return
	}
	defer tx.Close(&err)

	has, err := tx.Has("teamZones", "WHERE zoneID=?", req.ZoneID)
	if err != nil {
		return
	}

	if !has {
		err = fix.Field(UnknownZone, "zoneID")
		return
	}

	_, err = tx.Insert(req)
	if err != nil {
		return
	}
	err = tx.Commit()
	return
}

/*
func (s *Model) UpdateTeamChampName(req TeamChamp) (err error) {
	if req.Name == "" {
		err = fix.Field(EmptyValue, "name")
		return
	}

	err = s.qx.Exec("UPDATE teamChamps SET name=? WHERE champID=?", req.Name, req.ChampID)
	if err != nil {
		return
	}
	return
}
*/

func (s *Model) AddTeam(req Team) (err error) {
	aliasName := NormalizeNameToAlias(req.CanonicalName)

	req.CanonicalName = strings.Title(strings.ToLower(aliasName))

	if req.CanonicalName == "" {
		err = fix.Field(EmptyValue, "canonicalName")
		return
	}

	tx, err := s.qx.Tx()
	if err != nil {
		return
	}
	defer tx.Close(&err)

	_, err = tx.Insert(req)
	if err != nil {
		return
	}

	zone := TeamZone{
		ZoneID: req.ZoneID,
	}

	_, err = tx.One(&zone)
	if err != nil {
		return
	}

	// Добавляем alias
	_, err = tx.Insert(TeamAlias{
		Name:    aliasName,
		TeamID:  req.TeamID,
		SportID: zone.SportID,
	})
	if err != nil {
		return
	}

	err = tx.Commit()
	return
}

func (s *Model) AddTeamAlias(req TeamAlias) (err error) {
	req.AliasID = 0
	req.Name = NormalizeNameToAlias(req.Name)

	if req.Name == "" {
		err = fix.Field(EmptyValue, "name")
		return
	}

	tx, err := s.qx.Tx()
	if err != nil {
		return
	}
	defer tx.Close(&err)

	// Чтобы узнать sportID сперва достаем Team
	team := Team{
		TeamID: req.TeamID,
	}

	found, err := tx.One(&team)
	if err != nil {
		return
	}

	if !found {
		err = fix.Field(UnknownTeam, "teamID")
		return
	}

	// Чтобы узнать sportID затем достаем teamZone
	zone := TeamZone{
		ZoneID: team.ZoneID,
	}

	_, err = tx.One(&zone)
	if err != nil {
		return
	}

	req.SportID = zone.SportID

	/*
		hasTeam, err := tx.Has("teams", "WHERE teamID=?", req.TeamID)
		if err != nil {
			return
		}

		if !hasTeam {
			err = fix.Field(UnknownTeam, "teamID")
			return
		}
	*/

	hasAlias, err := tx.Has("teamAliases", "WHERE teamID=? AND name=?",
		req.TeamID, req.Name)
	if err != nil {
		return
	}

	if hasAlias {
		err = fix.Field(Duplicate, "name")
		return
	}

	// Добавляем alias
	_, err = tx.Insert(req)
	if err != nil {
		return
	}

	err = tx.Commit()
	return
}

func (s *Model) SetTeamWasLinked(teamID string) (err error) {
	err = s.qx.Exec(`UPDATE teams SET wasLinked=true WHERE teamID=?`, teamID)
	return
}

func (s *Model) RemoveTeamAlias(aliasID int64) (err error) {
	return s.qx.Exec(`DELETE FROM teamAliases WHERE aliasID=?`, aliasID)
}

func (s *Model) AddTeamMatch(req TeamMatch) (err error) {
	tx, err := s.qx.Tx()
	if err != nil {
		return
	}
	defer tx.Close(&err)

	req.MatchID = strings.TrimSpace(req.MatchID)

	if req.MatchID == "" {
		err = fix.Field(EmptyValue, "matchID")
		return
	}

	/*
		hasChamp, err := tx.Has("teamChamps", "WHERE champID=?", req.ChampID)
		if err != nil {
			return
		}

		if !hasChamp {
			err = fix.Field(UnknownChamp, "champID")
			return
		}

		hasHomeTeam, err := tx.Has("teams", "WHERE teamID=?", req.HomeTeamID)
		if err != nil {
			return
		}

		if !hasHomeTeam {
			err = fix.Field(UnknownTeam, "teamID")
			return
		}

		hasAwayTeam, err := tx.Has("teams", "WHERE teamID=?", req.AwayTeamID)
		if err != nil {
			return
		}

		if !hasAwayTeam {
			err = fix.Field(UnknownTeam, "teamID")
			return
		}
	*/
	_, err = tx.Insert(req)
	if err != nil {
		return
	}
	err = tx.Commit()
	return
}

type UpdateTeamCanonicalNameIn struct {
	TeamID           string
	CanonicalName    string
	NewCanonicalName string
}

func (s *Model) UpdateTeamCanonicalName(in UpdateTeamCanonicalNameIn) (err error) {
	tx, err := s.qx.Tx()
	if err != nil {
		return
	}
	defer tx.Close(&err)

	// Старый canonicalName не нормализуем, ибо предполагается что имя мы получили из БД
	in.NewCanonicalName = strings.Title(strings.ToLower(NormalizeNameToAlias(in.NewCanonicalName)))

	if in.NewCanonicalName == "" {
		err = fix.Field(EmptyValue, "newCanonicalName")
		return
	}

	// Удаляем старый alias
	err = tx.Exec("DELETE FROM teamAliases WHERE teamID=? AND name=?",
		in.TeamID, in.CanonicalName)
	if err != nil {
		return
	}

	// Обновляем canonicalName
	err = tx.Exec("UPDATE teams SET canonicalName=? WHERE teamID=?",
		in.NewCanonicalName, in.TeamID)
	if err != nil {
		fmt.Printf("old: %q, new: %q, teamID: %s\n", in.CanonicalName,
			in.NewCanonicalName, in.TeamID)

		//return
		err = nil
	}

	hasAlias, err := tx.Has("teamAliases", "WHERE teamID=? AND name=?",
		in.TeamID, in.NewCanonicalName)
	if err != nil {
		return
	}

	if !hasAlias {
		// Добавляем новый alias
		_, err = tx.Insert(TeamAlias{
			Name:   in.NewCanonicalName,
			TeamID: in.TeamID,
		})
		if err != nil {
			return
		}
	}

	err = tx.Commit()
	return
}

func (s *Model) ListTeamZones(sportID int) (list []TeamZone, err error) {
	err = s.qx.ListBy(&list, `WHERE sportID=? ORDER BY name ASC`, sportID)
	if err != nil {
		return
	}
	return
}

func (s *Model) ListTeamCandidates(sportID int, name string) (matchIDs []string, err error) {
	name = NormalizeNameToAlias(name)

	err = s.qx.ListQuery(&matchIDs,
		`SELECT teamID FROM teamAliases WHERE sportID=? AND name=?`, sportID, name)
	if err != nil {
		return
	}
	return
}

func (s *Model) ListTeamsByZone(zoneID string) (list []Team, err error) {
	err = s.qx.ListBy(&list, `WHERE zoneID=? ORDER BY canonicalName ASC`, zoneID)
	if err != nil {
		return
	}
	return
}

func (s *Model) ListTeamAliases(teamID string) (list []TeamAlias, err error) {
	err = s.qx.ListBy(&list, `WHERE teamID=? ORDER BY name ASC`, teamID)
	if err != nil {
		return
	}
	return
}

func (s *Model) ListTeams() (list []Team, err error) {
	err = s.qx.List(&list)
	if err != nil {
		return
	}
	return
}
