package usecase

import (
	"context"
	"testing"

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

func TestCheckCreditLineErrors(t *testing.T) {
	svc, _ := newTestService()
	ctx := context.Background()

	_, err := svc.CheckCreditLine(ctx, uuid.Must(uuid.NewV7()), 100)
	if err == nil {
		t.Fatal("expected error for missing company")
	}

	company := domain.Company{ID: uuid.Must(uuid.NewV7())}
	svc.repo.(*MockRepository).companies = append(svc.repo.(*MockRepository).companies, company)

	_, err = svc.CheckCreditLine(ctx, company.ID, 100)
	if err == nil {
		t.Fatal("expected error when credit line not enabled")
	}
}

func TestCheckCreditLineAvailable(t *testing.T) {
	svc, repo := newTestService()
	ctx := context.Background()

	company := domain.Company{
		ID:               uuid.Must(uuid.NewV7()),
		CreditLimitCents: 10000,
		CreditUsedCents:  2500,
	}
	repo.companies = append(repo.companies, company)

	ok, err := svc.CheckCreditLine(ctx, company.ID, 5000)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !ok {
		t.Fatal("expected credit line to be available")
	}
}

func TestUseAndReleaseCreditLine(t *testing.T) {
	svc, repo := newTestService()
	ctx := context.Background()

	company := domain.Company{
		ID:               uuid.Must(uuid.NewV7()),
		CreditLimitCents: 9000,
		CreditUsedCents:  1000,
	}
	repo.companies = append(repo.companies, company)

	if err := svc.UseCreditLine(ctx, company.ID, 3000); err != nil {
		t.Fatalf("unexpected error using credit line: %v", err)
	}

	updated, _ := repo.GetCompany(ctx, company.ID)
	if updated.CreditUsedCents != 4000 {
		t.Fatalf("expected credit used to be 4000, got %d", updated.CreditUsedCents)
	}

	if err := svc.ReleaseCreditLine(ctx, company.ID, 5000); err != nil {
		t.Fatalf("unexpected error releasing credit: %v", err)
	}

	updated, _ = repo.GetCompany(ctx, company.ID)
	if updated.CreditUsedCents != 0 {
		t.Fatalf("expected credit used to floor at 0, got %d", updated.CreditUsedCents)
	}
}

func TestUseCreditLineInsufficient(t *testing.T) {
	svc, repo := newTestService()
	ctx := context.Background()

	company := domain.Company{
		ID:               uuid.Must(uuid.NewV7()),
		CreditLimitCents: 5000,
		CreditUsedCents:  4500,
	}
	repo.companies = append(repo.companies, company)

	if err := svc.UseCreditLine(ctx, company.ID, 1000); err != ErrInsufficientCredit {
		t.Fatalf("expected ErrInsufficientCredit, got %v", err)
	}
}

func TestSetCreditLimit(t *testing.T) {
	svc, repo := newTestService()
	ctx := context.Background()

	company := domain.Company{ID: uuid.Must(uuid.NewV7())}
	repo.companies = append(repo.companies, company)

	if err := svc.SetCreditLimit(ctx, company.ID, 12000); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	updated, _ := repo.GetCompany(ctx, company.ID)
	if updated.CreditLimitCents != 12000 {
		t.Fatalf("expected credit limit to be 12000, got %d", updated.CreditLimitCents)
	}
}
