package commerce

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

type JSONRaw []byte

func (j *JSONRaw) Scan(value any) error {
	if value == nil {
		*j = nil
		return nil
	}
	switch v := value.(type) {
	case []byte:
		*j = append((*j)[0:0], v...)
	case string:
		*j = append((*j)[0:0], v...)
	default:
		return fmt.Errorf("unsupported JSON value type %T", value)
	}
	return nil
}

func (j JSONRaw) Value() (driver.Value, error) {
	if len(j) == 0 {
		return nil, nil
	}
	return string(j), nil
}

func (j JSONRaw) MarshalJSON() ([]byte, error) {
	if len(j) == 0 {
		return []byte("null"), nil
	}
	if json.Valid(j) {
		return j, nil
	}
	return json.Marshal(string(j))
}

func (j *JSONRaw) UnmarshalJSON(data []byte) error {
	if j == nil {
		return nil
	}
	if len(data) == 0 || string(data) == "null" {
		*j = nil
		return nil
	}
	*j = append((*j)[0:0], data...)
	return nil
}

type ProductCategory struct {
	ID            int64     `gorm:"column:id;primaryKey" json:"id"`
	Slug          string    `gorm:"column:slug" json:"slug"`
	Name          string    `gorm:"column:name" json:"name"`
	Description   *string   `gorm:"column:description" json:"description"`
	Icon          *string   `gorm:"column:icon" json:"icon"`
	SortOrder     int       `gorm:"column:sort_order" json:"sort_order"`
	Status        string    `gorm:"column:status" json:"status"`
	IsFeatured    bool      `gorm:"column:is_featured" json:"is_featured"`
	FeaturedLabel string    `gorm:"column:featured_label" json:"featured_label"`
	CreatedAt     time.Time `gorm:"column:created_at" json:"created_at"`
	UpdatedAt     time.Time `gorm:"column:updated_at" json:"updated_at"`
}

func (ProductCategory) TableName() string {
	return "product_categories"
}

type ProductGroup struct {
	ID               int64     `gorm:"column:id;primaryKey" json:"id"`
	CategoryID       int64     `gorm:"column:category_id" json:"category_id"`
	ParentID         *int64    `gorm:"column:parent_id" json:"parent_id"`
	Slug             string    `gorm:"column:slug" json:"slug"`
	Name             string    `gorm:"column:name" json:"name"`
	Headline         *string   `gorm:"column:headline" json:"headline"`
	Description      *string   `gorm:"column:description" json:"description"`
	Icon             *string   `gorm:"column:icon" json:"icon"`
	NetworkType      *string   `gorm:"column:network_type" json:"network_type"`
	SortOrder        int       `gorm:"column:sort_order" json:"sort_order"`
	RequiresRealName bool      `gorm:"column:requires_real_name" json:"requires_real_name"`
	Area             *int      `gorm:"column:area" json:"area"`
	Node             *int      `gorm:"column:node" json:"node"`
	OSOptions        JSONRaw   `gorm:"column:os_options" json:"-"`
	CreatedAt        time.Time `gorm:"column:created_at" json:"created_at"`
	UpdatedAt        time.Time `gorm:"column:updated_at" json:"updated_at"`
}

func (ProductGroup) TableName() string {
	return "product_groups"
}

type Product struct {
	ID                   int64     `gorm:"column:id;primaryKey" json:"id"`
	GroupID              int64     `gorm:"column:group_id" json:"group_id"`
	SKU                  string    `gorm:"column:sku" json:"sku"`
	Name                 string    `gorm:"column:name" json:"name"`
	Type                 string    `gorm:"column:type" json:"type"`
	Status               string    `gorm:"column:status" json:"status"`
	VCPU                 *int      `gorm:"column:vcpu" json:"vcpu"`
	CPUModel             *string   `gorm:"column:cpu_model" json:"cpu_model"`
	CPUBaseMHz           *int      `gorm:"column:cpu_base_mhz" json:"cpu_base_mhz"`
	CPUTurboMHz          *int      `gorm:"column:cpu_turbo_mhz" json:"cpu_turbo_mhz"`
	Memory               *string   `gorm:"column:memory" json:"memory"`
	Disk                 *string   `gorm:"column:disk" json:"disk"`
	Bandwidth            *string   `gorm:"column:bandwidth" json:"bandwidth"`
	Features             *string   `gorm:"column:features" json:"features"`
	Badges               *string   `gorm:"column:badges" json:"badges"`
	BaseSetupFee         float64   `gorm:"column:base_setup_fee" json:"base_setup_fee"`
	BasePrice            float64   `gorm:"column:base_price" json:"base_price"`
	StockPolicy          string    `gorm:"column:stock_policy" json:"stock_policy"`
	Stock                int       `gorm:"column:stock" json:"stock"`
	MinQuantity          int       `gorm:"column:min_quantity" json:"min_quantity"`
	MaxQuantity          int       `gorm:"column:max_quantity" json:"max_quantity"`
	AutoProvision        bool      `gorm:"column:auto_provision" json:"auto_provision"`
	TrialEnabled         bool      `gorm:"column:trial_enabled" json:"trial_enabled"`
	TrialDays            int       `gorm:"column:trial_days" json:"trial_days"`
	SortOrder            int       `gorm:"column:sort_order" json:"sort_order"`
	IsFeatured           bool      `gorm:"column:is_featured" json:"is_featured"`
	RequiresRealName     bool      `gorm:"column:requires_real_name" json:"requires_real_name"`
	CloudServerID        *int64    `gorm:"column:cloud_server_id" json:"cloud_server_id"`
	APIType              string    `gorm:"column:api_type" json:"api_type"`
	APIIdentifier        *string   `gorm:"column:api_identifier" json:"api_identifier"`
	ProvisionInterfaceID *int64    `gorm:"column:provision_interface_id" json:"provision_interface_id"`
	ProvisionConfig      JSONRaw   `gorm:"column:provision_config" json:"-"`
	CreatedAt            time.Time `gorm:"column:created_at" json:"created_at"`
	UpdatedAt            time.Time `gorm:"column:updated_at" json:"updated_at"`
}

func (Product) TableName() string {
	return "products"
}

type ProductPricing struct {
	ID            int64     `gorm:"column:id;primaryKey" json:"id"`
	ProductID     int64     `gorm:"column:product_id" json:"-"`
	Cycle         string    `gorm:"column:cycle" json:"cycle"`
	Price         float64   `gorm:"column:price" json:"price"`
	OriginalPrice *float64  `gorm:"column:original_price" json:"original_price"`
	SetupFee      float64   `gorm:"column:setup_fee" json:"setup_fee"`
	IsEnabled     bool      `gorm:"column:is_enabled" json:"is_enabled"`
	SortOrder     int       `gorm:"column:sort_order" json:"sort_order"`
	CreatedAt     time.Time `gorm:"column:created_at" json:"-"`
	UpdatedAt     time.Time `gorm:"column:updated_at" json:"-"`
}

func (ProductPricing) TableName() string {
	return "product_pricings"
}

type CartItem struct {
	ID           int64     `gorm:"column:id;primaryKey" json:"id"`
	UserID       int64     `gorm:"column:user_id" json:"user_id"`
	ProductID    int64     `gorm:"column:product_id" json:"product_id"`
	Cycle        string    `gorm:"column:cycle" json:"cycle"`
	Quantity     int       `gorm:"column:quantity" json:"quantity"`
	AutoRenew    bool      `gorm:"column:auto_renew" json:"auto_renew"`
	Alias        *string   `gorm:"column:alias" json:"alias"`
	OSImage      *string   `gorm:"column:os_image" json:"os_image"`
	UnitPrice    float64   `gorm:"column:unit_price" json:"unit_price"`
	AddonPrice   float64   `gorm:"column:addon_price" json:"addon_price"`
	SetupFee     float64   `gorm:"column:setup_fee" json:"setup_fee"`
	SliderValues JSONRaw   `gorm:"column:slider_values" json:"-"`
	CreatedAt    time.Time `gorm:"column:created_at" json:"created_at"`
	UpdatedAt    time.Time `gorm:"column:updated_at" json:"updated_at"`
}

func (CartItem) TableName() string {
	return "cart_items"
}

type PromoCode struct {
	ID                  int64      `gorm:"column:id;primaryKey"`
	Code                string     `gorm:"column:code"`
	Description         *string    `gorm:"column:description"`
	IssuerUserID        *int64     `gorm:"column:issuer_user_id"`
	IssuerType          *string    `gorm:"column:issuer_type"`
	PointCost           int        `gorm:"column:point_cost"`
	PointRefunded       int        `gorm:"column:point_refunded"`
	Type                string     `gorm:"column:type"`
	Value               int        `gorm:"column:value"`
	Scope               string     `gorm:"column:scope"`
	DiscountLevel       string     `gorm:"column:discount_level"`
	ScopeIDs            *string    `gorm:"column:scope_ids"`
	StartsAt            *time.Time `gorm:"column:starts_at"`
	ExpiresAt           *time.Time `gorm:"column:expires_at"`
	MaxUses             int        `gorm:"column:max_uses"`
	MaxUsesPerUser      int        `gorm:"column:max_uses_per_user"`
	UsedCount           int        `gorm:"column:used_count"`
	ApplicableCycles    *string    `gorm:"column:applicable_cycles"`
	MinOrderAmount      int        `gorm:"column:min_order_amount"`
	MinQuantity         int        `gorm:"column:min_quantity"`
	MaxDiscountAmount   int        `gorm:"column:max_discount_amount"`
	RequiredProductIDs  *string    `gorm:"column:required_product_ids"`
	RequiredGroupIDs    *string    `gorm:"column:required_group_ids"`
	RequiredCategoryIDs *string    `gorm:"column:required_category_ids"`
	AllowedUserIDs      *string    `gorm:"column:allowed_user_ids"`
	NewUsersOnly        bool       `gorm:"column:new_users_only"`
	AppliesToRenewals   bool       `gorm:"column:applies_to_renewals"`
	IsStackable         bool       `gorm:"column:is_stackable"`
	ClaimMethod         string     `gorm:"column:claim_method"`
	ListOnMall          bool       `gorm:"column:list_on_mall"`
	IsEnabled           bool       `gorm:"column:is_enabled"`
	CreatedAt           time.Time  `gorm:"column:created_at"`
	UpdatedAt           time.Time  `gorm:"column:updated_at"`
}

func (PromoCode) TableName() string {
	return "promo_codes"
}

type PromoCodeUsage struct {
	ID              int64     `gorm:"column:id;primaryKey"`
	PromoCodeID     int64     `gorm:"column:promo_code_id"`
	CodeSnapshot    string    `gorm:"column:code_snapshot"`
	UserID          int64     `gorm:"column:user_id"`
	OrderID         int64     `gorm:"column:order_id"`
	OrderAmount     int       `gorm:"column:order_amount"`
	EligibleAmount  int       `gorm:"column:eligible_amount"`
	DiscountAmount  int       `gorm:"column:discount_amount"`
	Status          string    `gorm:"column:status"`
	UsedAt          time.Time `gorm:"column:used_at"`
	PayloadSnapshot JSONRaw   `gorm:"column:payload_snapshot"`
	CreatedAt       time.Time `gorm:"column:created_at"`
	UpdatedAt       time.Time `gorm:"column:updated_at"`
}

func (PromoCodeUsage) TableName() string {
	return "promo_code_usages"
}

type CouponMallClaim struct {
	ID          int64      `gorm:"column:id;primaryKey"`
	MallItemID  int64      `gorm:"column:mall_item_id"`
	PromoCodeID int64      `gorm:"column:promo_code_id"`
	UserID      int64      `gorm:"column:user_id"`
	PointsPaid  int        `gorm:"column:points_paid"`
	Code        *string    `gorm:"column:code"`
	Status      string     `gorm:"column:status"`
	UsedAt      *time.Time `gorm:"column:used_at"`
	OrderID     *int64     `gorm:"column:order_id"`
	CreatedAt   time.Time  `gorm:"column:created_at"`
	UpdatedAt   time.Time  `gorm:"column:updated_at"`
}

func (CouponMallClaim) TableName() string {
	return "coupon_mall_claims"
}

type CouponMallItem struct {
	ID                      int64     `gorm:"column:id;primaryKey"`
	PromoCodeID             int64     `gorm:"column:promo_code_id"`
	IssuerUserID            int64     `gorm:"column:issuer_user_id"`
	Title                   *string   `gorm:"column:title"`
	Subtitle                *string   `gorm:"column:subtitle"`
	CoverImage              *string   `gorm:"column:cover_image"`
	Description             *string   `gorm:"column:description"`
	PointsPrice             int       `gorm:"column:points_price"`
	StockTotal              int       `gorm:"column:stock_total"`
	StockRemaining          int       `gorm:"column:stock_remaining"`
	Status                  string    `gorm:"column:status"`
	Scope                   string    `gorm:"column:scope"`
	VisibleUserIDs          *string   `gorm:"column:visible_user_ids"`
	SortOrder               int       `gorm:"column:sort_order"`
	Category                *string   `gorm:"column:category"`
	MaxClaimsPerUser        int       `gorm:"column:max_claims_per_user"`
	MaxClaimsPerUserPerDay  int       `gorm:"column:max_claims_per_user_per_day"`
	RequiredMemberLevel     int       `gorm:"column:required_member_level"`
	RequiredMemberLevelName *string   `gorm:"column:required_member_level_name"`
	IsHot                   bool      `gorm:"column:is_hot"`
	CreatedAt               time.Time `gorm:"column:created_at"`
	UpdatedAt               time.Time `gorm:"column:updated_at"`
}

func (CouponMallItem) TableName() string {
	return "coupon_mall_items"
}

type Order struct {
	ID                     int64      `gorm:"column:id;primaryKey"`
	UserID                 int64      `gorm:"column:user_id"`
	OutOrderNo             string     `gorm:"column:out_order_no"`
	Status                 string     `gorm:"column:status"`
	TotalAmount            int        `gorm:"column:total_amount"`
	DiscountAmount         int        `gorm:"column:discount_amount"`
	PromoCodeID            *int64     `gorm:"column:promo_code_id"`
	ItemsSnapshot          JSONRaw    `gorm:"column:items_snapshot"`
	Remark                 *string    `gorm:"column:remark"`
	AgentID                *int64     `gorm:"column:agent_id"`
	AgentTierID            *int64     `gorm:"column:agent_tier_id"`
	AgentCostRate          *int       `gorm:"column:agent_cost_rate"`
	AgentCostAmount        *int       `gorm:"column:agent_cost_amount"`
	AgentDeltaAmount       *int       `gorm:"column:agent_delta_amount"`
	MemberCommissionRate   *int       `gorm:"column:member_commission_rate"`
	MemberCommissionAmount *int       `gorm:"column:member_commission_amount"`
	SettlementStatus       *string    `gorm:"column:settlement_status"`
	AffCode                *string    `gorm:"column:aff_code"`
	PointsClaimed          bool       `gorm:"column:points_claimed"`
	PointsClaimedAt        *time.Time `gorm:"column:points_claimed_at"`
	PointsClaimedAmount    int        `gorm:"column:points_claimed_amount"`
	CreatedAt              time.Time  `gorm:"column:created_at"`
	UpdatedAt              time.Time  `gorm:"column:updated_at"`
}

func (Order) TableName() string {
	return "orders"
}

type UserAgent struct {
	ID                     int64      `gorm:"column:id;primaryKey" json:"id"`
	UserID                 int64      `gorm:"column:user_id" json:"user_id"`
	AgentTierID            *int64     `gorm:"column:agent_tier_id" json:"agent_tier_id"`
	Status                 string     `gorm:"column:status" json:"status"`
	InviteCode             *string    `gorm:"column:invite_code" json:"invite_code"`
	TotalSales             int        `gorm:"column:total_sales" json:"total_sales"`
	TotalProfit            int        `gorm:"column:total_profit" json:"total_profit"`
	TotalSubsidy           int        `gorm:"column:total_subsidy" json:"total_subsidy"`
	AgentBalance           int        `gorm:"column:agent_balance" json:"agent_balance"`
	AgentFrozenBalance     int        `gorm:"column:agent_frozen_balance" json:"agent_frozen_balance"`
	ApprovedAt             *time.Time `gorm:"column:approved_at" json:"approved_at"`
	ApprovedBy             *int64     `gorm:"column:approved_by" json:"approved_by"`
	RejectReason           *string    `gorm:"column:reject_reason" json:"reject_reason"`
	Remark                 *string    `gorm:"column:remark" json:"remark"`
	ReviewMessage          *string    `gorm:"column:review_message" json:"review_message"`
	ApplyTier              *string    `gorm:"column:apply_tier" json:"apply_tier"`
	ApplyReason            *string    `gorm:"column:apply_reason" json:"apply_reason"`
	ApplyChannels          *string    `gorm:"column:apply_channels" json:"apply_channels"`
	ObserveStartedAt       *time.Time `gorm:"column:observe_started_at" json:"observe_started_at"`
	ObserveUntil           *time.Time `gorm:"column:observe_until" json:"observe_until"`
	RiskLockedAt           *time.Time `gorm:"column:risk_locked_at" json:"risk_locked_at"`
	RiskReason             *string    `gorm:"column:risk_reason" json:"risk_reason"`
	LastEvaluatedAt        *time.Time `gorm:"column:last_evaluated_at" json:"last_evaluated_at"`
	LastEvaluationSnapshot JSONRaw    `gorm:"column:last_evaluation_snapshot" json:"last_evaluation_snapshot"`
	CreatedAt              time.Time  `gorm:"column:created_at" json:"created_at"`
	UpdatedAt              time.Time  `gorm:"column:updated_at" json:"updated_at"`
}

func (UserAgent) TableName() string {
	return "user_agents"
}

type AgentTier struct {
	ID                             int64   `gorm:"column:id;primaryKey" json:"id"`
	Name                           string  `gorm:"column:name" json:"name"`
	Code                           string  `gorm:"column:code" json:"code"`
	CostRate                       int     `gorm:"column:cost_rate" json:"cost_rate"`
	MinMemberLevel                 int     `gorm:"column:min_member_level" json:"min_member_level"`
	MinTotalSpend                  int     `gorm:"column:min_total_spend" json:"min_total_spend"`
	MonthlySalesRequired           int     `gorm:"column:monthly_sales_required" json:"monthly_sales_required"`
	MonthlyActiveCustomersRequired int     `gorm:"column:monthly_active_customers_required" json:"monthly_active_customers_required"`
	MaxRefundRateBps               int     `gorm:"column:max_refund_rate_bps" json:"max_refund_rate_bps"`
	MaxMonthlySubsidyCents         int     `gorm:"column:max_monthly_subsidy_cents" json:"max_monthly_subsidy_cents"`
	MinBalanceForSubsidyCents      int     `gorm:"column:min_balance_for_subsidy_cents" json:"min_balance_for_subsidy_cents"`
	ObserveDays                    int     `gorm:"column:observe_days" json:"observe_days"`
	FreezeDays                     int     `gorm:"column:freeze_days" json:"freeze_days"`
	AutoDowngradeEnabled           bool    `gorm:"column:auto_downgrade_enabled" json:"auto_downgrade_enabled"`
	MaxCouponDiscountRate          int     `gorm:"column:max_coupon_discount_rate" json:"max_coupon_discount_rate"`
	MaxMonthlyCouponCount          int     `gorm:"column:max_monthly_coupon_count" json:"max_monthly_coupon_count"`
	SortOrder                      int     `gorm:"column:sort_order" json:"sort_order"`
	Enabled                        bool    `gorm:"column:enabled" json:"enabled"`
	Description                    *string `gorm:"column:description" json:"description"`
}

func (AgentTier) TableName() string {
	return "agent_tiers"
}

type AgentSettlement struct {
	ID                int64      `gorm:"column:id;primaryKey" json:"id"`
	OrderID           int64      `gorm:"column:order_id" json:"order_id"`
	OrderNo           string     `gorm:"column:order_no" json:"order_no"`
	SettlementType    string     `gorm:"column:settlement_type" json:"settlement_type"`
	UserID            int64      `gorm:"column:user_id" json:"user_id"`
	CustomerUserID    *int64     `gorm:"column:customer_user_id" json:"customer_user_id"`
	AgentTierID       *int64     `gorm:"column:agent_tier_id" json:"agent_tier_id"`
	StandardAmount    int        `gorm:"column:standard_amount" json:"standard_amount"`
	CustomerPayAmount int        `gorm:"column:customer_pay_amount" json:"customer_pay_amount"`
	AgentCostRate     *int       `gorm:"column:agent_cost_rate" json:"agent_cost_rate"`
	AgentCostAmount   *int       `gorm:"column:agent_cost_amount" json:"agent_cost_amount"`
	DeltaAmount       int        `gorm:"column:delta_amount" json:"delta_amount"`
	CommissionRate    *int       `gorm:"column:commission_rate" json:"commission_rate"`
	Status            string     `gorm:"column:status" json:"status"`
	FrozenUntil       *time.Time `gorm:"column:frozen_until" json:"frozen_until"`
	PointsAmount      int        `gorm:"column:points_amount" json:"points_amount"`
	PointLogID        *int64     `gorm:"column:point_log_id" json:"point_log_id"`
	SettledAt         *time.Time `gorm:"column:settled_at" json:"settled_at"`
	ReversedAt        *time.Time `gorm:"column:reversed_at" json:"reversed_at"`
	Remark            *string    `gorm:"column:remark" json:"remark"`
	CreatedAt         time.Time  `gorm:"column:created_at" json:"created_at"`
	UpdatedAt         time.Time  `gorm:"column:updated_at" json:"updated_at"`
}

func (AgentSettlement) TableName() string {
	return "agent_settlements"
}

type AgentBalanceLog struct {
	ID                 int64     `gorm:"column:id;primaryKey"`
	UserID             int64     `gorm:"column:user_id"`
	ChangeType         string    `gorm:"column:change_type"`
	Delta              int       `gorm:"column:delta"`
	BalanceAfter       int       `gorm:"column:balance_after"`
	FrozenBalanceAfter int       `gorm:"column:frozen_balance_after"`
	OrderID            *int64    `gorm:"column:order_id"`
	RefNo              *string   `gorm:"column:ref_no"`
	Remark             *string   `gorm:"column:remark"`
	OperatorID         *int64    `gorm:"column:operator_id"`
	CreatedAt          time.Time `gorm:"column:created_at"`
	UpdatedAt          time.Time `gorm:"column:updated_at"`
}

func (AgentBalanceLog) TableName() string {
	return "agent_balance_logs"
}

type AgentCustomer struct {
	ID             int64     `gorm:"column:id;primaryKey"`
	AgentUserID    int64     `gorm:"column:agent_user_id"`
	CustomerUserID int64     `gorm:"column:customer_user_id"`
	BindSource     string    `gorm:"column:bind_source"`
	BoundAt        time.Time `gorm:"column:bound_at"`
	FirstOrderID   *int64    `gorm:"column:first_order_id"`
	Status         string    `gorm:"column:status"`
	CreatedAt      time.Time `gorm:"column:created_at"`
	UpdatedAt      time.Time `gorm:"column:updated_at"`
}

func (AgentCustomer) TableName() string {
	return "agent_customers"
}

type AffiliateClick struct {
	ID               int64      `gorm:"column:id;primaryKey"`
	AffCode          string     `gorm:"column:aff_code"`
	AgentID          *int64     `gorm:"column:agent_id"`
	LandingURL       *string    `gorm:"column:landing_url"`
	IP               *string    `gorm:"column:ip"`
	UserAgent        *string    `gorm:"column:user_agent"`
	Referer          *string    `gorm:"column:referer"`
	UTMSource        *string    `gorm:"column:utm_source"`
	UTMMedium        *string    `gorm:"column:utm_medium"`
	UTMCampaign      *string    `gorm:"column:utm_campaign"`
	UTMContent       *string    `gorm:"column:utm_content"`
	UTMTerm          *string    `gorm:"column:utm_term"`
	RegisteredUserID *int64     `gorm:"column:registered_user_id"`
	ConvertedAt      *time.Time `gorm:"column:converted_at"`
	CreatedAt        time.Time  `gorm:"column:created_at"`
	UpdatedAt        time.Time  `gorm:"column:updated_at"`
}

func (AffiliateClick) TableName() string {
	return "affiliate_clicks"
}

type OrderRefund struct {
	ID                  int64      `gorm:"column:id;primaryKey"`
	RefundNo            string     `gorm:"column:refund_no"`
	UserID              int64      `gorm:"column:user_id"`
	OrderID             int64      `gorm:"column:order_id"`
	RefundType          string     `gorm:"column:refund_type"`
	RefundAmount        int        `gorm:"column:refund_amount"`
	Status              string     `gorm:"column:status"`
	ResourceStatus      string     `gorm:"column:resource_status"`
	ResourceError       *string    `gorm:"column:resource_error"`
	ResourceCompletedAt *time.Time `gorm:"column:resource_completed_at"`
	Reason              *string    `gorm:"column:reason"`
	PayloadSnapshot     JSONRaw    `gorm:"column:payload_snapshot"`
	CreatedAt           time.Time  `gorm:"column:created_at"`
	UpdatedAt           time.Time  `gorm:"column:updated_at"`
}

func (OrderRefund) TableName() string {
	return "order_refunds"
}

type UpstreamActionLog struct {
	ID              int64      `gorm:"column:id;primaryKey"`
	UserID          *int64     `gorm:"column:user_id"`
	OrderID         *int64     `gorm:"column:order_id"`
	OrderRefundID   *int64     `gorm:"column:order_refund_id"`
	InstanceID      *int64     `gorm:"column:instance_id"`
	CloudServerID   *int64     `gorm:"column:cloud_server_id"`
	UpstreamID      *int64     `gorm:"column:upstream_id"`
	ActionType      string     `gorm:"column:action_type"`
	ResourceType    string     `gorm:"column:resource_type"`
	ResourceID      *string    `gorm:"column:resource_id"`
	Source          string     `gorm:"column:source"`
	Status          string     `gorm:"column:status"`
	UpstreamTaskID  *int64     `gorm:"column:upstream_task_id"`
	RequestMethod   *string    `gorm:"column:request_method"`
	RequestPath     *string    `gorm:"column:request_path"`
	RequestPayload  JSONRaw    `gorm:"column:request_payload"`
	ResponsePayload JSONRaw    `gorm:"column:response_payload"`
	TaskPayload     JSONRaw    `gorm:"column:task_payload"`
	ErrorMessage    *string    `gorm:"column:error_message"`
	Remark          *string    `gorm:"column:remark"`
	AttemptCount    int        `gorm:"column:attempt_count"`
	LastCheckedAt   *time.Time `gorm:"column:last_checked_at"`
	CompletedAt     *time.Time `gorm:"column:completed_at"`
	CreatedAt       time.Time  `gorm:"column:created_at"`
	UpdatedAt       time.Time  `gorm:"column:updated_at"`
}

func (UpstreamActionLog) TableName() string {
	return "upstream_action_logs"
}

type CloudServer struct {
	ID                int64      `gorm:"column:id;primaryKey"`
	Name              string     `gorm:"column:name"`
	ServerType        string     `gorm:"column:server_type"`
	AccountType       string     `gorm:"column:account_type"`
	Hostname          string     `gorm:"column:hostname"`
	Port              int        `gorm:"column:port"`
	Secure            bool       `gorm:"column:secure"`
	Username          string     `gorm:"column:username"`
	PasswordEncrypted string     `gorm:"column:password_encrypted"`
	UserPrefix        *string    `gorm:"column:user_prefix"`
	Disabled          bool       `gorm:"column:disabled"`
	Status            string     `gorm:"column:status"`
	LastCheckAt       *time.Time `gorm:"column:last_check_at"`
	LastCheckMessage  *string    `gorm:"column:last_check_message"`
	ClientID          *int64     `gorm:"column:client_id"`
	Remark            *string    `gorm:"column:remark"`
	SortOrder         int        `gorm:"column:sort_order"`
	CreatedAt         time.Time  `gorm:"column:created_at"`
	UpdatedAt         time.Time  `gorm:"column:updated_at"`
}

func (CloudServer) TableName() string {
	return "cloud_servers"
}

type UserMembership struct {
	ID                int64      `gorm:"column:id;primaryKey" json:"id"`
	UserID            int64      `gorm:"column:user_id" json:"user_id"`
	MemberLevelID     *int64     `gorm:"column:member_level_id" json:"member_level_id"`
	MemberLevelLocked bool       `gorm:"column:member_level_locked" json:"member_level_locked"`
	AgentTier         *string    `gorm:"column:agent_tier" json:"agent_tier"`
	TotalSpent        int        `gorm:"column:total_spent" json:"total_spent"`
	TotalPoints       int        `gorm:"column:total_points" json:"total_points"`
	AvailablePoints   int        `gorm:"column:available_points" json:"available_points"`
	UpgradedAt        *time.Time `gorm:"column:upgraded_at" json:"upgraded_at"`
}

func (UserMembership) TableName() string {
	return "user_memberships"
}

type MemberLevel struct {
	ID                    int64  `gorm:"column:id;primaryKey" json:"id"`
	Name                  string `gorm:"column:name" json:"name"`
	Level                 int    `gorm:"column:level" json:"level"`
	MinTotalSpent         int    `gorm:"column:min_total_spent" json:"min_total_spent"`
	PointsCashbackRate    int    `gorm:"column:points_cashback_rate" json:"points_cashback_rate"`
	MaxPointsDiscountRate int    `gorm:"column:max_points_discount_rate" json:"max_points_discount_rate"`
	CommissionRate        int    `gorm:"column:commission_rate" json:"commission_rate"`
	Enabled               bool   `gorm:"column:enabled" json:"enabled"`
}

func (MemberLevel) TableName() string {
	return "member_levels"
}

type UserAccount struct {
	ID                     int64      `gorm:"column:id;primaryKey"`
	Email                  *string    `gorm:"column:email"`
	Username               string     `gorm:"column:username"`
	HashedPassword         *string    `gorm:"column:hashed_password"`
	Phone                  *string    `gorm:"column:phone"`
	IDCardNo               *string    `gorm:"column:id_card_no"`
	IDCardNoHash           *string    `gorm:"column:id_card_no_hash"`
	RealName               *string    `gorm:"column:real_name"`
	IDCardVerifiedAt       *time.Time `gorm:"column:id_card_verified_at"`
	IDCardFrontImage       *string    `gorm:"column:id_card_front_image"`
	IDCardBackImage        *string    `gorm:"column:id_card_back_image"`
	IDCardFaceImage        *string    `gorm:"column:id_card_face_image"`
	IDCardVerifyRemark     *string    `gorm:"column:id_card_verify_remark"`
	Balance                int        `gorm:"column:balance"`
	Role                   string     `gorm:"column:role"`
	Status                 string     `gorm:"column:status"`
	Nickname               *string    `gorm:"column:nickname"`
	Avatar                 *string    `gorm:"column:avatar"`
	IsEmailVerified        bool       `gorm:"column:is_email_verified"`
	IsPhoneVerified        bool       `gorm:"column:is_phone_verified"`
	IDCardVerified         string     `gorm:"column:id_card_verified"`
	LastLoginAt            *time.Time `gorm:"column:last_login_at"`
	InviteCode             *string    `gorm:"column:invite_code"`
	InviteCodeChangeCount  int        `gorm:"column:invite_code_change_count"`
	InviteCodeChangeExtra  int        `gorm:"column:invite_code_change_extra"`
	FullRefundQuotaExtra   int        `gorm:"column:full_refund_quota_extra"`
	FullRefundQuotaResetAt *time.Time `gorm:"column:full_refund_quota_reset_at"`
	BoundAgentID           *int64     `gorm:"column:bound_agent_id"`
	CreatedAt              time.Time  `gorm:"column:created_at"`
	UpdatedAt              time.Time  `gorm:"column:updated_at"`
}

func (UserAccount) TableName() string {
	return "users"
}

type BalanceLog struct {
	ID           int64     `gorm:"column:id;primaryKey"`
	UserID       int64     `gorm:"column:user_id"`
	ChangeType   string    `gorm:"column:change_type"`
	Delta        int       `gorm:"column:delta"`
	BalanceAfter int       `gorm:"column:balance_after"`
	RefNo        *string   `gorm:"column:ref_no"`
	OperatorID   *int64    `gorm:"column:operator_id"`
	Remark       *string   `gorm:"column:remark"`
	CreatedAt    time.Time `gorm:"column:created_at"`
	UpdatedAt    time.Time `gorm:"column:updated_at"`
}

func (BalanceLog) TableName() string {
	return "balance_logs"
}

type RechargeOrder struct {
	ID            int64     `gorm:"column:id;primaryKey"`
	UserID        int64     `gorm:"column:user_id"`
	OutTradeNo    string    `gorm:"column:out_trade_no"`
	TradeNo       *string   `gorm:"column:trade_no"`
	PaymentPlugin *string   `gorm:"column:payment_plugin"`
	PaymentMethod *string   `gorm:"column:payment_method"`
	NotifyToken   *string   `gorm:"column:notify_token"`
	Channel       string    `gorm:"column:channel"`
	Amount        float64   `gorm:"column:amount"`
	AmountCents   int       `gorm:"column:amount_cents"`
	Status        string    `gorm:"column:status"`
	CallbackRaw   *string   `gorm:"column:callback_raw"`
	ClientIP      *string   `gorm:"column:client_ip"`
	Remark        *string   `gorm:"column:remark"`
	CreatedAt     time.Time `gorm:"column:created_at"`
	UpdatedAt     time.Time `gorm:"column:updated_at"`
}

func (RechargeOrder) TableName() string {
	return "recharge_orders"
}

type PointLog struct {
	ID           int64     `gorm:"column:id;primaryKey" json:"id"`
	UserID       int64     `gorm:"column:user_id" json:"user_id"`
	ChangeType   string    `gorm:"column:change_type" json:"change_type"`
	Delta        int       `gorm:"column:delta" json:"delta"`
	BalanceAfter int       `gorm:"column:balance_after" json:"balance_after"`
	OrderID      *int64    `gorm:"column:order_id" json:"order_id"`
	RefNo        *string   `gorm:"column:ref_no" json:"ref_no"`
	Remark       *string   `gorm:"column:remark" json:"remark"`
	CreatedAt    time.Time `gorm:"column:created_at" json:"created_at"`
	UpdatedAt    time.Time `gorm:"column:updated_at" json:"updated_at"`
}

func (PointLog) TableName() string {
	return "point_logs"
}

type PointReward struct {
	ID                int64      `gorm:"column:id;primaryKey"`
	UserID            int64      `gorm:"column:user_id"`
	OrderID           int64      `gorm:"column:order_id"`
	InstanceID        *int64     `gorm:"column:instance_id"`
	SourceType        string     `gorm:"column:source_type"`
	Status            string     `gorm:"column:status"`
	AmountCents       int        `gorm:"column:amount_cents"`
	RewardRate        int        `gorm:"column:reward_rate"`
	Points            int        `gorm:"column:points"`
	RefNo             *string    `gorm:"column:ref_no"`
	PointLogID        *int64     `gorm:"column:point_log_id"`
	ReversePointLogID *int64     `gorm:"column:reverse_point_log_id"`
	ClaimedAt         *time.Time `gorm:"column:claimed_at"`
	CancelledAt       *time.Time `gorm:"column:cancelled_at"`
	ReversedAt        *time.Time `gorm:"column:reversed_at"`
	Remark            *string    `gorm:"column:remark"`
	PayloadSnapshot   JSONRaw    `gorm:"column:payload_snapshot"`
	CreatedAt         time.Time  `gorm:"column:created_at"`
	UpdatedAt         time.Time  `gorm:"column:updated_at"`
}

func (PointReward) TableName() string {
	return "point_rewards"
}

type PointTask struct {
	ID             int64      `gorm:"column:id;primaryKey" json:"id"`
	UserID         int64      `gorm:"column:user_id" json:"user_id"`
	TaskType       string     `gorm:"column:task_type" json:"task_type"`
	RewardPoints   int        `gorm:"column:reward_points" json:"reward_points"`
	SubmittedValue *string    `gorm:"column:submitted_value" json:"submitted_value"`
	CheckinDate    *time.Time `gorm:"column:checkin_date" json:"checkin_date"`
	CheckinPoints  *int       `gorm:"column:checkin_points" json:"checkin_points"`
	CompletedAt    *time.Time `gorm:"column:completed_at" json:"completed_at"`
	CreatedAt      time.Time  `gorm:"column:created_at" json:"created_at"`
	UpdatedAt      time.Time  `gorm:"column:updated_at" json:"updated_at"`
}

func (PointTask) TableName() string {
	return "point_tasks"
}

type PointWithdrawal struct {
	ID            int64      `gorm:"column:id;primaryKey" json:"id"`
	UserID        int64      `gorm:"column:user_id" json:"user_id"`
	PointsAmount  int        `gorm:"column:points_amount" json:"points_amount"`
	FeePoints     int        `gorm:"column:fee_points" json:"fee_points"`
	CreditedCents int        `gorm:"column:credited_cents" json:"credited_cents"`
	Status        string     `gorm:"column:status" json:"status"`
	Remark        *string    `gorm:"column:remark" json:"remark"`
	ProcessedAt   *time.Time `gorm:"column:processed_at" json:"processed_at"`
	CreatedAt     time.Time  `gorm:"column:created_at" json:"created_at"`
	UpdatedAt     time.Time  `gorm:"column:updated_at" json:"updated_at"`
}

func (PointWithdrawal) TableName() string {
	return "point_withdrawals"
}

type SpendEventTypeConfig struct {
	ID          int64   `gorm:"column:id;primaryKey"`
	Code        string  `gorm:"column:code"`
	Label       string  `gorm:"column:label"`
	Description *string `gorm:"column:description"`
	Enabled     bool    `gorm:"column:enabled"`
	SortOrder   int     `gorm:"column:sort_order"`
}

func (SpendEventTypeConfig) TableName() string {
	return "spend_event_type_configs"
}

type UserSpendEvent struct {
	ID              int64     `gorm:"column:id;primaryKey"`
	UserID          int64     `gorm:"column:user_id"`
	EventType       string    `gorm:"column:event_type"`
	EventKey        string    `gorm:"column:event_key"`
	AmountCents     int       `gorm:"column:amount_cents"`
	OrderID         *int64    `gorm:"column:order_id"`
	RefNo           *string   `gorm:"column:ref_no"`
	Remark          *string   `gorm:"column:remark"`
	PayloadSnapshot JSONRaw   `gorm:"column:payload_snapshot"`
	CreatedAt       time.Time `gorm:"column:created_at"`
	UpdatedAt       time.Time `gorm:"column:updated_at"`
}

func (UserSpendEvent) TableName() string {
	return "user_spend_events"
}

type NotificationPreference struct {
	ID           int64  `gorm:"column:id;primaryKey"`
	UserID       int64  `gorm:"column:user_id"`
	Category     string `gorm:"column:category"`
	InAppEnabled bool   `gorm:"column:in_app_enabled"`
	EmailEnabled bool   `gorm:"column:email_enabled"`
	SMSEnabled   bool   `gorm:"column:sms_enabled"`
}

func (NotificationPreference) TableName() string {
	return "notification_preferences"
}

type Announcement struct {
	ID             int64      `gorm:"column:id;primaryKey" json:"id"`
	Title          string     `gorm:"column:title" json:"title"`
	Content        string     `gorm:"column:content" json:"content"`
	Category       string     `gorm:"column:category" json:"category"`
	Level          string     `gorm:"column:level" json:"level"`
	Link           *string    `gorm:"column:link" json:"link"`
	ActionLabel    *string    `gorm:"column:action_label" json:"action_label"`
	ActionURL      *string    `gorm:"column:action_url" json:"action_url"`
	TargetType     string     `gorm:"column:target_type" json:"target_type"`
	TargetUserIDs  JSONRaw    `gorm:"column:target_user_ids" json:"target_user_ids"`
	IsPinned       bool       `gorm:"column:is_pinned" json:"is_pinned"`
	IsPublished    bool       `gorm:"column:is_published" json:"is_published"`
	PublishedAt    *time.Time `gorm:"column:published_at" json:"published_at"`
	ExpiresAt      *time.Time `gorm:"column:expires_at" json:"expires_at"`
	CreatedBy      *int64     `gorm:"column:created_by" json:"created_by"`
	CreatedByID    *int64     `gorm:"column:created_by_id" json:"created_by_id"`
	TargetAudience string     `gorm:"column:target_audience" json:"target_audience"`
	CreatedAt      time.Time  `gorm:"column:created_at" json:"created_at"`
	UpdatedAt      time.Time  `gorm:"column:updated_at" json:"updated_at"`
}

func (Announcement) TableName() string {
	return "announcements"
}

type Activity struct {
	ID                int64      `gorm:"column:id;primaryKey" json:"id"`
	Title             string     `gorm:"column:title" json:"title"`
	Subtitle          *string    `gorm:"column:subtitle" json:"subtitle"`
	Description       string     `gorm:"column:description" json:"description"`
	Content           *string    `gorm:"column:content" json:"content"`
	ImageURL          *string    `gorm:"column:image_url" json:"image_url"`
	BannerURL         *string    `gorm:"column:banner_url" json:"banner_url"`
	TargetURL         *string    `gorm:"column:target_url" json:"target_url"`
	Label             *string    `gorm:"column:label" json:"label"`
	TemplateKey       string     `gorm:"column:template_key" json:"template_key"`
	ButtonText        string     `gorm:"column:button_text" json:"button_text"`
	ParticipationMode string     `gorm:"column:participation_mode" json:"participation_mode"`
	PromoCodeID       *int64     `gorm:"column:promo_code_id" json:"promo_code_id"`
	Audience          string     `gorm:"column:audience" json:"audience"`
	Rules             *string    `gorm:"column:rules" json:"rules"`
	PerUserLimit      int        `gorm:"column:per_user_limit" json:"per_user_limit"`
	TotalLimit        int        `gorm:"column:total_limit" json:"total_limit"`
	LimitedTime       bool       `gorm:"column:limited_time" json:"limited_time"`
	StartsAt          *time.Time `gorm:"column:starts_at" json:"starts_at"`
	EndsAt            *time.Time `gorm:"column:ends_at" json:"ends_at"`
	IsPublished       bool       `gorm:"column:is_published" json:"is_published"`
	IsFeatured        bool       `gorm:"column:is_featured" json:"is_featured"`
	ShowOnHome        bool       `gorm:"column:show_on_home" json:"show_on_home"`
	SortOrder         int        `gorm:"column:sort_order" json:"sort_order"`
	CreatedBy         *int64     `gorm:"column:created_by" json:"created_by"`
	CreatedAt         time.Time  `gorm:"column:created_at" json:"created_at"`
	UpdatedAt         time.Time  `gorm:"column:updated_at" json:"updated_at"`
}

func (Activity) TableName() string {
	return "activities"
}

type ActivityProduct struct {
	ID                 int64    `gorm:"column:id;primaryKey" json:"id"`
	ActivityID         int64    `gorm:"column:activity_id" json:"activity_id"`
	ProductID          int64    `gorm:"column:product_id" json:"product_id"`
	SectionName        string   `gorm:"column:section_name" json:"section_name"`
	SectionDescription *string  `gorm:"column:section_description" json:"section_description"`
	CardStyle          string   `gorm:"column:card_style" json:"card_style"`
	CustomLabel        *string  `gorm:"column:custom_label" json:"custom_label"`
	ProductDescription *string  `gorm:"column:product_description" json:"product_description"`
	BillingCycle       *string  `gorm:"column:billing_cycle" json:"billing_cycle"`
	ActivityPrice      *float64 `gorm:"column:activity_price" json:"activity_price"`
	DiscountPercent    *float64 `gorm:"column:discount_percent" json:"discount_percent"`
	StockLimit         int      `gorm:"column:stock_limit" json:"stock_limit"`
	PerUserLimit       int      `gorm:"column:per_user_limit" json:"per_user_limit"`
	SortOrder          int      `gorm:"column:sort_order" json:"sort_order"`
}

func (ActivityProduct) TableName() string {
	return "activity_products"
}

type AnnouncementRead struct {
	ID             int64     `gorm:"column:id;primaryKey"`
	AnnouncementID int64     `gorm:"column:announcement_id"`
	UserID         int64     `gorm:"column:user_id"`
	ReadAt         time.Time `gorm:"column:read_at"`
	CreatedAt      time.Time `gorm:"column:created_at"`
	UpdatedAt      time.Time `gorm:"column:updated_at"`
}

func (AnnouncementRead) TableName() string {
	return "announcement_reads"
}

type Notification struct {
	ID          int64      `gorm:"column:id;primaryKey"`
	UserID      int64      `gorm:"column:user_id"`
	Category    string     `gorm:"column:category"`
	Level       string     `gorm:"column:level"`
	SenderID    *int64     `gorm:"column:sender_id"`
	SenderName  *string    `gorm:"column:sender_name"`
	SenderType  string     `gorm:"column:sender_type"`
	Title       string     `gorm:"column:title"`
	Content     string     `gorm:"column:content"`
	Link        *string    `gorm:"column:link"`
	ActionLabel *string    `gorm:"column:action_label"`
	ActionURL   *string    `gorm:"column:action_url"`
	IsRead      bool       `gorm:"column:is_read"`
	ReadAt      *time.Time `gorm:"column:read_at"`
	HandledAt   *time.Time `gorm:"column:handled_at"`
	ArchivedAt  *time.Time `gorm:"column:archived_at"`
	CreatedAt   time.Time  `gorm:"column:created_at"`
	UpdatedAt   time.Time  `gorm:"column:updated_at"`
}

func (Notification) TableName() string {
	return "notifications"
}

type TicketDepartment struct {
	ID               int64     `gorm:"column:id;primaryKey"`
	Code             *string   `gorm:"column:code"`
	Name             string    `gorm:"column:name"`
	Description      *string   `gorm:"column:description"`
	IsEnabled        bool      `gorm:"column:is_enabled"`
	SortOrder        int       `gorm:"column:sort_order"`
	MinMemberLevel   *int      `gorm:"column:min_member_level"`
	AutoReplyEnabled bool      `gorm:"column:auto_reply_enabled"`
	AutoReplyContent *string   `gorm:"column:auto_reply_content"`
	CreatedAt        time.Time `gorm:"column:created_at"`
	UpdatedAt        time.Time `gorm:"column:updated_at"`
}

func (TicketDepartment) TableName() string {
	return "ticket_departments"
}

type Ticket struct {
	ID                  int64      `gorm:"column:id;primaryKey"`
	TicketNo            string     `gorm:"column:ticket_no"`
	UserID              int64      `gorm:"column:user_id"`
	DepartmentID        *int64     `gorm:"column:department_id"`
	DepartmentName      *string    `gorm:"column:department_name"`
	InstanceID          *int64     `gorm:"column:instance_id"`
	Subject             string     `gorm:"column:subject"`
	Priority            string     `gorm:"column:priority"`
	Status              string     `gorm:"column:status"`
	LastMessageAt       *time.Time `gorm:"column:last_message_at"`
	LastReplyBy         *string    `gorm:"column:last_reply_by"`
	AssigneeID          *int64     `gorm:"column:assignee_id"`
	AssignedAt          *time.Time `gorm:"column:assigned_at"`
	UserUnreadCount     int        `gorm:"column:user_unread_count"`
	AdminUnreadCount    int        `gorm:"column:admin_unread_count"`
	ClosedAt            *time.Time `gorm:"column:closed_at"`
	SatisfactionRating  *int       `gorm:"column:satisfaction_rating"`
	SatisfactionComment *string    `gorm:"column:satisfaction_comment"`
	SatisfactionRatedAt *time.Time `gorm:"column:satisfaction_rated_at"`
	CreatedAt           time.Time  `gorm:"column:created_at"`
	UpdatedAt           time.Time  `gorm:"column:updated_at"`
}

func (Ticket) TableName() string {
	return "tickets"
}

type TicketMessage struct {
	ID          int64     `gorm:"column:id;primaryKey"`
	TicketID    int64     `gorm:"column:ticket_id"`
	SenderType  string    `gorm:"column:sender_type"`
	SenderID    *int64    `gorm:"column:sender_id"`
	Content     string    `gorm:"column:content"`
	Attachments JSONRaw   `gorm:"column:attachments"`
	IsInternal  bool      `gorm:"column:is_internal"`
	CreatedAt   time.Time `gorm:"column:created_at"`
	UpdatedAt   time.Time `gorm:"column:updated_at"`
}

func (TicketMessage) TableName() string {
	return "ticket_messages"
}

type TicketEvent struct {
	ID        int64     `gorm:"column:id;primaryKey"`
	TicketID  int64     `gorm:"column:ticket_id"`
	ActorType string    `gorm:"column:actor_type"`
	ActorID   *int64    `gorm:"column:actor_id"`
	EventType string    `gorm:"column:event_type"`
	FromValue *string   `gorm:"column:from_value"`
	ToValue   *string   `gorm:"column:to_value"`
	Message   *string   `gorm:"column:message"`
	Meta      JSONRaw   `gorm:"column:meta"`
	CreatedAt time.Time `gorm:"column:created_at"`
	UpdatedAt time.Time `gorm:"column:updated_at"`
}

func (TicketEvent) TableName() string {
	return "ticket_events"
}

type TicketAttachment struct {
	ID             int64     `gorm:"column:id;primaryKey"`
	Token          string    `gorm:"column:token"`
	StoragePath    string    `gorm:"column:storage_path"`
	OriginalName   *string   `gorm:"column:original_name"`
	ContentType    string    `gorm:"column:content_type"`
	Size           int       `gorm:"column:size"`
	UploadedByType string    `gorm:"column:uploaded_by_type"`
	UploadedByID   *int64    `gorm:"column:uploaded_by_id"`
	TicketID       *int64    `gorm:"column:ticket_id"`
	MessageID      *int64    `gorm:"column:message_id"`
	IsClaimed      bool      `gorm:"column:is_claimed"`
	CreatedAt      time.Time `gorm:"column:created_at"`
	UpdatedAt      time.Time `gorm:"column:updated_at"`
}

func (TicketAttachment) TableName() string {
	return "ticket_attachments"
}

type TicketReplyTemplate struct {
	ID           int64     `gorm:"column:id;primaryKey"`
	Title        string    `gorm:"column:title"`
	Content      string    `gorm:"column:content"`
	DepartmentID *int64    `gorm:"column:department_id"`
	IsEnabled    bool      `gorm:"column:is_enabled"`
	SortOrder    int       `gorm:"column:sort_order"`
	UsageCount   int       `gorm:"column:usage_count"`
	CreatedByID  *int64    `gorm:"column:created_by_id"`
	UpdatedByID  *int64    `gorm:"column:updated_by_id"`
	CreatedAt    time.Time `gorm:"column:created_at"`
	UpdatedAt    time.Time `gorm:"column:updated_at"`
}

func (TicketReplyTemplate) TableName() string {
	return "ticket_reply_templates"
}

type SystemSetting struct {
	ID          int64     `gorm:"column:id;primaryKey"`
	Key         string    `gorm:"column:key"`
	Value       JSONRaw   `gorm:"column:value"`
	Label       string    `gorm:"column:label"`
	Description *string   `gorm:"column:description"`
	CreatedAt   time.Time `gorm:"column:created_at"`
	UpdatedAt   time.Time `gorm:"column:updated_at"`
}

func (SystemSetting) TableName() string {
	return "system_settings"
}

type Instance struct {
	ID                int64      `gorm:"column:id;primaryKey" json:"id"`
	UserID            int64      `gorm:"column:user_id" json:"user_id"`
	OrderID           int64      `gorm:"column:order_id" json:"order_id"`
	ProductID         int64      `gorm:"column:product_id" json:"product_id"`
	CloudServerID     *int64     `gorm:"column:cloud_server_id" json:"cloud_server_id"`
	Status            string     `gorm:"column:status"`
	SuspendType       *string    `gorm:"column:suspend_type"`
	IsLocked          int        `gorm:"column:is_locked"`
	Internet          int        `gorm:"column:internet"`
	Cycle             string     `gorm:"column:cycle"`
	UnitPrice         int        `gorm:"column:unit_price"`
	AutoRenew         int        `gorm:"column:auto_renew"`
	NextRenewAmount   int        `gorm:"column:next_renew_amount"`
	Alias             *string    `gorm:"column:alias"`
	Hostname          *string    `gorm:"column:hostname"`
	OSImage           *string    `gorm:"column:os_image"`
	CPU               *int       `gorm:"column:cpu"`
	Memory            *int       `gorm:"column:memory"`
	SystemDiskSize    *int       `gorm:"column:system_disk_size"`
	DataDiskSize      *int       `gorm:"column:data_disk_size"`
	InBW              *int       `gorm:"column:in_bw"`
	OutBW             *int       `gorm:"column:out_bw"`
	IPNum             *int       `gorm:"column:ip_num"`
	NatACLLimit       *int       `gorm:"column:nat_acl_limit"`
	TrafficQuota      *int       `gorm:"column:traffic_quota"`
	TrafficType       *int       `gorm:"column:traffic_type"`
	ExpiresAt         *time.Time `gorm:"column:expires_at"`
	UpstreamID        *int64     `gorm:"column:upstream_id"`
	UpstreamTaskID    *int64     `gorm:"column:upstream_task_id"`
	UpstreamInvoiceID *int64     `gorm:"column:upstream_invoice_id"`
	UpstreamPayload   JSONRaw    `gorm:"column:upstream_payload"`
	MainIP            *string    `gorm:"column:main_ip"`
	RootPassword      *string    `gorm:"column:root_password"`
	SSHPort           *int       `gorm:"column:ssh_port"`
	ProvisionAttempts int        `gorm:"column:provision_attempts"`
	LastProvisionAt   *time.Time `gorm:"column:last_provision_at"`
	ProvisionLog      *string    `gorm:"column:provision_log"`
	DownstreamToken   *string    `gorm:"column:downstream_token"`
	TerminatedAt      *time.Time `gorm:"column:terminated_at"`
	CreatedAt         time.Time  `gorm:"column:created_at"`
	UpdatedAt         time.Time  `gorm:"column:updated_at"`
}

func (Instance) TableName() string {
	return "instances"
}

type AutoRenewalEvent struct {
	ID           int64      `gorm:"column:id;primaryKey"`
	EventKey     string     `gorm:"column:event_key"`
	UserID       int64      `gorm:"column:user_id"`
	InstanceID   int64      `gorm:"column:instance_id"`
	OrderID      *int64     `gorm:"column:order_id"`
	Status       string     `gorm:"column:status"`
	Cycles       int        `gorm:"column:cycles"`
	AmountCents  int        `gorm:"column:amount_cents"`
	OldExpiresAt time.Time  `gorm:"column:old_expires_at"`
	NewExpiresAt *time.Time `gorm:"column:new_expires_at"`
	ErrorCode    *string    `gorm:"column:error_code"`
	Message      *string    `gorm:"column:message"`
	ProcessedAt  *time.Time `gorm:"column:processed_at"`
	CreatedAt    time.Time  `gorm:"column:created_at"`
	UpdatedAt    time.Time  `gorm:"column:updated_at"`
}

type TaskRunLog struct {
	ID           int64      `gorm:"column:id;primaryKey"`
	TaskKey      string     `gorm:"column:task_key"`
	TaskName     string     `gorm:"column:task_name"`
	TriggerType  string     `gorm:"column:trigger_type"`
	Status       string     `gorm:"column:status"`
	OperatorID   *int64     `gorm:"column:operator_id"`
	StartedAt    time.Time  `gorm:"column:started_at"`
	FinishedAt   *time.Time `gorm:"column:finished_at"`
	DurationMS   *int       `gorm:"column:duration_ms"`
	Summary      JSONRaw    `gorm:"column:summary"`
	ErrorMessage *string    `gorm:"column:error_message"`
	CreatedAt    time.Time  `gorm:"column:created_at"`
	UpdatedAt    time.Time  `gorm:"column:updated_at"`
}

func (TaskRunLog) TableName() string {
	return "task_run_logs"
}

func (AutoRenewalEvent) TableName() string {
	return "auto_renewal_events"
}

func jsonObject(raw JSONRaw) map[string]any {
	if len(raw) == 0 {
		return nil
	}
	var out map[string]any
	if err := json.Unmarshal(raw, &out); err != nil {
		return nil
	}
	return out
}

func jsonRawFromMap(value map[string]any) JSONRaw {
	if value == nil {
		return nil
	}
	raw, err := json.Marshal(value)
	if err != nil {
		return nil
	}
	return JSONRaw(raw)
}

func jsonList(raw JSONRaw) []any {
	if len(raw) == 0 {
		return []any{}
	}
	var out []any
	if err := json.Unmarshal(raw, &out); err != nil {
		return []any{}
	}
	return out
}

func jsonMap(raw JSONRaw) map[string]any {
	if len(raw) == 0 {
		return nil
	}
	var out map[string]any
	if err := json.Unmarshal(raw, &out); err != nil {
		return nil
	}
	return out
}
