package domain

import (
	"context"
	"errors"
	"fmt"
	"time"

	"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
)

var ErrDuplicateAuctionImported = errors.New("another auction with the same fingerprint exists")

type (
	Usecase struct {
		Storage
	}

	Storage interface {
		GetUpcoming(context.Context, UpcomingQuery) ([]Auction, int64, int64, error)
		CreateUpcoming(context.Context, Auction) (string, error)
	}

	UpcomingQuery struct {
		Term            string
		Page            int
		Limit           int
		StartDateFilter time.Time
	}

	ImportAuctionMessage struct {
		Auction
	}

	AuctionCreated struct {
		Auction
		Duplicate bool
	}

	UpcomingResults struct {
		Page    int
		Total   int64
		Found   int64
		Results []Auction
	}
)

func (d *Usecase) GetUpcoming(ctx context.Context, q UpcomingQuery) (results UpcomingResults, err error) {
	if results.Results, results.Total, results.Found, err = d.Storage.GetUpcoming(ctx, q); err != nil {
		err = fmt.Errorf("could not get upcoming from storage: %w", err)
		return
	}

	return
}

// TODO: tests
func (d *Usecase) ImportAuction(ctx context.Context, in ImportAuctionMessage) (event AuctionCreated, err error) {
	if in.Fingerprint, err = d.Storage.CreateUpcoming(ctx, in.Auction); err != nil && !errors.Is(err, ErrDuplicateAuctionImported) {
		err = fmt.Errorf("could not import auction: %w", err)
		return
	}

	// Duplicates aren't an error, instead let the requester know
	err = nil
	event = AuctionCreated{
		Auction:   in.Auction,
		Duplicate: errors.Is(err, ErrDuplicateAuctionImported),
	}

	status := "✅"
	if event.Duplicate {
		status = "🚫"
	}

	kernel.TraceLog.Printf("%s Import Auction [%s]", status, in.Fingerprint)

	return
}
