package packs

import (
	"testing"

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

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

	mock.ExpectQuery(`SELECT o\.ApiName, f\.ApiName`).
		WillReturnRows(sqlmock.NewRows([]string{"ApiName", "ApiName"}).AddRow("Event", "Name"))
	mock.ExpectQuery(`SELECT Id, ObjectApiName, Config, COALESCE\(Source,''\), COALESCE\(IsCustomized,0\) FROM _System_PageLayout WHERE IsDeleted = 0 OR IsDeleted IS NULL`).
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "Config", "Source", "IsCustomized"}).AddRow(
			"curated_Lead_default",
			"Lead",
			`{"id":"curated_Lead_default","objectApiName":"Lead","layoutName":"Lead Layout","relatedLists":[{"id":"Event-WhoId","label":"Events","objectApiName":"Event","lookupField":"WhoId","secondaryLabel":"via Name ID"}]}`,
			"curated",
			0,
		))

	if err := BackfillLayoutRelatedLists(db); err != nil {
		t.Fatalf("BackfillLayoutRelatedLists: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}

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

	mock.ExpectQuery(`SELECT o\.ApiName, f\.ApiName`).
		WillReturnRows(sqlmock.NewRows([]string{"ApiName", "ApiName"}).AddRow("Event", "Name"))
	mock.ExpectQuery(`SELECT Id, ObjectApiName, Config, COALESCE\(Source,''\), COALESCE\(IsCustomized,0\) FROM _System_PageLayout WHERE IsDeleted = 0 OR IsDeleted IS NULL`).
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "Config", "Source", "IsCustomized"}).AddRow(
			"auto_lead_default",
			"Lead",
			`{"id":"auto_lead_default","objectApiName":"Lead","layoutName":"Lead Layout","relatedLists":[{"id":"Event-WhoId","label":"Old Events","objectApiName":"Event","lookupField":"WhoId","secondaryLabel":"old"}]}`,
			"auto_generated",
			0,
		))
	mock.ExpectQuery(`SELECT\s+f\.ApiName,\s+f\.Label,\s+o\.ApiName,\s+o\.PluralLabel,\s+rel\.RelatedListLabel,\s+rel\.RelatedListFields`).
		WillReturnRows(sqlmock.NewRows([]string{
			"LookupFieldAPI", "LookupFieldLabel", "ChildObjectAPI", "ChildPluralLabel", "RelatedListLabel", "RelatedListFields",
		}).AddRow("WhoId", "Name", "Event", "Events", nil, nil))
	mock.ExpectExec(`UPDATE _System_PageLayout SET Config = \?, LastModifiedDate = CURRENT_TIMESTAMP WHERE Id = \?`).
		WithArgs(sqlmock.AnyArg(), "auto_lead_default").
		WillReturnResult(sqlmock.NewResult(0, 1))

	if err := BackfillLayoutRelatedLists(db); err != nil {
		t.Fatalf("BackfillLayoutRelatedLists: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}

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

	mock.ExpectQuery(`SELECT o\.ApiName, f\.ApiName`).
		WillReturnRows(sqlmock.NewRows([]string{"ApiName", "ApiName"}).AddRow("AccountPartner", "Name"))
	mock.ExpectQuery(`SELECT Id, ObjectApiName, Config, COALESCE\(Source,''\), COALESCE\(IsCustomized,0\) FROM _System_PageLayout WHERE IsDeleted = 0 OR IsDeleted IS NULL`).
		WillReturnRows(sqlmock.NewRows([]string{"Id", "ObjectApiName", "Config", "Source", "IsCustomized"}).AddRow(
			"auto_account_default",
			"Account",
			`{"id":"auto_account_default","objectApiName":"Account","layoutName":"Account Layout","relatedLists":[{"id":"AccountPartner-AccountFromId","label":"Account Partners","objectApiName":"AccountPartner","lookupField":"AccountFromId","secondaryLabel":"via Account"}]}`,
			"auto_generated",
			0,
		))
	mock.ExpectQuery(`SELECT\s+f\.ApiName,\s+f\.Label,\s+o\.ApiName,\s+o\.PluralLabel,\s+rel\.RelatedListLabel,\s+rel\.RelatedListFields`).
		WillReturnRows(sqlmock.NewRows([]string{
			"LookupFieldAPI", "LookupFieldLabel", "ChildObjectAPI", "ChildPluralLabel", "RelatedListLabel", "RelatedListFields",
		}).AddRow("AccountFromId", "Account", "AccountPartner", "Account Partners", nil, nil))

	if err := BackfillLayoutRelatedLists(db); err != nil {
		t.Fatalf("BackfillLayoutRelatedLists: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("sql expectations: %v", err)
	}
}
