package domain

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

const (
	KeyModePlatform = "platform"
	KeyModeByok     = "byok"

	MeterAICopy     = "ai_copy"
	MeterAIResearch = "ai_research"
	MeterWebSearch  = "web_search"
	MeterAIImage    = "ai_image"

	PlanFree    = "free"
	PlanStarter = "starter"
	PlanPro     = "pro"
)

var (
	ErrNotFound      = errors.New("usage not found")
	ErrForbidden     = errors.New("usage forbidden")
	ErrNoKey         = errors.New("no api key configured (platform or byok)")
	ErrQuotaExceeded = errors.New("platform credits insufficient")
	// 分項點數上限（與 FE soft_caps 對齊；platform only）
	ErrMeterCapExceeded = errors.New("usage.err.meterCap")
	// 平台 key 無容量／限流：僅 BYOK 可繼續（不扣平台點）
	ErrPlatformCapacity = errors.New("usage.err.platformCapacity")
	ErrInvalidPlan      = errors.New("invalid plan")
	ErrInvalidRange     = errors.New("invalid usage analytics range")
	ErrPurchaseDisabled = errors.New("self-service plan purchase is disabled; use billing checkout")
)

type Event struct {
	ID        string `bson:"_id" json:"id"`
	UID       int64  `bson:"uid" json:"uid"`
	Meter     string `bson:"meter" json:"meter"`
	Credits   int    `bson:"credits" json:"credits"` // platform only; byok always 0
	KeyMode   string `bson:"key_mode" json:"key_mode"`
	Label     string `bson:"label" json:"label"`
	Source    string `bson:"source" json:"source"`
	MonthKey  string `bson:"month_key" json:"month_key"`
	CreatedAt int64  `bson:"created_at" json:"created_at"`
}

type MonthlyCounter struct {
	ID           string         `bson:"_id" json:"id"`
	UID          int64          `bson:"uid" json:"uid"`
	MonthKey     string         `bson:"month_key" json:"month_key"`
	TotalCredits int            `bson:"total_credits" json:"total_credits"`
	ByMeter      map[string]int `bson:"by_meter" json:"by_meter"`
	UpdatedAt    int64          `bson:"updated_at" json:"updated_at"`
}

type MemberPrefs struct {
	UID                   int64  `bson:"uid" json:"uid"`
	PlanID                string `bson:"plan_id" json:"plan_id"`
	Unlimited             bool   `bson:"unlimited" json:"unlimited"`
	AdminOverride         bool   `bson:"admin_override" json:"admin_override"`
	PaidPlanID            string `bson:"paid_plan_id,omitempty" json:"paid_plan_id,omitempty"`
	SubscriptionStatus    string `bson:"subscription_status,omitempty" json:"subscription_status,omitempty"`
	StripeCustomerID      string `bson:"stripe_customer_id,omitempty" json:"stripe_customer_id,omitempty"`
	StripeSubscriptionID  string `bson:"stripe_subscription_id,omitempty" json:"stripe_subscription_id,omitempty"`
	CurrentPeriodStart    int64  `bson:"current_period_start,omitempty" json:"current_period_start,omitempty"`
	CurrentPeriodEnd      int64  `bson:"current_period_end,omitempty" json:"current_period_end,omitempty"`
	CancelAtPeriodEnd     bool   `bson:"cancel_at_period_end" json:"cancel_at_period_end"`
	BillingEventID        string `bson:"billing_event_id,omitempty" json:"-"`
	BillingEventCreatedAt int64  `bson:"billing_event_created_at,omitempty" json:"-"`
	// InviteBonusCredits — 邀請贈點（入平台額度池，與消耗分開顯示）
	InviteBonusCredits int   `bson:"invite_bonus_credits,omitempty" json:"invite_bonus_credits,omitempty"`
	UpdatedAt          int64 `bson:"updated_at" json:"updated_at"`
}

const MeterInviteBonus = "invite_bonus"
const KeyModeBonus = "bonus"

type Purchase struct {
	ID        string `bson:"_id" json:"id"`
	UID       int64  `bson:"uid" json:"uid"`
	PlanID    string `bson:"plan_id" json:"plan_id"`
	MockRef   string `bson:"mock_ref,omitempty" json:"mock_ref,omitempty"`
	CreatedAt int64  `bson:"created_at" json:"created_at"`
}

type PlanDef struct {
	ID             string
	MonthlyCredits int
	// SoftCaps：各 meter 點數硬上限（platform）；加總 = MonthlyCredits
	SoftCaps map[string]int
	/*
		demand-radar 配額（spec §4.9）。這是「常駐監控」的規模上限，
		與上面的點數是兩件事：AI 判定與回覆仍走既有 meter，不重複收費、
		也不新增第五個 meter。
	*/
	MaxActiveWatches      int
	MaxDailyOpportunities int
}

// Plans — 與 FE PLANS 同步（2026-07 · 組合毛利 ≥50%）
// 安全單價約 $0.012／點；Starter NT$590≈$18.4 / Pro NT$1990≈$62.2
// Free 120 點：夠用試用（可虧 ~$1.44 滿用）；付費扛回組合毛利。
var Plans = map[string]PlanDef{
	PlanFree: {
		ID: PlanFree, MonthlyCredits: 120,
		SoftCaps: map[string]int{
			MeterAICopy: 60, MeterAIResearch: 15, MeterWebSearch: 30, MeterAIImage: 15,
		},
		MaxActiveWatches: 1, MaxDailyOpportunities: 5,
	},
	PlanStarter: {
		ID: PlanStarter, MonthlyCredits: 600,
		SoftCaps: map[string]int{
			MeterAICopy: 300, MeterAIResearch: 90, MeterWebSearch: 150, MeterAIImage: 60,
		},
		MaxActiveWatches: 5, MaxDailyOpportunities: 30,
	},
	PlanPro: {
		ID: PlanPro, MonthlyCredits: 2000,
		SoftCaps: map[string]int{
			MeterAICopy: 1000, MeterAIResearch: 300, MeterWebSearch: 500, MeterAIImage: 200,
		},
		MaxActiveWatches: 20, MaxDailyOpportunities: 100,
	},
}

var DefaultCreditCost = map[string]int{
	MeterAICopy: 1, MeterAIResearch: 3, MeterWebSearch: 1, MeterAIImage: 5,
}

// ResolvePlan — 正規化 plan_id（小寫）並回傳方案；未知 → Free
func ResolvePlan(planID string) PlanDef {
	id := strings.ToLower(strings.TrimSpace(planID))
	if p, ok := Plans[id]; ok && p.ID != "" {
		return p
	}
	return Plans[PlanFree]
}

// MeterCost returns platform credit cost for one call.
func MeterCost(meter string) int {
	if c := DefaultCreditCost[meter]; c > 0 {
		return c
	}
	return 1
}

func NowNano() int64 { return time.Now().UTC().UnixNano() }

func MonthKey(nano int64) string {
	t := time.Unix(0, nano).UTC()
	return t.Format("2006-01")
}

func CurrentMonthKey() string { return MonthKey(NowNano()) }

// Summary split — never merge platform+byok into one total_calls only.
type MeterCount struct {
	Count   int `json:"count"`
	Credits int `json:"credits"`
}

type PlatformBlock struct {
	CreditsUsed      int                   `json:"credits_used"`
	CreditsRemaining int                   `json:"credits_remaining"`
	CreditsTotal     int                   `json:"credits_total"`
	CallCount        int                   `json:"call_count"`
	ByMeter          map[string]MeterCount `json:"by_meter"`
}

type ByokBlock struct {
	CallCount int                   `json:"call_count"`
	ByMeter   map[string]MeterCount `json:"by_meter"`
}

type MonthSummary struct {
	MonthKey  string        `json:"month_key"`
	UID       int64         `json:"uid"`
	PlanID    string        `json:"plan_id"`
	Unlimited bool          `json:"unlimited"`
	Platform  PlatformBlock `json:"platform"`
	Byok      ByokBlock     `json:"byok"`
	// Legacy FE bars: only platform credits (not mixed)
	TotalCredits     int `json:"total_credits"`
	RemainingCredits int `json:"remaining_credits"`
}

type TenantRow struct {
	UID                 int64  `json:"uid"`
	PlanID              string `json:"plan_id"`
	Unlimited           bool   `json:"unlimited"`
	PlatformCreditsUsed int    `json:"platform_credits_used"`
	ByokCallCount       int    `json:"byok_call_count"`
}

type TenantSummary struct {
	MonthKey            string      `json:"month_key"`
	PlatformCreditsUsed int         `json:"platform_credits_used"`
	ByokCallCount       int         `json:"byok_call_count"`
	Members             []TenantRow `json:"members"`
}

type AnalyticsMember struct {
	UID         int64
	Email       string
	DisplayName string
}

type AnalyticsQuery struct {
	Granularity string
	From        time.Time
	To          time.Time
}

type AnalyticsBucket struct {
	Key              string
	Label            string
	PurchasedCredits int
	ConsumedCredits  int
	AICalls          int
	SearchCalls      int
	ByokCallCount    int
}

type AnalyticsMemberRow struct {
	UID              int64
	Email            string
	DisplayName      string
	Unlimited        bool
	PlanID           string
	PurchasedCredits int
	TotalCredits     int
	AICalls          int
	SearchCalls      int
	ByokCallCount    int
	RemainingCredits int
	Pct              int
}

type TenantAnalytics struct {
	Granularity      string
	From             string
	To               string
	RangeLabel       string
	PurchasedCredits int
	ConsumedCredits  int
	RemainingCredits int
	Pct              int
	AICalls          int
	SearchCalls      int
	ByMeter          map[string]MeterCount
	Byok             ByokBlock
	Series           []AnalyticsBucket
	Members          []AnalyticsMemberRow
}
