package bunmodel

import (
	"fmt"
	"time"

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

type Server struct {
	bun.BaseModel        `bun:"table:servers,alias:server"`
	Key                  string       `bun:"key,nullzero,pk"`
	URL                  string       `bun:"url,nullzero"`
	Open                 bool         `bun:"open"`
	Special              bool         `bun:"special"`
	NumPlayers           int          `bun:"num_players"`
	NumTribes            int          `bun:"num_tribes"`
	NumVillages          int          `bun:"num_villages"`
	NumPlayerVillages    int          `bun:"num_player_villages"`
	NumBarbarianVillages int          `bun:"num_barbarian_villages"`
	NumBonusVillages     int          `bun:"num_bonus_villages"`
	Config               ServerConfig `bun:"config"`
	BuildingInfo         BuildingInfo `bun:"building_info"`
	UnitInfo             UnitInfo     `bun:"unit_info"`
	CreatedAt            time.Time    `bun:"created_at,nullzero"`
	// TODO: rename this column to player_data_synced_at
	PlayerDataUpdatedAt      time.Time `bun:"player_data_updated_at,nullzero"`
	PlayerSnapshotsCreatedAt time.Time `bun:"player_snapshots_created_at,nullzero"`
	// TODO: rename this column to tribe_data_synced_at
	TribeDataUpdatedAt      time.Time `bun:"tribe_data_updated_at,nullzero"`
	TribeSnapshotsCreatedAt time.Time `bun:"tribe_snapshots_created_at,nullzero"`
	// TODO: rename this column to village_data_synced_at
	VillageDataUpdatedAt time.Time `bun:"village_data_updated_at,nullzero"`
	// TODO: rename this column to ennoblement_data_synced_at
	EnnoblementDataUpdatedAt time.Time `bun:"ennoblement_data_updated_at,nullzero"`
	VersionCode              string    `bun:"version_code,nullzero"`
}

func (s Server) ToDomain() (domain.Server, error) {
	serverCfg, err := s.Config.ToDomain()
	if err != nil {
		return domain.Server{}, fmt.Errorf("couldn't construct domain.Server (key=%s): %w", s.Key, err)
	}

	buildingInfo, err := s.BuildingInfo.ToDomain()
	if err != nil {
		return domain.Server{}, fmt.Errorf("couldn't construct domain.Server (key=%s): %w", s.Key, err)
	}

	unitInfo, err := s.UnitInfo.ToDomain()
	if err != nil {
		return domain.Server{}, fmt.Errorf("couldn't construct domain.Server (key=%s): %w", s.Key, err)
	}

	converted, err := domain.UnmarshalServerFromDatabase(
		s.Key,
		s.VersionCode,
		s.URL,
		s.Open,
		s.Special,
		s.NumPlayers,
		s.NumTribes,
		s.NumVillages,
		s.NumPlayerVillages,
		s.NumBarbarianVillages,
		s.NumBonusVillages,
		serverCfg,
		buildingInfo,
		unitInfo,
		s.CreatedAt,
		s.PlayerDataUpdatedAt,
		s.PlayerSnapshotsCreatedAt,
		s.TribeDataUpdatedAt,
		s.TribeSnapshotsCreatedAt,
		s.VillageDataUpdatedAt,
		s.EnnoblementDataUpdatedAt,
	)
	if err != nil {
		return domain.Server{}, fmt.Errorf("couldn't construct domain.Server (key=%s): %w", s.Key, err)
	}

	return converted, nil
}

type Servers []Server

func (ss Servers) ToDomain() (domain.Servers, error) {
	res := make(domain.Servers, 0, len(ss))

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

		res = append(res, converted)
	}

	return res, nil
}
