package bunmodel

import (
	"fmt"
	"time"

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

var VillageMetaColumns = []string{"id", "name", "profile_url", "x", "y", "continent"}

type Village struct {
	bun.BaseModel `bun:"table:villages,alias:village"`

	ID         int       `bun:"id,nullzero,pk"`
	ServerKey  string    `bun:"server_key,nullzero,pk"`
	Name       string    `bun:"name,nullzero"`
	Points     int       `bun:"points"`
	X          int       `bun:"x"`
	Y          int       `bun:"y"`
	Continent  string    `bun:"continent"`
	Bonus      int       `bun:"bonus"`
	PlayerID   int       `bun:"player_id,nullzero"`
	Player     Player    `bun:"player,rel:belongs-to,join:player_id=id,join:server_key=server_key"`
	ProfileURL string    `bun:"profile_url,nullzero"`
	CreatedAt  time.Time `bun:"created_at,nullzero"`
}

func (v Village) ToDomain() (domain.Village, error) {
	converted, err := domain.UnmarshalVillageFromDatabase(
		v.ID,
		v.ServerKey,
		v.Name,
		v.Points,
		v.X,
		v.Y,
		v.Continent,
		v.Bonus,
		v.PlayerID,
		v.ProfileURL,
		v.CreatedAt,
	)
	if err != nil {
		return domain.Village{}, fmt.Errorf(
			"couldn't construct domain.Village (id=%d,serverKey=%s): %w",
			v.ID,
			v.ServerKey,
			err,
		)
	}

	return converted, nil
}

func (v Village) ToDomainWithRelations() (domain.VillageWithRelations, error) {
	converted, err := v.ToDomain()
	if err != nil {
		return domain.VillageWithRelations{}, err
	}

	var player domain.NullPlayerMetaWithRelations
	if v.Player.ID > 0 {
		player.Valid = true
		player.V, err = v.Player.ToMetaWithRelations()
		if err != nil {
			return domain.VillageWithRelations{}, err
		}
	}

	return converted.WithRelations(player), nil
}

func (v Village) ToMeta() (domain.VillageMeta, error) {
	converted, err := domain.UnmarshalVillageMetaFromDatabase(
		v.ID,
		v.Name,
		v.X,
		v.Y,
		v.Continent,
		v.ProfileURL,
	)
	if err != nil {
		return domain.VillageMeta{}, fmt.Errorf(
			"couldn't construct domain.VillageMeta (id=%d,serverKey=%s): %w",
			v.ID,
			v.ServerKey,
			err,
		)
	}
	return converted, nil
}

type Villages []Village

func (vs Villages) ToDomain() (domain.Villages, error) {
	return sliceToDomain(vs)
}

func (vs Villages) ToDomainWithRelations() (domain.VillagesWithRelations, error) {
	return sliceToDomainWithRelations(vs)
}
