package state

import (
	"errors"
	"sync"
	"time"
)

const (
	RoleParticipant = "participant"
	RoleViewer      = "viewer"

	RevealModeManual  = "manual"
	RevealModeAutoAll = "all_voted"
)

var (
	ErrRoomNotFound        = errors.New("room not found")
	ErrParticipantNotFound = errors.New("participant not found")
	ErrUnauthorized        = errors.New("unauthorized")
	ErrRoomFull            = errors.New("room is full")
	ErrInvalidRole         = errors.New("invalid role")
	ErrSpectatorsBlocked   = errors.New("spectators are not allowed")
	ErrPasswordRequired    = errors.New("password required or invalid")
	ErrInvalidCard         = errors.New("invalid card")
)

type RoomSettings struct {
	RoomName         string   `json:"roomName"`
	MaxPeople        int      `json:"maxPeople"`
	Cards            []string `json:"cards"`
	AllowSpectators  bool     `json:"allowSpectators"`
	AnonymousVoting  bool     `json:"anonymousVoting"`
	AutoReset        bool     `json:"autoReset"`
	RevealMode       string   `json:"revealMode"`
	VotingTimeoutSec int      `json:"votingTimeoutSec"`
	PasswordSalt     string   `json:"passwordSalt,omitempty"`
	PasswordHash     string   `json:"passwordHash,omitempty"`
}

type Participant struct {
	ID        string    `json:"id"`
	Username  string    `json:"username"`
	Role      string    `json:"role"`
	IsAdmin   bool      `json:"isAdmin"`
	Connected bool      `json:"connected"`
	HasVoted  bool      `json:"hasVoted"`
	VoteValue string    `json:"voteValue,omitempty"`
	JoinedAt  time.Time `json:"joinedAt"`
	UpdatedAt time.Time `json:"updatedAt"`
}

type RoundState struct {
	Revealed bool `json:"revealed"`
}

type persistedRoom struct {
	ID           string         `json:"id"`
	AdminToken   string         `json:"adminToken"`
	CreatedAt    time.Time      `json:"createdAt"`
	UpdatedAt    time.Time      `json:"updatedAt"`
	Settings     RoomSettings   `json:"settings"`
	Round        RoundState     `json:"round"`
	Participants []*Participant `json:"participants"`
}

type subscriber struct {
	participantID string
	ch            chan []byte
}

type Room struct {
	ID           string
	AdminToken   string
	CreatedAt    time.Time
	UpdatedAt    time.Time
	Settings     RoomSettings
	Round        RoundState
	Participants map[string]*Participant

	mu          sync.RWMutex
	subscribers map[string]*subscriber
}

type CreateRoomInput struct {
	RoomName         string
	CreatorUsername  string
	MaxPeople        int
	Cards            []string
	AllowSpectators  bool
	AnonymousVoting  bool
	AutoReset        bool
	RevealMode       string
	VotingTimeoutSec int
	Password         string
}

type JoinRoomInput struct {
	ParticipantID string
	Username      string
	Role          string
	Password      string
	AdminToken    string
}

type CreateRoomResult struct {
	RoomID               string `json:"roomId"`
	CreatorParticipantID string `json:"creatorParticipantId"`
	AdminToken           string `json:"adminToken"`
	ParticipantLink      string `json:"participantLink"`
	AdminLink            string `json:"adminLink"`
}

type JoinRoomResult struct {
	ParticipantID string `json:"participantId"`
	IsAdmin       bool   `json:"isAdmin"`
	Role          string `json:"role"`
	Username      string `json:"username"`
}

type PublicParticipant struct {
	ID        string `json:"id"`
	Username  string `json:"username"`
	Role      string `json:"role"`
	IsAdmin   bool   `json:"isAdmin"`
	Connected bool   `json:"connected"`
	HasVoted  bool   `json:"hasVoted"`
	VoteValue string `json:"voteValue,omitempty"`
}

type RoomLinks struct {
	ParticipantLink string `json:"participantLink"`
	AdminLink       string `json:"adminLink,omitempty"`
}

type PublicRoomState struct {
	RoomID            string              `json:"roomId"`
	RoomName          string              `json:"roomName"`
	Cards             []string            `json:"cards"`
	Revealed          bool                `json:"revealed"`
	RevealMode        string              `json:"revealMode"`
	MaxPeople         int                 `json:"maxPeople"`
	AllowSpectators   bool                `json:"allowSpectators"`
	AnonymousVoting   bool                `json:"anonymousVoting"`
	AutoReset         bool                `json:"autoReset"`
	VotingTimeoutSec  int                 `json:"votingTimeoutSec"`
	Participants      []PublicParticipant `json:"participants"`
	SelfParticipantID string              `json:"selfParticipantId"`
	ViewerIsAdmin     bool                `json:"viewerIsAdmin"`
	Links             RoomLinks           `json:"links"`
}
