package bunmodel

import (
	"fmt"
	"time"

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

type TribeChange struct {
	bun.BaseModel `bun:"table:tribe_changes,alias:tc"`

	ID         int       `bun:"id,pk,autoincrement,identity"`
	ServerKey  string    `bun:"server_key,nullzero"`
	PlayerID   int       `bun:"player_id,nullzero"`
	Player     Player    `bun:"player,rel:belongs-to,join:player_id=id,join:server_key=server_key"`
	NewTribeID int       `bun:"new_tribe_id,nullzero"`
	NewTribe   Tribe     `bun:"new_tribe,rel:belongs-to,join:new_tribe_id=id,join:server_key=server_key"`
	OldTribeID int       `bun:"old_tribe_id,nullzero"`
	OldTribe   Tribe     `bun:"old_tribe,rel:belongs-to,join:old_tribe_id=id,join:server_key=server_key"`
	CreatedAt  time.Time `bun:"created_at,nullzero"`
}

func (tc TribeChange) ToDomain() (domain.TribeChange, error) {
	converted, err := domain.UnmarshalTribeChangeFromDatabase(
		tc.ID,
		tc.ServerKey,
		tc.PlayerID,
		tc.OldTribeID,
		tc.NewTribeID,
		tc.CreatedAt,
	)
	if err != nil {
		return domain.TribeChange{}, fmt.Errorf(
			"couldn't construct domain.TribeChange (id=%d): %w",
			tc.ID,
			err,
		)
	}

	return converted, nil
}

//nolint:gocyclo
func (tc TribeChange) ToDomainWithRelations() (domain.TribeChangeWithRelations, error) {
	converted, err := tc.ToDomain()
	if err != nil {
		return domain.TribeChangeWithRelations{}, err
	}

	player, err := tc.Player.ToMeta()
	if err != nil {
		return domain.TribeChangeWithRelations{}, err
	}

	var oldTribe domain.NullTribeMeta
	if tc.OldTribe.ID > 0 {
		oldTribe.Valid = true
		oldTribe.V, err = tc.OldTribe.ToMeta()
		if err != nil {
			return domain.TribeChangeWithRelations{}, err
		}
	}

	var newTribe domain.NullTribeMeta
	if tc.NewTribe.ID > 0 {
		newTribe.Valid = true
		newTribe.V, err = tc.NewTribe.ToMeta()
		if err != nil {
			return domain.TribeChangeWithRelations{}, err
		}
	}

	return converted.WithRelations(player, oldTribe, newTribe), nil
}

type TribeChanges []TribeChange

func (tcs TribeChanges) ToDomain() (domain.TribeChanges, error) {
	return sliceToDomain(tcs)
}

func (tcs TribeChanges) ToDomainWithRelations() (domain.TribeChangesWithRelations, error) {
	return sliceToDomainWithRelations(tcs)
}
