package models

import (
	"cmp"
	"slices"
	"time"

	"github.com/mergestat/timediff"
)

type MapScoreList []MapScore

type Capture struct {
	ID        int64        `bun:",pk,autoincrement"`
	Host      string       `bun:",notnull"`
	Port      string       `bun:",notnull"`
	Name      string       `bun:",unique,notnull"`
	Active    bool         `bun:",notnull"`
	Start     time.Time    `bun:",notnull,default:current_timestamp"`
	MapScores MapScoreList `bun:"rel:has-many,join:id=capture_id"`
}

type MapScore struct {
	ID        int64     `bun:",pk,autoincrement"`
	CaptureID int64     `bun:"capture_id"`
	StartTime time.Time `bun:",notnull"`
	Map       string    `bun:",notnull"`
	ScoreList []Score   `bun:"rel:has-many,join:id=mapscore_id"`
}

type Score struct {
	Name       string `bun:",pk,notnull"`
	MapScoreID int64  `bun:"mapscore_id,pk,notnull"`
	Score      int
	Ping       int
}

type ResultTable struct {
	Header []ResultTableHeader
	Rows   []ResultTableRow
}

type ResultTableHeader struct {
	Title    string
	Subtitle string
}

type ResultTableRow struct {
	Name       string
	Total      int
	Individual []int
}

func (msl MapScoreList) BuildTable() *ResultTable {
	rt := &ResultTable{
		Header: []ResultTableHeader{{Title: "Name"}, {Title: "Total"}},
	}

	userMapRows := make(map[string]int)

	for mapIndex, mapScore := range msl {
		rt.Header = append(rt.Header, ResultTableHeader{
			Title:    mapScore.Map,
			Subtitle: timediff.TimeDiff(mapScore.StartTime),
		})
		for _, score := range mapScore.ScoreList {
			if score.Ping > 0 {
				if _, ok := userMapRows[score.Name]; !ok {
					rt.Rows = append(rt.Rows, ResultTableRow{
						Name:       score.Name,
						Total:      0,
						Individual: make([]int, len(msl)),
					})

					userMapRows[score.Name] = len(rt.Rows) - 1
				}

				row := userMapRows[score.Name]
				rt.Rows[row].Total = rt.Rows[row].Total + score.Score
				rt.Rows[row].Individual[mapIndex] = score.Score
			}
		}
	}

	slices.SortFunc(rt.Rows, func(a, b ResultTableRow) int {
		return cmp.Compare(b.Total, a.Total)
	})

	return rt
}
