package models

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestIsTrialActive(t *testing.T) {
	now := time.Now().UTC()
	future := now.Add(24 * time.Hour)
	past := now.Add(-24 * time.Hour)

	tests := []struct {
		name     string
		sub      *UserSubscription
		expected bool
	}{
		{
			name:     "trial_end in future returns true",
			sub:      &UserSubscription{TrialEnd: &future},
			expected: true,
		},
		{
			name:     "trial_end in past returns false",
			sub:      &UserSubscription{TrialEnd: &past},
			expected: false,
		},
		{
			name:     "trial_end nil returns false",
			sub:      &UserSubscription{TrialEnd: nil},
			expected: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := tt.sub.IsTrialActive()
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestIsPro(t *testing.T) {
	now := time.Now().UTC()
	future := now.Add(24 * time.Hour)
	past := now.Add(-24 * time.Hour)

	tests := []struct {
		name     string
		sub      *UserSubscription
		expected bool
	}{
		{
			name: "tier=pro, expires_at in future returns true",
			sub: &UserSubscription{
				Tier:      TierPro,
				ExpiresAt: &future,
			},
			expected: true,
		},
		{
			name: "tier=pro, expires_at in past returns false",
			sub: &UserSubscription{
				Tier:      TierPro,
				ExpiresAt: &past,
			},
			expected: false,
		},
		{
			name: "tier=free, trial active returns true",
			sub: &UserSubscription{
				Tier:     TierFree,
				TrialEnd: &future,
			},
			expected: true,
		},
		{
			name: "tier=free, trial expired returns false",
			sub: &UserSubscription{
				Tier:     TierFree,
				TrialEnd: &past,
			},
			expected: false,
		},
		{
			name: "tier=free, no trial returns false",
			sub: &UserSubscription{
				Tier:     TierFree,
				TrialEnd: nil,
			},
			expected: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := tt.sub.IsPro()
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestHasSubscriptionHelpers(t *testing.T) {
	empty := ""
	validStripeID := "sub_1234567890"
	validReceipt := "MIIT..."
	validToken := "google-purchase-token-123"

	tests := []struct {
		name     string
		sub      *UserSubscription
		method   string
		expected bool
	}{
		// HasStripeSubscription
		{
			name:     "HasStripeSubscription with nil returns false",
			sub:      &UserSubscription{StripeSubscriptionID: nil},
			method:   "stripe",
			expected: false,
		},
		{
			name:     "HasStripeSubscription with empty string returns false",
			sub:      &UserSubscription{StripeSubscriptionID: &empty},
			method:   "stripe",
			expected: false,
		},
		{
			name:     "HasStripeSubscription with valid ID returns true",
			sub:      &UserSubscription{StripeSubscriptionID: &validStripeID},
			method:   "stripe",
			expected: true,
		},
		// HasAppleSubscription
		{
			name:     "HasAppleSubscription with nil returns false",
			sub:      &UserSubscription{AppleReceiptData: nil},
			method:   "apple",
			expected: false,
		},
		{
			name:     "HasAppleSubscription with empty string returns false",
			sub:      &UserSubscription{AppleReceiptData: &empty},
			method:   "apple",
			expected: false,
		},
		{
			name:     "HasAppleSubscription with valid receipt returns true",
			sub:      &UserSubscription{AppleReceiptData: &validReceipt},
			method:   "apple",
			expected: true,
		},
		// HasGoogleSubscription
		{
			name:     "HasGoogleSubscription with nil returns false",
			sub:      &UserSubscription{GooglePurchaseToken: nil},
			method:   "google",
			expected: false,
		},
		{
			name:     "HasGoogleSubscription with empty string returns false",
			sub:      &UserSubscription{GooglePurchaseToken: &empty},
			method:   "google",
			expected: false,
		},
		{
			name:     "HasGoogleSubscription with valid token returns true",
			sub:      &UserSubscription{GooglePurchaseToken: &validToken},
			method:   "google",
			expected: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var result bool
			switch tt.method {
			case "stripe":
				result = tt.sub.HasStripeSubscription()
			case "apple":
				result = tt.sub.HasAppleSubscription()
			case "google":
				result = tt.sub.HasGoogleSubscription()
			}
			assert.Equal(t, tt.expected, result)
		})
	}
}
