package storage

import (
	"os"
	"path/filepath"
	"testing"
	"time"

	"crm-go/models"
)

func TestUpdateTrialPeriodWithIsTrial(t *testing.T) {
	// Create a temporary directory for test data
	tempDir, err := os.MkdirTemp("", "trial_test")
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tempDir)

	// Create a test storage
	testFilePath := filepath.Join(tempDir, "trial_periods.json")
	storage := NewTrialPeriodStorage(testFilePath)

	// Create a trial period with isTrial = true
	now := time.Now()
	startTime := now
	endTime := now.Add(7 * 24 * time.Hour)

	trialPeriod := models.TrialPeriod{
		CustomerName: "test-customer-001",
		StartTime:    startTime,
		EndTime:      endTime,
		IsTrial:      true,
	}

	createdPeriod, err := storage.CreateTrialPeriod(trialPeriod)
	if err != nil {
		t.Fatalf("Failed to create trial period: %v", err)
	}

	if createdPeriod.ID == "" {
		t.Fatal("Created trial period should have an ID")
	}

	if !createdPeriod.IsTrial {
		t.Fatal("Created trial period should have IsTrial = true")
	}

	// Test updating isTrial to false
	isTrialFalse := false
	updateRequest := models.UpdateTrialPeriodRequest{
		IsTrial: &isTrialFalse,
	}

	err = storage.UpdateTrialPeriod(createdPeriod.ID, updateRequest)
	if err != nil {
		t.Fatalf("Failed to update trial period: %v", err)
	}

	// Verify the update
	updatedPeriod, err := storage.GetTrialPeriodByID(createdPeriod.ID)
	if err != nil {
		t.Fatalf("Failed to get updated trial period: %v", err)
	}

	if updatedPeriod == nil {
		t.Fatal("Updated trial period should not be nil")
	}

	if updatedPeriod.IsTrial {
		t.Fatal("Updated trial period should have IsTrial = false")
	}

	// Test updating isTrial back to true
	isTrialTrue := true
	updateRequest2 := models.UpdateTrialPeriodRequest{
		IsTrial: &isTrialTrue,
	}

	err = storage.UpdateTrialPeriod(createdPeriod.ID, updateRequest2)
	if err != nil {
		t.Fatalf("Failed to update trial period back to true: %v", err)
	}

	// Verify the update
	updatedPeriod2, err := storage.GetTrialPeriodByID(createdPeriod.ID)
	if err != nil {
		t.Fatalf("Failed to get updated trial period: %v", err)
	}

	if !updatedPeriod2.IsTrial {
		t.Fatal("Updated trial period should have IsTrial = true")
	}
}

func TestUpdateTrialPeriodWithStartEndTime(t *testing.T) {
	// Create a temporary directory for test data
	tempDir, err := os.MkdirTemp("", "trial_test_time")
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tempDir)

	// Create a test storage
	testFilePath := filepath.Join(tempDir, "trial_periods.json")
	storage := NewTrialPeriodStorage(testFilePath)

	// Create a trial period
	now := time.Now()
	startTime := now
	endTime := now.Add(7 * 24 * time.Hour)

	trialPeriod := models.TrialPeriod{
		CustomerName: "test-customer-002",
		StartTime:    startTime,
		EndTime:      endTime,
		IsTrial:      true,
	}

	createdPeriod, err := storage.CreateTrialPeriod(trialPeriod)
	if err != nil {
		t.Fatalf("Failed to create trial period: %v", err)
	}

	// Update start and end times along with isTrial
	newStartTime := now.Add(1 * 24 * time.Hour).Format(time.RFC3339)
	newEndTime := now.Add(14 * 24 * time.Hour).Format(time.RFC3339)
	isTrialFalse := false

	updateRequest := models.UpdateTrialPeriodRequest{
		StartTime: &newStartTime,
		EndTime:   &newEndTime,
		IsTrial:   &isTrialFalse,
	}

	err = storage.UpdateTrialPeriod(createdPeriod.ID, updateRequest)
	if err != nil {
		t.Fatalf("Failed to update trial period: %v", err)
	}

	// Verify all updates
	updatedPeriod, err := storage.GetTrialPeriodByID(createdPeriod.ID)
	if err != nil {
		t.Fatalf("Failed to get updated trial period: %v", err)
	}

	if updatedPeriod == nil {
		t.Fatal("Updated trial period should not be nil")
	}

	if updatedPeriod.IsTrial {
		t.Fatal("Updated trial period should have IsTrial = false")
	}

	// Verify start time was updated (approximately)
	expectedStartTime, _ := time.Parse(time.RFC3339, newStartTime)
	if !updatedPeriod.StartTime.Equal(expectedStartTime) {
		t.Fatalf("StartTime mismatch: expected %v, got %v", expectedStartTime, updatedPeriod.StartTime)
	}

	// Verify end time was updated
	expectedEndTime, _ := time.Parse(time.RFC3339, newEndTime)
	if !updatedPeriod.EndTime.Equal(expectedEndTime) {
		t.Fatalf("EndTime mismatch: expected %v, got %v", expectedEndTime, updatedPeriod.EndTime)
	}
}

func TestGetAllTrialPeriods(t *testing.T) {
	// Create a temporary directory for test data
	tempDir, err := os.MkdirTemp("", "trial_test_all")
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tempDir)

	// Create a test storage
	testFilePath := filepath.Join(tempDir, "trial_periods.json")
	storage := NewTrialPeriodStorage(testFilePath)

	// Initially should be empty
	periods, err := storage.GetAllTrialPeriods()
	if err != nil {
		t.Fatalf("Failed to get all trial periods: %v", err)
	}
	if len(periods) != 0 {
		t.Fatalf("Expected 0 periods, got %d", len(periods))
	}

	// Create multiple trial periods
	now := time.Now()
	for i := 0; i < 3; i++ {
		trialPeriod := models.TrialPeriod{
			CustomerName: "test-customer-bulk",
			StartTime:    now.Add(time.Duration(i) * 24 * time.Hour),
			EndTime:      now.Add(time.Duration(i+7) * 24 * time.Hour),
			IsTrial:      i%2 == 0, // Alternate true/false
		}
		_, err := storage.CreateTrialPeriod(trialPeriod)
		if err != nil {
			t.Fatalf("Failed to create trial period %d: %v", i, err)
		}
		// Add small delay to ensure different createdAt times
		time.Sleep(10 * time.Millisecond)
	}

	// Verify all periods are retrieved
	periods, err = storage.GetAllTrialPeriods()
	if err != nil {
		t.Fatalf("Failed to get all trial periods: %v", err)
	}
	if len(periods) != 3 {
		t.Fatalf("Expected 3 periods, got %d", len(periods))
	}

	// Verify periods are sorted by CreatedAt descending (newest first)
	for i := 0; i < len(periods)-1; i++ {
		if periods[i].CreatedAt.Before(periods[i+1].CreatedAt) {
			t.Fatal("Periods should be sorted by CreatedAt descending")
		}
	}
}

func TestDeleteTrialPeriod(t *testing.T) {
	// Create a temporary directory for test data
	tempDir, err := os.MkdirTemp("", "trial_test_delete")
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tempDir)

	// Create a test storage
	testFilePath := filepath.Join(tempDir, "trial_periods.json")
	storage := NewTrialPeriodStorage(testFilePath)

	// Create a trial period
	now := time.Now()
	trialPeriod := models.TrialPeriod{
		CustomerName: "test-customer-delete",
		StartTime:    now,
		EndTime:      now.Add(7 * 24 * time.Hour),
		IsTrial:      true,
	}

	createdPeriod, err := storage.CreateTrialPeriod(trialPeriod)
	if err != nil {
		t.Fatalf("Failed to create trial period: %v", err)
	}

	// Verify it exists
	existingPeriod, err := storage.GetTrialPeriodByID(createdPeriod.ID)
	if err != nil {
		t.Fatalf("Failed to get trial period: %v", err)
	}
	if existingPeriod == nil {
		t.Fatal("Trial period should exist after creation")
	}

	// Delete the trial period
	err = storage.DeleteTrialPeriod(createdPeriod.ID)
	if err != nil {
		t.Fatalf("Failed to delete trial period: %v", err)
	}

	// Verify it no longer exists
	deletedPeriod, err := storage.GetTrialPeriodByID(createdPeriod.ID)
	if err != nil {
		t.Fatalf("Failed to get trial period after delete: %v", err)
	}
	if deletedPeriod != nil {
		t.Fatal("Trial period should not exist after deletion")
	}
}
