package dashboard

import (
	"testing"
	"time"

	"system-altrak/internal/domain"
	"system-altrak/internal/repository"

	"github.com/glebarez/sqlite"
	"gorm.io/gorm"
)

func newDashboardTestDB(t *testing.T) *gorm.DB {
	t.Helper()

	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	if err != nil {
		t.Fatalf("failed to open sqlite database: %v", err)
	}

	if err := db.AutoMigrate(&domain.CustomerProfile{}, &domain.OperationalRecord{}); err != nil {
		t.Fatalf("failed to migrate dashboard schema: %v", err)
	}

	return db
}

func TestGetStatsReturnsCountsAndTrendSeries(t *testing.T) {
	db := newDashboardTestDB(t)

	if err := db.Create(&domain.CustomerProfile{
		CustomerName: "Alpha One",
		BranchID:     1,
	}).Error; err != nil {
		t.Fatalf("failed to seed customer profile: %v", err)
	}

	localNow := time.Now().Local()
	testTime := time.Date(localNow.Year(), localNow.Month(), localNow.Day(), 12, 0, 0, 0, localNow.Location())
	if err := db.Create(&domain.OperationalRecord{
		BaseModel: domain.BaseModel{
			CreatedAt: testTime,
		},
		PsoNo:        "PSO-001",
		CustomerName: "Alpha One",
		BranchID:     1,
		IsVerified:   false,
	}).Error; err != nil {
		t.Fatalf("failed to seed pending operational record: %v", err)
	}
	if err := db.Create(&domain.OperationalRecord{
		BaseModel: domain.BaseModel{
			CreatedAt: testTime,
		},
		PsoNo:        "PSO-002",
		CustomerName: "Alpha One",
		BranchID:     1,
		IsVerified:   true,
		VerifiedAt:   &testTime,
	}).Error; err != nil {
		t.Fatalf("failed to seed verified operational record: %v", err)
	}

	baseRepo := repository.NewRepository(db)
	repo := NewRepository(baseRepo)

	stats, err := repo.GetStats(1, "admin")
	if err != nil {
		t.Fatalf("get stats failed: %v", err)
	}

	if stats["active_customers"] != int64(1) {
		t.Fatalf("expected one customer, got=%v", stats["active_customers"])
	}
	if stats["pending_docs"] != int64(1) {
		t.Fatalf("expected one pending doc, got=%v", stats["pending_docs"])
	}
	if stats["verified_docs"] != int64(1) {
		t.Fatalf("expected one verified doc, got=%v", stats["verified_docs"])
	}
	if stats["total_docs"] != int64(2) {
		t.Fatalf("expected two total docs, got=%v", stats["total_docs"])
	}

	trend, ok := stats["activity_trend"].([]dashboardTrendPoint)
	if !ok {
		t.Fatalf("expected activity_trend slice, got=%T", stats["activity_trend"])
	}
	if len(trend) != 30 {
		t.Fatalf("expected 30-day trend series, got=%d", len(trend))
	}
	last := trend[len(trend)-1]
	if last.Documents != 2 || last.Verified != 1 {
		t.Fatalf("unexpected latest trend point: %+v", last)
	}
}

func TestGetStatsReturnsErrorWhenDatabaseFails(t *testing.T) {
	db := newDashboardTestDB(t)

	baseRepo := repository.NewRepository(db)
	repo := NewRepository(baseRepo)

	sqlDB, err := db.DB()
	if err != nil {
		t.Fatalf("failed to access underlying sql DB: %v", err)
	}
	if err := sqlDB.Close(); err != nil {
		t.Fatalf("failed to close database: %v", err)
	}

	if _, err := repo.GetStats(1, "admin"); err == nil {
		t.Fatal("expected repository error when database is closed")
	}
}
