package files

import (
	"context"
	"database/sql"
	"os"
	"regexp"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/require"
)

// TestMain installs the tenant-shaped href field registration that the
// behavior tests below assume. The L0 package no longer ships these
// pairs — the tenant-quarantine package registers them at runtime via
// its init() — so tests must register an equivalent set to exercise
// rewrite behavior. Keeps this _test.go self-contained without
// importing the tenant package (which would create an
// l0-feature → tenant-quarantine cycle).
func TestMain(m *testing.M) {
	ResetHrefFieldsForTest()
	RegisterHrefFields(
		HrefRewriteField{ParentApiName: "Contract", FieldApiName: "Archived_Contract__c"},
		HrefRewriteField{ParentApiName: "Contract", FieldApiName: "NonstandardUploadUrl__c"},
		HrefRewriteField{ParentApiName: "Contract", FieldApiName: "StandardUploadUrl__c"},
		HrefRewriteField{ParentApiName: "Order", FieldApiName: "Archived_Order_Form__c"},
		HrefRewriteField{ParentApiName: "Order", FieldApiName: "NonStandardUploadUrl__c"},
		HrefRewriteField{ParentApiName: "Order", FieldApiName: "StandardUploadUrl__c"},
	)
	os.Exit(m.Run())
}

func TestExtractDistributionIDBody(t *testing.T) {
	cases := []struct {
		name     string
		href     string
		wantBody string
		wantOK   bool
	}{
		{
			name:     "canonical SF share URL",
			href:     "https://pingcap.my.salesforce.com/sfc/p/5g000002G54u/a/5g000000fzhX/epjVA1yYwJhz0WLxCYury8JKJWcWBntFGDm1bXfuWrE",
			wantBody: "5g000000fzhX",
			wantOK:   true,
		},
		{
			name:   "missing /a/ segment",
			href:   "https://pingcap.my.salesforce.com/foo/bar/baz",
			wantOK: false,
		},
		{
			name:   "body shorter than 12 chars",
			href:   "https://pingcap.my.salesforce.com/sfc/p/x/a/short/secret",
			wantOK: false,
		},
		{
			name:   "body longer than 12 chars",
			href:   "https://pingcap.my.salesforce.com/sfc/p/x/a/thirteen_chrs/secret",
			wantOK: false,
		},
		{
			name:   "body has no trailing separator",
			href:   "https://pingcap.my.salesforce.com/sfc/p/x/a/5g000000fzhX",
			wantOK: false,
		},
		{
			name:     "newer pod prefix",
			href:     "https://pingcap.my.salesforce.com/sfc/p/x/a/BV0000000TNJ/secret",
			wantBody: "BV0000000TNJ",
			wantOK:   true,
		},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			body, ok := extractDistributionIDBody(tc.href)
			require.Equal(t, tc.wantOK, ok)
			if tc.wantOK {
				require.Equal(t, tc.wantBody, body)
			}
		})
	}
}

// TestRewriteRecord_EmptyRegistryIsNoop verifies greenfield behavior:
// an org that has not registered any href fields (i.e. the tenant
// overlay is not applied) sees the resolver as a pure no-op even
// when called with a value that would otherwise match the rewrite
// pattern. Exercises the L0-without-tenant-overlay path.
func TestRewriteRecord_EmptyRegistryIsNoop(t *testing.T) {
	// Temporarily clear the registry this test file installed in
	// TestMain, then restore it so later tests still pass.
	saved := snapshotHrefFields()
	ResetHrefFieldsForTest()
	defer func() {
		ResetHrefFieldsForTest()
		RegisterHrefFields(saved...)
	}()

	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	r := NewHrefFieldResolver(db)
	original := `<a href="https://pingcap.my.salesforce.com/sfc/p/x/a/5g000000fzhX/k">x</a>`
	rec := models.SObject{"Archived_Contract__c": original}
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", "800XYZ", rec))
	require.Equal(t, original, rec["Archived_Contract__c"])
	require.Empty(t, FieldsToRewriteForObject("Contract"))
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestRewriteRecord_NilResolverIsNoop(t *testing.T) {
	var r *HrefFieldResolver
	rec := models.SObject{"Archived_Contract__c": "untouched"}
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", "8005g000000swN1AAI", rec))
	require.Equal(t, "untouched", rec["Archived_Contract__c"])
}

func TestRewriteRecord_SkipsNonMatchingObject(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	r := NewHrefFieldResolver(db)
	rec := models.SObject{
		"Archived_Contract__c": "<a href=\"https://pingcap.my.salesforce.com/sfc/p/x/a/5g000000fzhX/k\">label</a>",
	}
	// Account is not registered, so no SQL must execute.
	require.NoError(t, r.RewriteRecord(context.Background(), "Account", "001ABC", rec))
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestRewriteRecord_RewritesResolvedHref(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	const parentID = "8005g000000swN1AAI"
	const distBody = "5g000000fzhX"
	const sysFileID = "sysfilecompat_a265d4bc58073d8ea5e619737269c8b6"

	// Archived_Contract__c is the first registered Contract field; subsequent
	// Contract fields (NonstandardUploadUrl__c) are absent from the record so
	// they trigger no query. Order fields are skipped because object != Order.
	mock.ExpectQuery(regexp.QuoteMeta(
		"SELECT sf.`Id`, sf.`Name` FROM `_System_File` sf " +
			"JOIN `ContentDistribution` cd " +
			"  ON cd.`ContentVersionId` = sf.`SourceContentVersionId` " +
			" AND cd.`IsDeleted` = 0 " +
			"WHERE SUBSTRING(cd.`Id`, 4, 12) = ? " +
			"  AND sf.`ParentId` = ? " +
			"  AND (sf.`Status` IS NULL OR sf.`Status` = 'Active') " +
			"ORDER BY sf.`CreatedDate` DESC " +
			"LIMIT 1")).
		WithArgs(distBody, parentID).
		WillReturnRows(sqlmock.NewRows([]string{"Id", "Name"}).AddRow(sysFileID, "IN-NDA-71521327_Flipkart_Signed.pdf"))

	r := NewHrefFieldResolver(db)
	rec := models.SObject{
		"Archived_Contract__c": `<a href="https://pingcap.my.salesforce.com/sfc/p/5g000002G54u/a/5g000000fzhX/epjVA1yYwJhz0WLxCYury8JKJWcWBntFGDm1bXfuWrE" target="_blank">JP-NDA-23662607</a>`,
	}
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", parentID, rec))
	require.Equal(t,
		`<a href="/services/data/v63.0/files/sysfilecompat_a265d4bc58073d8ea5e619737269c8b6/download" target="_blank">JP-NDA-23662607</a>`,
		rec["Archived_Contract__c"])
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestRewriteRecord_LeavesUnresolvedHrefAlone(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	const parentID = "800BV0000000Zt4YAE"
	const distBody = "BV0000000TNJ"

	mock.ExpectQuery(regexp.QuoteMeta(
		"SELECT sf.`Id`, sf.`Name` FROM `_System_File` sf")).
		WithArgs(distBody, parentID).
		WillReturnError(sql.ErrNoRows)

	r := NewHrefFieldResolver(db)
	original := `<a href="https://pingcap.my.salesforce.com/sfc/p/x/a/BV0000000TNJ/secret" target="_blank">TH-MA-80707251</a>`
	rec := models.SObject{"Archived_Contract__c": original}
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", parentID, rec))
	require.Equal(t, original, rec["Archived_Contract__c"], "value must be untouched when no _System_File matches")
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestRewriteRecord_LeavesAlreadyLocalHrefAlone(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	r := NewHrefFieldResolver(db)
	already := `<a href="/services/data/v63.0/files/sysfilecompat_xxx/download" target="_blank">label</a>`
	rec := models.SObject{"Archived_Contract__c": already}
	// No SQL should execute because the prefix-check skips the lookup.
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", "800XYZ", rec))
	require.Equal(t, already, rec["Archived_Contract__c"])
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestRewriteRecord_RewritesBareURLAndWrapsWithFileName(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	const parentID = "8005g000000sws0AAA"
	const distBody = "5g000000fzhX"
	const sysFileID = "sysfilecompat_863dfecd3825ae545b480c9ac4137020"

	mock.ExpectQuery(regexp.QuoteMeta(
		"SELECT sf.`Id`, sf.`Name` FROM `_System_File` sf")).
		WithArgs(distBody, parentID).
		WillReturnRows(sqlmock.NewRows([]string{"Id", "Name"}).AddRow(sysFileID, "IN-NDA-71521327_Flipkart_Signed.pdf"))

	r := NewHrefFieldResolver(db)
	rec := models.SObject{
		// StandardUploadUrl__c stores a bare URL (no anchor wrapper).
		"StandardUploadUrl__c": `https://pingcap.my.salesforce.com/sfc/p/5g000002G54u/a/5g000000fzhX/epjVA1yYwJhz0WLxCYury8JKJWcWBntFGDm1bXfuWrE`,
	}
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", parentID, rec))
	require.Equal(t,
		`<a href="/services/data/v63.0/files/sysfilecompat_863dfecd3825ae545b480c9ac4137020/download" target="_blank">IN-NDA-71521327_Flipkart_Signed.pdf</a>`,
		rec["StandardUploadUrl__c"],
		"bare URL must be wrapped in an anchor with the file name as label")
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestRewriteRecord_SkipsEmptyAndNonStringValues(t *testing.T) {
	db, mock, err := sqlmock.New()
	require.NoError(t, err)
	defer db.Close()

	r := NewHrefFieldResolver(db)
	rec := models.SObject{
		"Archived_Contract__c":     "",
		"NonstandardUploadUrl__c":  nil,
	}
	require.NoError(t, r.RewriteRecord(context.Background(), "Contract", "800XYZ", rec))
	require.NoError(t, mock.ExpectationsWereMet())
}
