// Package domain contains the core value types shared across all packages
// in this module. It has zero internal imports — only the standard library.
// Every other package imports domain; domain imports nothing from this module.
package domain

import "time"

// ── Book types ────────────────────────────────────────────────────────────────

// BookMeta carries all bibliographic information about a novel.
type BookMeta struct {
	Slug          string   `json:"slug"`
	Title         string   `json:"title"`
	Author        string   `json:"author"`
	Cover         string   `json:"cover,omitempty"`
	Status        string   `json:"status,omitempty"`
	Genres        []string `json:"genres,omitempty"`
	Summary       string   `json:"summary,omitempty"`
	TotalChapters int      `json:"total_chapters,omitempty"`
	SourceURL     string   `json:"source_url"`
	Ranking       int      `json:"ranking,omitempty"`
	Rating        float64  `json:"rating,omitempty"`
	// MetaUpdated is the Unix timestamp (seconds) when the book record was last
	// updated in PocketBase. Populated on read; not sent on write (PocketBase
	// manages its own updated field).
	MetaUpdated int64 `json:"meta_updated,omitempty"`
}

// CatalogueEntry is a lightweight book reference returned by catalogue pages.
type CatalogueEntry struct {
	Slug  string `json:"slug"`
	Title string `json:"title"`
	URL   string `json:"url"`
}

// ChapterRef is a reference to a single chapter returned by chapter-list pages.
type ChapterRef struct {
	Number int    `json:"number"`
	Title  string `json:"title"`
	URL    string `json:"url"`
	Volume int    `json:"volume,omitempty"`
}

// Chapter contains the fully-extracted text of a single chapter.
type Chapter struct {
	Ref  ChapterRef `json:"ref"`
	Text string     `json:"text"`
}

// RankingItem represents a single entry in the novel ranking list.
type RankingItem struct {
	Rank      int       `json:"rank"`
	Slug      string    `json:"slug"`
	Title     string    `json:"title"`
	Author    string    `json:"author,omitempty"`
	Cover     string    `json:"cover,omitempty"`
	Status    string    `json:"status,omitempty"`
	Genres    []string  `json:"genres,omitempty"`
	SourceURL string    `json:"source_url,omitempty"`
	Updated   time.Time `json:"updated,omitempty"`
}

// ── Voice types ───────────────────────────────────────────────────────────────

// Voice describes a single text-to-speech voice available in the system.
type Voice struct {
	// ID is the voice identifier passed to TTS clients (e.g. "af_bella", "alba").
	ID string `json:"id"`
	// Engine is "kokoro" or "pocket-tts".
	Engine string `json:"engine"`
	// Lang is the primary language tag (e.g. "en-us", "en-gb", "en", "es", "fr").
	Lang string `json:"lang"`
	// Gender is "f" or "m".
	Gender string `json:"gender"`
}

// ── Storage record types ──────────────────────────────────────────────────────

// ChapterInfo is a lightweight chapter descriptor stored in the index.
type ChapterInfo struct {
	Number int    `json:"number"`
	Title  string `json:"title"`
	Date   string `json:"date,omitempty"`
}

// ReadingProgress holds a single user's reading position for one book.
type ReadingProgress struct {
	Slug      string    `json:"slug"`
	Chapter   int       `json:"chapter"`
	UpdatedAt time.Time `json:"updated_at"`
}

// ── Task record types ─────────────────────────────────────────────────────────

// TaskStatus enumerates the lifecycle states of any task.
type TaskStatus string

const (
	TaskStatusPending   TaskStatus = "pending"
	TaskStatusRunning   TaskStatus = "running"
	TaskStatusDone      TaskStatus = "done"
	TaskStatusFailed    TaskStatus = "failed"
	TaskStatusCancelled TaskStatus = "cancelled"
)

// ScrapeTask represents a book-scraping job stored in PocketBase.
type ScrapeTask struct {
	ID              string     `json:"id"`
	Kind            string     `json:"kind"`       // "catalogue" | "book" | "book_range"
	TargetURL       string     `json:"target_url"` // non-empty for single-book tasks
	FromChapter     int        `json:"from_chapter,omitempty"`
	ToChapter       int        `json:"to_chapter,omitempty"`
	WorkerID        string     `json:"worker_id,omitempty"`
	Status          TaskStatus `json:"status"`
	BooksFound      int        `json:"books_found"`
	ChaptersScraped int        `json:"chapters_scraped"`
	ChaptersSkipped int        `json:"chapters_skipped"`
	Errors          int        `json:"errors"`
	Started         time.Time  `json:"started"`
	Finished        time.Time  `json:"finished,omitempty"`
	ErrorMessage    string     `json:"error_message,omitempty"`
}

// ScrapeResult is the outcome reported by the runner after finishing a ScrapeTask.
type ScrapeResult struct {
	BooksFound      int    `json:"books_found"`
	ChaptersScraped int    `json:"chapters_scraped"`
	ChaptersSkipped int    `json:"chapters_skipped"`
	Errors          int    `json:"errors"`
	ErrorMessage    string `json:"error_message,omitempty"`
}

// AudioTask represents an audio-generation job stored in PocketBase.
type AudioTask struct {
	ID           string     `json:"id"`
	CacheKey     string     `json:"cache_key"` // "slug/chapter/voice"
	Slug         string     `json:"slug"`
	Chapter      int        `json:"chapter"`
	Voice        string     `json:"voice"`
	WorkerID     string     `json:"worker_id,omitempty"`
	Status       TaskStatus `json:"status"`
	ErrorMessage string     `json:"error_message,omitempty"`
	Started      time.Time  `json:"started"`
	Finished     time.Time  `json:"finished,omitempty"`
}

// AudioResult is the outcome reported by the runner after finishing an AudioTask.
type AudioResult struct {
	ObjectKey    string `json:"object_key,omitempty"`
	ErrorMessage string `json:"error_message,omitempty"`
}

// TranslationTask represents a machine-translation job stored in PocketBase.
type TranslationTask struct {
	ID           string     `json:"id"`
	CacheKey     string     `json:"cache_key"` // "{slug}/{chapter}/{lang}"
	Slug         string     `json:"slug"`
	Chapter      int        `json:"chapter"`
	Lang         string     `json:"lang"`
	WorkerID     string     `json:"worker_id,omitempty"`
	Status       TaskStatus `json:"status"`
	ErrorMessage string     `json:"error_message,omitempty"`
	Started      time.Time  `json:"started"`
	Finished     time.Time  `json:"finished,omitempty"`
}

// TranslationResult is the outcome reported by the runner after finishing a TranslationTask.
type TranslationResult struct {
	ObjectKey    string `json:"object_key,omitempty"`
	ErrorMessage string `json:"error_message,omitempty"`
}

// ImportTask represents a PDF/EPUB import job stored in PocketBase.
type ImportTask struct {
	ID               string     `json:"id"`
	Slug             string     `json:"slug"` // derived from filename
	Title            string     `json:"title"`
	FileName         string     `json:"file_name"`
	FileType         string     `json:"file_type"` // "pdf" or "epub"
	WorkerID         string     `json:"worker_id,omitempty"`
	InitiatorUserID  string     `json:"initiator_user_id,omitempty"` // PocketBase user ID who submitted the import
	Status           TaskStatus `json:"status"`
	ChaptersDone     int        `json:"chapters_done"`
	ChaptersTotal    int        `json:"chapters_total"`
	ErrorMessage     string     `json:"error_message,omitempty"`
	Started          time.Time  `json:"started"`
	Finished         time.Time  `json:"finished,omitempty"`
}

// ImportResult is the outcome reported by the runner after finishing an ImportTask.
type ImportResult struct {
	Slug             string `json:"slug,omitempty"`
	ChaptersImported int    `json:"chapters_imported"`
	ErrorMessage     string `json:"error_message,omitempty"`
}

// AIJob represents an AI generation task tracked in PocketBase (ai_jobs collection).
type AIJob struct {
	ID string `json:"id"`
	// Kind is one of: "chapter-names", "batch-covers", "chapter-covers", "refresh-metadata".
	Kind string `json:"kind"`
	// Slug is the book slug for per-book jobs; empty for catalogue-wide jobs.
	Slug   string     `json:"slug"`
	Status TaskStatus `json:"status"`
	// FromItem is the first item to process (chapter number, or 0-based book index).
	// 0 = start from the beginning.
	FromItem int `json:"from_item"`
	// ToItem is the last item to process (inclusive). 0 = process all.
	ToItem int `json:"to_item"`
	// ItemsDone is the cumulative count of successfully processed items.
	ItemsDone int `json:"items_done"`
	// ItemsTotal is the total number of items in this job.
	ItemsTotal int `json:"items_total"`
	Model      string `json:"model"`
	// Payload is a JSON-encoded string with job-specific parameters
	// (e.g. naming pattern for chapter-names, num_steps for batch-covers).
	Payload      string    `json:"payload"`
	ErrorMessage string    `json:"error_message,omitempty"`
	Started      time.Time `json:"started,omitempty"`
	Finished     time.Time `json:"finished,omitempty"`
	HeartbeatAt  time.Time `json:"heartbeat_at,omitempty"`
}
