package listing

import (
	"context"
	"errors"
	"strings"
	"time"
)

var (
	ErrDependencyUnavailable    = errors.New("dependency unavailable")
	ErrInvalidInput             = errors.New("invalid listing input")
	ErrListingLocked            = errors.New("listing locked")
	ErrListingMustOfflineToEdit = errors.New("listing must be offline to edit")
	ErrPublishCooldown          = errors.New("listing publish cooldown")
	ErrMissingTitle             = errors.New("missing listing title")
	ErrMissingServerRegion      = errors.New("missing server region")
	ErrInvalidPrice             = errors.New("invalid listing price")
	ErrInvalidDeposit           = errors.New("invalid listing deposit")
	ErrDepositTooLow            = errors.New("listing deposit too low")
	ErrInvalidHafCoin           = errors.New("invalid haf coin amount")
	ErrMissingScreenshot        = errors.New("missing screenshot")
	ErrMissingOnlineTime        = errors.New("missing online time")
	ErrInvalidOnlineTime        = errors.New("invalid online time")
	ErrAgreementRequired        = errors.New("listing publish agreement required")
	ErrTargetOwnerInvalid       = errors.New("target owner invalid")
	ErrMissingUploaderName      = errors.New("missing uploader name")
	ErrMissingUploadData        = errors.New("missing upload data")
	ErrUploaderNotFound         = errors.New("uploader not found")
	ErrUploaderAmbiguous        = errors.New("uploader ambiguous")
	ErrTooManyUploadItems       = errors.New("too many upload items")
)

type Service struct {
	repo   *Repository
	config ConfigReader
}

type ConfigReader interface {
	FindValue(ctx context.Context, key string) (string, error)
}

const (
	reviewRequiredConfigKey       = "listing.review_required"
	publishOptionsConfigKey       = "listing.publish_options"
	publishCooldownMinutesKey     = "listing.publish_cooldown_minutes"
	defaultFireLevelMin           = 38
	defaultPublishCooldownMinutes = 5
	maxExternalUploadItems        = 10
	defaultUploadScreenshot       = "/api/listings/default-upload-screenshot"
)

type PublishCooldownError struct {
	Cooldown  time.Duration
	Remaining time.Duration
}

func (e PublishCooldownError) Error() string {
	return ErrPublishCooldown.Error()
}

func (e PublishCooldownError) Is(target error) bool {
	return target == ErrPublishCooldown
}

type FireLevelTooLowError struct {
	Min int
}

func (e FireLevelTooLowError) Error() string {
	return "fire level too low"
}

type UploadValidationError struct {
	Missing []string
	Invalid []string
}

func (e UploadValidationError) Error() string {
	parts := make([]string, 0, 2)
	if len(e.Missing) > 0 {
		parts = append(parts, "缺少必填字段："+strings.Join(e.Missing, "、"))
	}
	if len(e.Invalid) > 0 {
		parts = append(parts, "字段格式不正确："+strings.Join(e.Invalid, "、"))
	}
	return strings.Join(parts, "；")
}

func NewService(repo *Repository, config ConfigReader) *Service {
	return &Service{repo: repo, config: config}
}
