package main

import (
	"database/sql"
	"sync"
	"time"
)

var preliminaryRoundStages = []string{"prelim_r1", "prelim_r2", "prelim_r3"}
var finalRoundStages = []string{"final_r1", "final_r2"}
var tieBreakStages = []string{"prelim_tiebreak", "final_tiebreak"}

var scoreStages = append(append(append([]string{}, preliminaryRoundStages...), finalRoundStages...), tieBreakStages...)

type App struct {
	db       *sql.DB
	cfg      Config
	sessions *SessionStore
	events   *EventHub
}

type SessionStore struct {
	mu       sync.RWMutex
	tokens   map[string]time.Time
	duration time.Duration
}

type EventHub struct {
	mu          sync.RWMutex
	nextID      int
	subscribers map[int]chan struct{}
}

type CompetitionMeta struct {
	TitleAr string `json:"titleAr"`
	TitleEn string `json:"titleEn"`
}

type Player struct {
	ID        int    `json:"id"`
	NameAr    string `json:"nameAr"`
	NameEn    string `json:"nameEn"`
	GroupCode string `json:"groupCode"`
	ImageData string `json:"imageData"`
}

type RankingRow struct {
	PlayerID   int    `json:"playerId"`
	NameAr     string `json:"nameAr"`
	NameEn     string `json:"nameEn"`
	GroupCode  string `json:"groupCode"`
	ImageData  string `json:"imageData"`
	Score      int    `json:"score"`
	TieBreak   int    `json:"tieBreak"`
	Rank       int    `json:"rank"`
	Seed       int    `json:"seed"`
	FinalGroup int    `json:"finalGroup"`
}

type TieBreakInfo struct {
	Required  bool  `json:"required"`
	Resolved  bool  `json:"resolved"`
	Slots     int   `json:"slots"`
	PlayerIDs []int `json:"playerIds"`
}

type DerivedState struct {
	PreliminaryRanking RankingBundle `json:"preliminaryRanking"`
	Finalists          []RankingRow  `json:"finalists"`
	FinalGroups        FinalGroups   `json:"finalGroups"`
	FinalRanking       RankingBundle `json:"finalRanking"`
	Podium             []RankingRow  `json:"podium"`
}

type RankingBundle struct {
	Rows       []RankingRow `json:"rows"`
	TieBreak   TieBreakInfo `json:"tieBreak"`
	Unresolved bool         `json:"unresolved"`
}

type FinalGroups struct {
	Group1 []RankingRow `json:"group1"`
	Group2 []RankingRow `json:"group2"`
}

type StateResponse struct {
	Competition CompetitionMeta              `json:"competition"`
	Players     []Player                     `json:"players"`
	Scores      map[string]map[string]int    `json:"scores"`
	ScoreProofs map[string]map[string]string `json:"scoreProofs,omitempty"`
	Settings    AppSettings                  `json:"settings"`
	Derived     DerivedState                 `json:"derived"`
	ServerTime  string                       `json:"serverTime"`
}

type AppSettings struct {
	ViewProofInView bool             `json:"viewProofInView"`
	LiveMode        LiveModeSettings `json:"liveMode"`
}

type LiveModeSettings struct {
	ActiveView          string `json:"activeView"`
	ShowGroupLive       bool   `json:"showGroupLive"`
	GroupDisplayMode    string `json:"groupDisplayMode"`
	GroupFixedCode      string `json:"groupFixedCode"`
	ShowPrelimTie       bool   `json:"showPrelimTie"`
	ShowPrelimOverall   bool   `json:"showPrelimOverall"`
	ShowFinalGroups     bool   `json:"showFinalGroups"`
	FinalDisplayMode    string `json:"finalDisplayMode"`
	FinalFixedGroup     int    `json:"finalFixedGroup"`
	ShowFinalTie        bool   `json:"showFinalTie"`
	ShowPodium          bool   `json:"showPodium"`
	RotationIntervalSec int    `json:"rotationIntervalSec"`
	RotationPlayerCount int    `json:"rotationPlayerCount"`
}

type AdminLoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type PlayerCreateRequest struct {
	NameAr    string `json:"nameAr"`
	NameEn    string `json:"nameEn"`
	GroupCode string `json:"groupCode"`
}

type PlayerUpdateRequest struct {
	NameAr     *string `json:"nameAr"`
	NameEn     *string `json:"nameEn"`
	GroupCode  *string `json:"groupCode"`
	ImageData  *string `json:"imageData"`
	ClearImage bool    `json:"clearImage"`
}

type ScoreUpdateRequest struct {
	Score int `json:"score"`
}

type ScoreProofUpdateRequest struct {
	ImageData string `json:"imageData"`
}

type AdminSettingsUpdateRequest struct {
	ViewProofInView *bool                          `json:"viewProofInView"`
	LiveMode        *LiveModeSettingsUpdateRequest `json:"liveMode"`
}

type LiveModeSettingsUpdateRequest struct {
	ActiveView          *string `json:"activeView"`
	ShowGroupLive       *bool   `json:"showGroupLive"`
	GroupDisplayMode    *string `json:"groupDisplayMode"`
	GroupFixedCode      *string `json:"groupFixedCode"`
	ShowPrelimTie       *bool   `json:"showPrelimTie"`
	ShowPrelimOverall   *bool   `json:"showPrelimOverall"`
	ShowFinalGroups     *bool   `json:"showFinalGroups"`
	FinalDisplayMode    *string `json:"finalDisplayMode"`
	FinalFixedGroup     *int    `json:"finalFixedGroup"`
	ShowFinalTie        *bool   `json:"showFinalTie"`
	ShowPodium          *bool   `json:"showPodium"`
	RotationIntervalSec *int    `json:"rotationIntervalSec"`
	RotationPlayerCount *int    `json:"rotationPlayerCount"`
}

type ResetStageRequest struct {
	ResetProofs bool `json:"resetProofs"`
}

type AutoGroupPlayersRequest struct {
	Groups []string `json:"groups"`
}

type ScoreAdviceResponse struct {
	Stage        string `json:"stage"`
	PlayerID     int    `json:"playerId"`
	AdvisedScore int    `json:"advisedScore"`
	Reason       string `json:"reason"`
	GeneratedAt  string `json:"generatedAt"`
}
