package apimodel

import (
	"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
)

func NewPlayerOpponentsDefeated(od domain.OpponentsDefeated) PlayerOpponentsDefeated {
	return PlayerOpponentsDefeated{
		RankAtt:    od.RankAtt(),
		RankDef:    od.RankDef(),
		RankSup:    od.RankSup(),
		RankTotal:  od.RankTotal(),
		ScoreAtt:   od.ScoreAtt(),
		ScoreDef:   od.ScoreDef(),
		ScoreSup:   od.ScoreSup(),
		ScoreTotal: od.ScoreTotal(),
	}
}

func NewPlayer(withRelations domain.PlayerWithRelations) Player {
	p := withRelations.Player()

	converted := Player{
		BestRank:          p.BestRank(),
		BestRankAt:        p.BestRankAt(),
		CreatedAt:         p.CreatedAt(),
		Id:                p.ID(),
		LastActivityAt:    p.LastActivityAt(),
		MostPoints:        p.MostPoints(),
		MostPointsAt:      p.MostPointsAt(),
		MostVillages:      p.MostVillages(),
		MostVillagesAt:    p.MostVillagesAt(),
		Name:              p.Name(),
		NumVillages:       p.NumVillages(),
		OpponentsDefeated: NewPlayerOpponentsDefeated(p.OD()),
		Points:            p.Points(),
		ProfileUrl:        p.ProfileURL().String(),
		Rank:              p.Rank(),
		Tribe:             NewNullTribeMeta(withRelations.Tribe()),
	}

	if deletedAt := p.DeletedAt(); !deletedAt.IsZero() {
		converted.DeletedAt = &deletedAt
	}

	return converted
}

func NewPlayerWithServer(withRelations domain.PlayerWithRelations) PlayerWithServer {
	p := withRelations.Player()

	converted := PlayerWithServer{
		BestRank:          p.BestRank(),
		BestRankAt:        p.BestRankAt(),
		CreatedAt:         p.CreatedAt(),
		Id:                p.ID(),
		LastActivityAt:    p.LastActivityAt(),
		MostPoints:        p.MostPoints(),
		MostPointsAt:      p.MostPointsAt(),
		MostVillages:      p.MostVillages(),
		MostVillagesAt:    p.MostVillagesAt(),
		Name:              p.Name(),
		NumVillages:       p.NumVillages(),
		OpponentsDefeated: NewPlayerOpponentsDefeated(p.OD()),
		Points:            p.Points(),
		ProfileUrl:        p.ProfileURL().String(),
		Rank:              p.Rank(),
		Tribe:             NewNullTribeMeta(withRelations.Tribe()),
		Server:            NewServerMeta(withRelations.Server()),
	}

	if deletedAt := p.DeletedAt(); !deletedAt.IsZero() {
		converted.DeletedAt = &deletedAt
	}

	return converted
}

func NewPlayerMeta(withRelations domain.PlayerMetaWithRelations) PlayerMeta {
	p := withRelations.Player()
	return PlayerMeta{
		Id:         p.ID(),
		Name:       p.Name(),
		ProfileUrl: p.ProfileURL().String(),
		Tribe:      NewNullTribeMeta(withRelations.Tribe()),
	}
}

func NewNullPlayerMeta(p domain.NullPlayerMetaWithRelations) *PlayerMeta {
	if !p.Valid {
		return nil
	}

	converted := NewPlayerMeta(p.V)

	return &converted
}

func NewListPlayersResponse(res domain.ListPlayersWithRelationsResult) ListPlayersResponse {
	players := res.Players()

	resp := ListPlayersResponse{
		Data: make([]Player, 0, len(players)),
		Cursor: Cursor{
			Next: res.Next().Encode(),
			Self: res.Self().Encode(),
		},
	}

	for _, p := range players {
		resp.Data = append(resp.Data, NewPlayer(p))
	}

	return resp
}

func NewGetPlayerResponse(p domain.PlayerWithRelations) GetPlayerResponse {
	return GetPlayerResponse{
		Data: NewPlayer(p),
	}
}

func NewListPlayersWithServersResponse(res domain.ListPlayersWithRelationsResult) ListPlayersWithServersResponse {
	players := res.Players()

	resp := ListPlayersWithServersResponse{
		Data: make([]PlayerWithServer, 0, len(players)),
		Cursor: Cursor{
			Next: res.Next().Encode(),
			Self: res.Self().Encode(),
		},
	}

	for _, p := range players {
		resp.Data = append(resp.Data, NewPlayerWithServer(p))
	}

	return resp
}
