package models

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"time"
)

type PriceMethod string

const (
	PriceMethodManual         PriceMethod = "manual"
	PriceMethodMedian         PriceMethod = "median"
	PriceMethodAverage        PriceMethod = "average"
	PriceMethodWeightedMedian PriceMethod = "weighted_median"
)

type Specs map[string]interface{}

func (s Specs) Value() (driver.Value, error) {
	return json.Marshal(s)
}

func (s *Specs) Scan(value interface{}) error {
	if value == nil {
		*s = make(Specs)
		return nil
	}
	bytes, ok := value.([]byte)
	if !ok {
		return errors.New("type assertion to []byte failed")
	}
	return json.Unmarshal(bytes, s)
}

type LotMetadata struct {
	LotName          string       `gorm:"column:lot_name;primaryKey;size:255" json:"lot_name"`
	CategoryID       *uint        `gorm:"column:category_id" json:"category_id"`
	Model            string       `gorm:"size:100" json:"model"`
	Specs            Specs        `gorm:"type:json" json:"specs"`
	CurrentPrice     *float64     `gorm:"type:decimal(12,2)" json:"current_price"`
	PriceMethod      PriceMethod  `gorm:"type:enum('manual','median','average','weighted_median');default:'median'" json:"price_method"`
	PricePeriodDays  int          `gorm:"default:90" json:"price_period_days"`
	PriceCoefficient float64      `gorm:"type:decimal(5,2);default:0" json:"price_coefficient"`
	ManualPrice      *float64     `gorm:"type:decimal(12,2)" json:"manual_price"`
	PriceUpdatedAt   *time.Time   `json:"price_updated_at"`
	RequestCount     int          `gorm:"default:0" json:"request_count"`
	LastRequestDate  *time.Time   `gorm:"type:date" json:"last_request_date"`
	PopularityScore  float64      `gorm:"type:decimal(10,4);default:0" json:"popularity_score"`
	MetaPrices       string       `gorm:"size:1000" json:"meta_prices"`
	MetaMethod       string       `gorm:"size:20" json:"meta_method"`
	MetaPeriodDays   int          `gorm:"default:90" json:"meta_period_days"`
	IsHidden         bool         `gorm:"default:false" json:"is_hidden"`

	// Relations
	Lot      *Lot      `gorm:"foreignKey:LotName;references:LotName" json:"lot,omitempty"`
	Category *Category `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
}

func (LotMetadata) TableName() string {
	return "qt_lot_metadata"
}

type PriceFreshness string

const (
	FreshnessFresh    PriceFreshness = "fresh"
	FreshnessNormal   PriceFreshness = "normal"
	FreshnessStale    PriceFreshness = "stale"
	FreshnessCritical PriceFreshness = "critical"
)

func (m *LotMetadata) GetPriceFreshness(greenDays, yellowDays, redDays, minQuotes int) PriceFreshness {
	if m.CurrentPrice == nil || *m.CurrentPrice == 0 {
		return FreshnessCritical
	}
	if m.PriceUpdatedAt == nil {
		return FreshnessCritical
	}

	daysSince := int(time.Since(*m.PriceUpdatedAt).Hours() / 24)

	if daysSince < greenDays && m.RequestCount >= minQuotes {
		return FreshnessFresh
	} else if daysSince < yellowDays {
		return FreshnessNormal
	} else if daysSince < redDays {
		return FreshnessStale
	}
	return FreshnessCritical
}
