package services

// Live-DB tests for FirmDashboardDefaultService — gated on
// TEST_DATABASE_URL like the rest of the integration suite.
//
// These cover the round-trip (Set → Get → Clear → Get) and the
// SanitizeForRead behavior on read. Pure-function validation lives in
// dashboard_layout_spec_test.go.

import (
	"context"
	"encoding/json"
	"os"
	"testing"

	"github.com/google/uuid"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
)

func openTestDBForFirmDefault(t *testing.T) *sqlx.DB {
	t.Helper()
	url := os.Getenv("TEST_DATABASE_URL")
	if url == "" {
		t.Skip("TEST_DATABASE_URL not set — skipping firm-dashboard-default live test")
	}
	db, err := sqlx.Connect("postgres", url)
	if err != nil {
		t.Fatalf("connect: %v", err)
	}
	return db
}

func TestFirmDashboardDefault_RoundTrip(t *testing.T) {
	db := openTestDBForFirmDefault(t)
	defer db.Close()
	svc := NewFirmDashboardDefaultService(db)
	ctx := context.Background()

	// Start clean — prior tests may have left a row.
	if err := svc.Clear(ctx); err != nil {
		t.Fatalf("pre-clear: %v", err)
	}

	if _, ok, err := svc.Get(ctx); err != nil || ok {
		t.Fatalf("Get after Clear: ok=%v err=%v; want ok=false err=nil", ok, err)
	}

	spec := FactoryDefaultLayout()
	if _, err := svc.Set(ctx, spec, uuid.Nil); err != nil {
		t.Fatalf("Set factory: %v", err)
	}

	got, ok, err := svc.Get(ctx)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if !ok {
		t.Fatal("Get: ok=false after Set; want true")
	}
	if len(got.Widgets) != len(spec.Widgets) {
		t.Errorf("widget count mismatch: %d vs %d", len(got.Widgets), len(spec.Widgets))
	}
	if got.Version != spec.Version {
		t.Errorf("version mismatch: %d vs %d", got.Version, spec.Version)
	}

	// Clear is idempotent.
	if err := svc.Clear(ctx); err != nil {
		t.Fatalf("clear after set: %v", err)
	}
	if err := svc.Clear(ctx); err != nil {
		t.Fatalf("second clear: %v", err)
	}
	if _, ok, err := svc.Get(ctx); err != nil || ok {
		t.Fatalf("Get after Clear: ok=%v err=%v; want false/nil", ok, err)
	}
}

func TestFirmDashboardDefault_RejectsInvalid(t *testing.T) {
	db := openTestDBForFirmDefault(t)
	defer db.Close()
	svc := NewFirmDashboardDefaultService(db)
	ctx := context.Background()

	bad := DashboardLayoutSpec{Version: 1, Widgets: []DashboardWidgetRef{
		{Key: WidgetUpcomingDeadlines, Visible: true, Settings: json.RawMessage(`{"count": 7}`)},
	}}
	_, err := svc.Set(ctx, bad, uuid.Nil)
	if err == nil {
		t.Fatal("Set with invalid count: err=nil; want ErrInvalidInput")
	}
}
