package usecase

import (
	"context"
	"errors"
	"strings"
	"testing"
	"time"

	"github.com/gofrs/uuid/v5"
	"github.com/saveinmed/backend-go/internal/domain"
)

type failingBatchRepo struct {
	*MockRepository
}

func (f *failingBatchRepo) BatchCreateProducts(ctx context.Context, products []domain.Product) error {
	return errors.New("boom")
}

func (f *failingBatchRepo) CreateInventoryItem(ctx context.Context, item *domain.InventoryItem) error {
	return errors.New("boom")
}

func (f *failingBatchRepo) GetInventoryItem(ctx context.Context, id uuid.UUID) (*domain.InventoryItem, error) {
	return nil, errors.New("boom")
}

func (f *failingBatchRepo) UpdateInventoryItem(ctx context.Context, item *domain.InventoryItem) error {
	return errors.New("boom")
}

func TestImportProductsSuccess(t *testing.T) {
	repo := NewMockRepository()
	svc := NewService(repo, &MockPaymentGateway{}, nil, &MockNotificationService{}, 2.5, 0.12, "secret", time.Hour, "pepper")

	csvData := strings.NewReader("name,price,stock,description,ean\nAspirin,12.5,5,Anti-inflammatory,123\nIbuprofen,10,0,,\n")
	sellerID := uuid.Must(uuid.NewV7())

	report, err := svc.ImportProducts(context.Background(), sellerID, csvData)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if report.TotalProcessed != 2 {
		t.Fatalf("expected total processed 2, got %d", report.TotalProcessed)
	}
	if report.SuccessCount != 2 {
		t.Fatalf("expected success count 2, got %d", report.SuccessCount)
	}
	if report.FailedCount != 0 {
		t.Fatalf("expected failed count 0, got %d", report.FailedCount)
	}

	if len(repo.products) != 2 {
		t.Fatalf("expected 2 products, got %d", len(repo.products))
	}

	if repo.products[0].SellerID != sellerID {
		t.Errorf("expected seller ID %s, got %s", sellerID, repo.products[0].SellerID)
	}
	if repo.products[0].PriceCents != 1250 {
		t.Errorf("expected price cents 1250, got %d", repo.products[0].PriceCents)
	}
	// Stock check removed (Dictionary Mode)
}

func TestImportProductsMissingHeaders(t *testing.T) {
	repo := NewMockRepository()
	svc := NewService(repo, &MockPaymentGateway{}, nil, &MockNotificationService{}, 2.5, 0.12, "secret", time.Hour, "pepper")

	csvData := strings.NewReader("ean,stock\n123,5\n")
	_, err := svc.ImportProducts(context.Background(), uuid.Must(uuid.NewV7()), csvData)
	if err == nil {
		t.Fatal("expected error for missing headers")
	}
	if !strings.Contains(err.Error(), "missing required header") {
		t.Fatalf("expected missing header error, got %v", err)
	}
}

func TestImportProductsEmptyCSV(t *testing.T) {
	repo := NewMockRepository()
	svc := NewService(repo, &MockPaymentGateway{}, nil, &MockNotificationService{}, 2.5, 0.12, "secret", time.Hour, "pepper")

	csvData := strings.NewReader("name,price\n")
	_, err := svc.ImportProducts(context.Background(), uuid.Must(uuid.NewV7()), csvData)
	if err == nil {
		t.Fatal("expected error for empty CSV")
	}
	if !strings.Contains(err.Error(), "csv file is empty") {
		t.Fatalf("expected empty csv error, got %v", err)
	}
}

func TestImportProductsInvalidRows(t *testing.T) {
	repo := NewMockRepository()
	svc := NewService(repo, &MockPaymentGateway{}, nil, &MockNotificationService{}, 2.5, 0.12, "secret", time.Hour, "pepper")

	csvData := strings.NewReader("name,price,stock\n,12.5,5\nValid,abc,2\nGood,5,1\n")
	sellerID := uuid.Must(uuid.NewV7())

	report, err := svc.ImportProducts(context.Background(), sellerID, csvData)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if report.TotalProcessed != 3 {
		t.Fatalf("expected total processed 3, got %d", report.TotalProcessed)
	}
	if report.FailedCount != 2 {
		t.Fatalf("expected failed count 2, got %d", report.FailedCount)
	}
	if report.SuccessCount != 1 {
		t.Fatalf("expected success count 1, got %d", report.SuccessCount)
	}
	if len(report.Errors) != 2 {
		t.Fatalf("expected 2 errors, got %d", len(report.Errors))
	}

	if len(repo.products) != 1 {
		t.Fatalf("expected 1 product, got %d", len(repo.products))
	}
}

func TestImportProductsBatchInsertFailure(t *testing.T) {
	baseRepo := NewMockRepository()
	repo := &failingBatchRepo{MockRepository: baseRepo}
	svc := NewService(repo, &MockPaymentGateway{}, nil, &MockNotificationService{}, 2.5, 0.12, "secret", time.Hour, "pepper")

	csvData := strings.NewReader("name,price\nItem,12.5\n")
	_, err := svc.ImportProducts(context.Background(), uuid.Must(uuid.NewV7()), csvData)
	if err == nil {
		t.Fatal("expected batch insert error")
	}
	if !strings.Contains(err.Error(), "batch insert failed") {
		t.Fatalf("expected batch insert error, got %v", err)
	}
}
