package packs

import (
	"context"
	"strings"
	"testing"

	sqlmock "github.com/DATA-DOG/go-sqlmock"
)

func TestReconcileSourceBackedPageLayoutDropsSoftDeletesUndeclaredRows(t *testing.T) {
	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	batch := &sourceBackedPageLayoutPackBatch{
		declaredNonDefault: []sourceBackedPageLayoutBusinessKey{{
			ObjectAPIName: "Quote",
			LayoutName:    "Quote Layout Expansion & Renewal",
		}},
	}
	mock.ExpectQuery(`SELECT Id, ObjectApiName, LayoutName`).
		WithArgs("salesforce-crm-standard").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "LayoutName", "COALESCE\\(IsDefault, 0\\)"}).
			AddRow("leftover-layout-1", "Quote", "Old Layout", 0))
	mock.ExpectQuery(`SELECT Id, ObjectApiName, COALESCE\(ProfileId, ''\), COALESCE\(RecordTypeId, ''\), COALESCE\(RoleId, ''\), COALESCE\(RouteSource, ''\)`).
		WithArgs("leftover-layout-1").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "ProfileId", "RecordTypeId", "RoleId", "RouteSource"}))
	mock.ExpectExec(`UPDATE _System_PageLayout`).
		WithArgs("salesforce-crm-standard", "leftover-layout-1").
		WillReturnResult(sqlmock.NewResult(0, 1))

	if err := reconcileSourceBackedPageLayoutDrops(context.Background(), db, batch, "salesforce-crm-standard"); err != nil {
		t.Fatalf("reconcileSourceBackedPageLayoutDrops() unexpected error: %v", err)
	}
}

func TestVerifySourceBackedPageLayoutPackSweeperRejectsUndeclaredRows(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	mock.ExpectQuery(`SELECT Id, ObjectApiName, LayoutName`).
		WithArgs("salesforce-crm-standard").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "LayoutName", "COALESCE\\(IsDefault, 0\\)"}).
			AddRow("leftover-layout-1", "Quote", "Old Layout", 0))
	mock.ExpectQuery(`SELECT Id, ObjectApiName, COALESCE\(ProfileId, ''\), COALESCE\(RecordTypeId, ''\), COALESCE\(RoleId, ''\), COALESCE\(RouteSource, ''\)`).
		WithArgs("leftover-layout-1").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "ProfileId", "RecordTypeId", "RoleId", "RouteSource"}))

	err = verifySourceBackedPageLayoutPackSweeper(context.Background(), db, nil, "salesforce-crm-standard")
	if err == nil {
		t.Fatal("verifySourceBackedPageLayoutPackSweeper() error = nil, want undeclared leftover rejection")
	}
	if !strings.Contains(err.Error(), "undeclared non-default page_layout row") {
		t.Fatalf("error = %v, want undeclared row label", err)
	}
	if !IsSourceBackedPageLayoutRepairableDrift(err) {
		t.Fatalf("error = %v, want repairable page_layout drift classification", err)
	}
}

func TestVerifySourceBackedPageLayoutPackSweeperIgnoresCanonicalDefaultRow(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	mock.ExpectQuery(`SELECT Id, ObjectApiName, LayoutName`).
		WithArgs("salesforce-crm-standard").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "LayoutName", "COALESCE\\(IsDefault, 0\\)"}).
			AddRow("curated_Quote_default", "Quote", "Quote Layout (Curated)", 0))

	if err := verifySourceBackedPageLayoutPackSweeper(context.Background(), db, nil, "salesforce-crm-standard"); err != nil {
		t.Fatalf("verifySourceBackedPageLayoutPackSweeper() unexpected error: %v", err)
	}
}

func TestVerifySourceBackedPageLayoutPackSweeperFailsClosedWhenLayoutStillReferenced(t *testing.T) {
	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
	if err != nil {
		t.Fatalf("sqlmock: %v", err)
	}
	defer db.Close()

	mock.ExpectQuery(`SELECT Id, ObjectApiName, LayoutName`).
		WithArgs("salesforce-crm-standard").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "LayoutName", "COALESCE\\(IsDefault, 0\\)"}).
			AddRow("leftover-layout-1", "Quote", "Old Layout", 0))
	mock.ExpectQuery(`SELECT Id, ObjectApiName, COALESCE\(ProfileId, ''\), COALESCE\(RecordTypeId, ''\), COALESCE\(RoleId, ''\), COALESCE\(RouteSource, ''\)`).
		WithArgs("leftover-layout-1").
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "ProfileId", "RecordTypeId", "RoleId", "RouteSource"}).
			AddRow("assign-1", "Quote", "", "", "", "managed_seed"))

	err = verifySourceBackedPageLayoutPackSweeper(context.Background(), db, nil, "salesforce-crm-standard")
	if err == nil {
		t.Fatal("verifySourceBackedPageLayoutPackSweeper() error = nil, want referenced-layout rejection")
	}
	if IsSourceBackedPageLayoutRepairableDrift(err) {
		t.Fatalf("error = %v, want non-repairable fail-closed classification", err)
	}
	if !strings.Contains(err.Error(), "layout assignment reference") {
		t.Fatalf("error = %v, want layout assignment reference detail", err)
	}
}
