package monetization

import (
	"context"
	"errors"
	"tercul/internal/domain"
	"tercul/internal/platform/log"
)

// MonetizationQueries contains the query handlers for monetization.
type MonetizationQueries struct {
	repo          domain.MonetizationRepository
	workRepo      domain.WorkRepository
	authorRepo    domain.AuthorRepository
	bookRepo      domain.BookRepository
	publisherRepo domain.PublisherRepository
	sourceRepo    domain.SourceRepository
}

// NewMonetizationQueries creates a new MonetizationQueries handler.
func NewMonetizationQueries(repo domain.MonetizationRepository, workRepo domain.WorkRepository, authorRepo domain.AuthorRepository, bookRepo domain.BookRepository, publisherRepo domain.PublisherRepository, sourceRepo domain.SourceRepository) *MonetizationQueries {
	return &MonetizationQueries{repo: repo, workRepo: workRepo, authorRepo: authorRepo, bookRepo: bookRepo, publisherRepo: publisherRepo, sourceRepo: sourceRepo}
}

// GetMonetizationByID retrieves a monetization by ID.
func (q *MonetizationQueries) GetMonetizationByID(ctx context.Context, id uint) (*domain.Monetization, error) {
	if id == 0 {
		return nil, errors.New("invalid monetization ID")
	}
	log.FromContext(ctx).With("id", id).Debug("Getting monetization by ID")
	return q.repo.GetByID(ctx, id)
}

// ListMonetizations retrieves all monetizations.
func (q *MonetizationQueries) ListMonetizations(ctx context.Context) ([]domain.Monetization, error) {
	log.FromContext(ctx).Debug("Listing all monetizations")
	return q.repo.ListAll(ctx)
}

func (q *MonetizationQueries) GetMonetizationsForWork(ctx context.Context, workID uint) ([]*domain.Monetization, error) {
	log.FromContext(ctx).With("work_id", workID).Debug("Getting monetizations for work")
	workRecord, err := q.workRepo.GetByIDWithOptions(ctx, workID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
	if err != nil {
		return nil, err
	}
	return workRecord.Monetizations, nil
}

func (q *MonetizationQueries) GetMonetizationsForAuthor(ctx context.Context, authorID uint) ([]*domain.Monetization, error) {
	log.FromContext(ctx).With("author_id", authorID).Debug("Getting monetizations for author")
	author, err := q.authorRepo.GetByIDWithOptions(ctx, authorID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
	if err != nil {
		return nil, err
	}
	return author.Monetizations, nil
}

func (q *MonetizationQueries) GetMonetizationsForBook(ctx context.Context, bookID uint) ([]*domain.Monetization, error) {
	log.FromContext(ctx).With("book_id", bookID).Debug("Getting monetizations for book")
	book, err := q.bookRepo.GetByIDWithOptions(ctx, bookID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
	if err != nil {
		return nil, err
	}
	return book.Monetizations, nil
}

func (q *MonetizationQueries) GetMonetizationsForPublisher(ctx context.Context, publisherID uint) ([]*domain.Monetization, error) {
	log.FromContext(ctx).With("publisher_id", publisherID).Debug("Getting monetizations for publisher")
	publisher, err := q.publisherRepo.GetByIDWithOptions(ctx, publisherID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
	if err != nil {
		return nil, err
	}
	return publisher.Monetizations, nil
}

func (q *MonetizationQueries) GetMonetizationsForSource(ctx context.Context, sourceID uint) ([]*domain.Monetization, error) {
	log.FromContext(ctx).With("source_id", sourceID).Debug("Getting monetizations for source")
	source, err := q.sourceRepo.GetByIDWithOptions(ctx, sourceID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
	if err != nil {
		return nil, err
	}
	return source.Monetizations, nil
}
