package oci

import (
	"context"
	"fmt"
	"time"

	"github.com/oracle/oci-go-sdk/v65/common"
	"github.com/oracle/oci-go-sdk/v65/tenantmanagercontrolplane"
)

// SubscriptionInfo 是租户订阅的摘要信息。
type SubscriptionInfo struct {
	ID          string     `json:"id"`
	ServiceName string     `json:"serviceName"`
	TimeCreated *time.Time `json:"timeCreated"`
	TimeUpdated *time.Time `json:"timeUpdated"`
}

// PromotionInfo 是订阅下的一条促销记录。
type PromotionInfo struct {
	Duration      int        `json:"duration"`
	DurationUnit  string     `json:"durationUnit"`
	Amount        float32    `json:"amount"`
	Status        string     `json:"status"`
	IsIntentToPay bool       `json:"isIntentToPay"`
	CurrencyUnit  string     `json:"currencyUnit"`
	TimeStarted   *time.Time `json:"timeStarted"`
	TimeExpired   *time.Time `json:"timeExpired"`
}

// SubscriptionDetail 是单个订阅的完整信息（Classic v1 订阅）。
type SubscriptionDetail struct {
	ID                       string          `json:"id"`
	ServiceName              string          `json:"serviceName"`
	ClassicSubscriptionID    string          `json:"classicSubscriptionId"`
	PaymentModel             string          `json:"paymentModel"`
	SubscriptionTier         string          `json:"subscriptionTier"`
	LifecycleState           string          `json:"lifecycleState"`
	ProgramType              string          `json:"programType"`
	CustomerCountryCode      string          `json:"customerCountryCode"`
	CloudAmountCurrency      string          `json:"cloudAmountCurrency"`
	CsiNumber                string          `json:"csiNumber"`
	RegionAssignment         string          `json:"regionAssignment"`
	IsGovernmentSubscription bool            `json:"isGovernmentSubscription"`
	Promotions               []PromotionInfo `json:"promotions"`
	StartDate                *time.Time      `json:"startDate"`
	EndDate                  *time.Time      `json:"endDate"`
	TimeCreated              *time.Time      `json:"timeCreated"`
	TimeUpdated              *time.Time      `json:"timeUpdated"`
}

// ListSubscriptions 实现 Client：分页列出租户全部订阅摘要。
func (c *RealClient) ListSubscriptions(ctx context.Context, cred Credentials) ([]SubscriptionInfo, error) {
	sc, err := tenantmanagercontrolplane.NewSubscriptionClientWithConfigurationProvider(provider(cred))
	if err != nil {
		return nil, fmt.Errorf("new subscription client: %w", err)
	}
	applyProxy(&sc.BaseClient, cred)
	var subs []SubscriptionInfo
	var page *string
	for {
		resp, err := sc.ListSubscriptions(ctx, tenantmanagercontrolplane.ListSubscriptionsRequest{
			CompartmentId: &cred.TenancyOCID,
			Page:          page,
		})
		if err != nil {
			return nil, fmt.Errorf("list subscriptions: %w", err)
		}
		for _, item := range resp.Items {
			subs = append(subs, SubscriptionInfo{
				ID:          deref(item.GetId()),
				ServiceName: deref(item.GetServiceName()),
				TimeCreated: sdkTime(item.GetTimeCreated()),
				TimeUpdated: sdkTime(item.GetTimeUpdated()),
			})
		}
		if resp.OpcNextPage == nil {
			return orEmpty(subs), nil
		}
		page = resp.OpcNextPage
	}
}

// GetSubscription 实现 Client：查询单个订阅的完整信息。
func (c *RealClient) GetSubscription(ctx context.Context, cred Credentials, subscriptionID string) (SubscriptionDetail, error) {
	sc, err := tenantmanagercontrolplane.NewSubscriptionClientWithConfigurationProvider(provider(cred))
	if err != nil {
		return SubscriptionDetail{}, fmt.Errorf("new subscription client: %w", err)
	}
	applyProxy(&sc.BaseClient, cred)
	resp, err := sc.GetSubscription(ctx, tenantmanagercontrolplane.GetSubscriptionRequest{
		SubscriptionId: &subscriptionID,
	})
	if err != nil {
		return SubscriptionDetail{}, fmt.Errorf("get subscription %s: %w", subscriptionID, err)
	}
	switch sub := resp.Subscription.(type) {
	case tenantmanagercontrolplane.ClassicSubscription:
		return toSubscriptionDetail(sub), nil
	case *tenantmanagercontrolplane.ClassicSubscription:
		return toSubscriptionDetail(*sub), nil
	default:
		return SubscriptionDetail{}, fmt.Errorf("get subscription %s: unexpected type %T", subscriptionID, resp.Subscription)
	}
}

func toSubscriptionDetail(sub tenantmanagercontrolplane.ClassicSubscription) SubscriptionDetail {
	detail := SubscriptionDetail{
		ID:                       deref(sub.Id),
		ServiceName:              deref(sub.ServiceName),
		ClassicSubscriptionID:    deref(sub.ClassicSubscriptionId),
		PaymentModel:             deref(sub.PaymentModel),
		SubscriptionTier:         deref(sub.SubscriptionTier),
		LifecycleState:           string(sub.LifecycleState),
		ProgramType:              deref(sub.ProgramType),
		CustomerCountryCode:      deref(sub.CustomerCountryCode),
		CloudAmountCurrency:      deref(sub.CloudAmountCurrency),
		CsiNumber:                deref(sub.CsiNumber),
		RegionAssignment:         deref(sub.RegionAssignment),
		IsGovernmentSubscription: sub.IsGovernmentSubscription != nil && *sub.IsGovernmentSubscription,
		StartDate:                sdkTime(sub.StartDate),
		EndDate:                  sdkTime(sub.EndDate),
		TimeCreated:              sdkTime(sub.TimeCreated),
		TimeUpdated:              sdkTime(sub.TimeUpdated),
	}
	detail.Promotions = make([]PromotionInfo, 0, len(sub.Promotion))
	for _, p := range sub.Promotion {
		detail.Promotions = append(detail.Promotions, toPromotionInfo(p))
	}
	return detail
}

func toPromotionInfo(p tenantmanagercontrolplane.Promotion) PromotionInfo {
	info := PromotionInfo{
		Status:       string(p.Status),
		DurationUnit: deref(p.DurationUnit),
		CurrencyUnit: deref(p.CurrencyUnit),
		TimeStarted:  sdkTime(p.TimeStarted),
		TimeExpired:  sdkTime(p.TimeExpired),
	}
	if p.Duration != nil {
		info.Duration = *p.Duration
	}
	if p.Amount != nil {
		info.Amount = *p.Amount
	}
	if p.IsIntentToPay != nil {
		info.IsIntentToPay = *p.IsIntentToPay
	}
	return info
}

func sdkTime(t *common.SDKTime) *time.Time {
	if t == nil {
		return nil
	}
	return &t.Time
}
