package service

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/TopherMayor/unified-media-manager/internal/db"
)

// CalendarEvent represents a single event on the calendar.
type CalendarEvent struct {
	ID        int64  `json:"id"`
	MediaType string `json:"media_type"`
	Title     string `json:"title"`
	Date      string `json:"date"`
	Year      *int   `json:"year,omitempty"`
	Status    string `json:"status"`
	PosterURL string `json:"poster_url,omitempty"`
}

// CalendarService queries monitored media by release date for calendar views.
type CalendarService struct {
	db *db.DB
}

// NewCalendarService creates a new CalendarService.
func NewCalendarService(database *db.DB) *CalendarService {
	return &CalendarService{db: database}
}

type posterImage struct {
	URL  string `json:"url"`
	Type string `json:"type"`
}

// EventsByMonth returns all monitored media with release dates in the given month.
func (s *CalendarService) EventsByMonth(ctx context.Context, year int, month time.Month) ([]CalendarEvent, error) {
	startDate := time.Date(year, month, 1, 0, 0, 0, 0, time.UTC)
	endDate := startDate.AddDate(0, 1, 0).Add(-time.Nanosecond)

	query := `SELECT id, media_type, title, release_date, year, status, images
		FROM media
		WHERE monitored = true AND deleted_at IS NULL
			AND release_date IS NOT NULL
			AND release_date BETWEEN $1 AND $2
		ORDER BY release_date`

	rows, err := s.db.Pool.Query(ctx, query, startDate, endDate)
	if err != nil {
		return nil, fmt.Errorf("query calendar events: %w", err)
	}
	defer rows.Close()

	var events []CalendarEvent
	for rows.Next() {
		var id int64
		var mediaType, title, status string
		var releaseDate time.Time
		var yearVal *int
		var imagesJSON []byte

		if err := rows.Scan(&id, &mediaType, &title, &releaseDate, &yearVal, &status, &imagesJSON); err != nil {
			continue
		}

		posterURL := extractPosterURL(imagesJSON)

		events = append(events, CalendarEvent{
			ID:        id,
			MediaType: mediaType,
			Title:     title,
			Date:      releaseDate.Format("2006-01-02"),
			Year:      yearVal,
			Status:    status,
			PosterURL: posterURL,
		})
	}

	if events == nil {
		events = []CalendarEvent{}
	}

	return events, nil
}

// extractPosterURL parses the images JSONB and returns the first poster URL.
func extractPosterURL(imagesJSON []byte) string {
	if len(imagesJSON) == 0 {
		return ""
	}
	var images []posterImage
	if err := json.Unmarshal(imagesJSON, &images); err != nil {
		return ""
	}
	for _, img := range images {
		if img.Type == "poster" && img.URL != "" {
			return img.URL
		}
	}
	return ""
}
