package bunmodel

import (
	"fmt"
	"time"

	"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
	"github.com/uptrace/bun"
)

type Player struct {
	bun.BaseModel `bun:"table:players,alias:player"`

	ID             int       `bun:"id,nullzero,pk"`
	ServerKey      string    `bun:"server_key,nullzero,pk"`
	Server         Server    `bun:"server,rel:belongs-to,join:server_key=key"`
	Name           string    `bun:"name,nullzero"`
	NumVillages    int       `bun:"num_villages"`
	Points         int       `bun:"points"`
	Rank           int       `bun:"rank"`
	TribeID        int       `bun:"tribe_id,nullzero"`
	Tribe          Tribe     `bun:"tribe,rel:belongs-to,join:tribe_id=id,join:server_key=server_key"`
	ProfileURL     string    `bun:"profile_url,nullzero"`
	BestRank       int       `bun:"best_rank"`
	BestRankAt     time.Time `bun:"best_rank_at,nullzero,default:CURRENT_TIMESTAMP"`
	MostPoints     int       `bun:"most_points"`
	MostPointsAt   time.Time `bun:"most_points_at,nullzero,default:CURRENT_TIMESTAMP"`
	MostVillages   int       `bun:"most_villages"`
	MostVillagesAt time.Time `bun:"most_villages_at,nullzero,default:CURRENT_TIMESTAMP"`
	LastActivityAt time.Time `bun:"last_activity_at,nullzero,default:CURRENT_TIMESTAMP"`
	CreatedAt      time.Time `bun:"created_at,nullzero,default:CURRENT_TIMESTAMP"`
	DeletedAt      time.Time `bun:"deleted_at,nullzero"`

	OpponentsDefeated
}

func (p Player) ToDomain() (domain.Player, error) {
	od, err := p.OpponentsDefeated.ToDomain()
	if err != nil {
		return domain.Player{}, fmt.Errorf(
			"couldn't construct domain.Player (id=%d,serverKey=%s): %w",
			p.ID,
			p.ServerKey,
			err,
		)
	}

	converted, err := domain.UnmarshalPlayerFromDatabase(
		p.ID,
		p.ServerKey,
		p.Name,
		p.NumVillages,
		p.Points,
		p.Rank,
		p.TribeID,
		od,
		p.ProfileURL,
		p.BestRank,
		p.BestRankAt,
		p.MostPoints,
		p.MostPointsAt,
		p.MostVillages,
		p.MostVillagesAt,
		p.LastActivityAt,
		p.CreatedAt,
		p.DeletedAt,
	)
	if err != nil {
		return domain.Player{}, fmt.Errorf(
			"couldn't construct domain.Player (id=%d,serverKey=%s): %w",
			p.ID,
			p.ServerKey,
			err,
		)
	}

	return converted, nil
}

type Players []Player

func (ps Players) ToDomain() (domain.Players, error) {
	res := make(domain.Players, 0, len(ps))

	for _, p := range ps {
		converted, err := p.ToDomain()
		if err != nil {
			return nil, err
		}

		res = append(res, converted)
	}

	return res, nil
}
