package particle

import (
	"encoding/json"
	"errors"
	"time"
)

type ParticleType string

const (
	TypeStream ParticleType = "stream"
	TypeFolder ParticleType = "folder"
	TypeMedia  ParticleType = "media"
	TypeFile   ParticleType = "file"
	TypeText   ParticleType = "text"
	TypeQuest  ParticleType = "quest"
	TypePaper  ParticleType = "paper"
	// TypeThink  ParticleType = "think"
)

type VisibilityMode string

const (
	VisibilityNetworkAll VisibilityMode = "network_all"
	VisibilityCustom     VisibilityMode = "custom"
	VisibilityInherited  VisibilityMode = "inherited"
)

var ErrInvalidParticleType = errors.New("invalid particle type")
var ErrInvalidVisibilityMode = errors.New("invalid visibility mode")

func ParseParticleType(s string) (ParticleType, error) {
	switch s {
	case string(TypeStream):
		return TypeStream, nil
	case string(TypeFolder):
		return TypeFolder, nil
	case string(TypeMedia):
		return TypeMedia, nil
	case string(TypeFile):
		return TypeFile, nil
	case string(TypeText):
		return TypeText, nil
	case string(TypeQuest):
		return TypeQuest, nil
	case string(TypePaper):
		return TypePaper, nil
	default:
		return "", ErrInvalidParticleType
	}
}

func ParseVisibilityMode(s string) (VisibilityMode, error) {
	switch s {
	case "", string(VisibilityNetworkAll):
		return VisibilityNetworkAll, nil
	case string(VisibilityCustom):
		return VisibilityCustom, nil
	case string(VisibilityInherited):
		return VisibilityInherited, nil
	default:
		return "", ErrInvalidVisibilityMode
	}
}

type StreamStatus string

const (
	StreamStatusOpen   StreamStatus = "open"
	StreamStatusClosed StreamStatus = "closed"
)

type Particle struct {
	ID             string
	Type           ParticleType
	NetworkID      string
	ParentID       *string
	CreatedByEmail string
	Visibility     VisibilityMode
	Data           json.RawMessage
	UpdatedAt      time.Time
	CreatedAt      time.Time
}

type CreateInput struct {
	Type       ParticleType
	NetworkID  string
	ParentID   *string
	Data       json.RawMessage
	Members    []string // Only used when visibility is custom
	Visibility VisibilityMode
}

type ListFilter struct {
	Types []ParticleType
}

type Cursor struct {
	Position  string // particle ID or timestamp
	Direction string // "before" or "after"
}

type ParticleList struct {
	Particles  []*Particle
	HasMore    bool
	NextCursor *Cursor
	PrevCursor *Cursor
}

type StreamData struct {
	Name        string  `json:"name"`
	Status      string  `json:"status"` // "open" or "closed"
	Description *string `json:"description"`
}

type FolderData struct {
	Name  string  `json:"name"`
	Color *string `json:"color"`
}

type MediaData struct {
	ObjectID   string `json:"object_id"`
	MimeType   string `json:"mime_type"`
	DurationMs int    `json:"duration_ms"`
}

type FileData struct {
	ObjectID string `json:"object_id"`
	Filename string `json:"filename"`
	MimeType string `json:"mime_type"`
	Size     int64  `json:"size"` // bytes
}

type TextData struct {
	Content string `json:"content"`
}

type QuestData struct {
	Title       string  `json:"title"`
	Description string  `json:"description"`
	Done        bool    `json:"done"`
	Status      *string `json:"status"`
	AssignedTo  *string `json:"assigned_to,omitempty"` // email
	DueDate     *string `json:"due_date,omitempty"`    // ISO date
}

type PaperData struct {
	Title   string `json:"title"`
	Content string `json:"content"` // markdown
}

type AckInfo struct {
	Email   string
	AckedAt time.Time
}
