package repo

import (
	"context"

	ubent "github.com/tidbcloud/devops/entity/userbehavior"
	ubmod "github.com/tidbcloud/devops/models/userbehavior"
	"github.com/tidbcloud/pkgv2/db"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func setupGTMLeadTestDB() Repository {
	gormDB, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	Expect(err).ToNot(HaveOccurred())

	err = gormDB.AutoMigrate(&ubmod.GTMLead{})
	Expect(err).ToNot(HaveOccurred())

	provider := db.NewProvider(gormDB)
	return New(provider)
}

var _ = Describe("GTMLeadDriver", func() {
	var (
		repository Repository
		driver     GTMLeadDriver
	)

	BeforeEach(func() {
		repository = setupGTMLeadTestDB()
		driver = repository.GTMLeadDriver()
	})

	It("creates a GTM lead", func() {
		companyName := "Test Company"
		contactFirstName := "Test"
		lead := &ubent.GTMLead{
			TenantID:         100,
			Email:            "test@example.com",
			EmailDomain:      "example.com",
			ContactFirstName: &contactFirstName,
			CompanyName:      &companyName,
			IsQualified:      true,
			RawEnrichment:    `{"test":"data"}`,
		}

		created, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())
		Expect(created).ToNot(BeNil())
		Expect(created.ID).ToNot(BeZero())
		Expect(created.TenantID).To(Equal(uint64(100)))
		Expect(created.ContactFirstName).ToNot(BeNil())
		Expect(*created.ContactFirstName).To(Equal("Test"))
	})

	It("gets a GTM lead by tenant ID", func() {
		companyName := "Test Company"
		lead := &ubent.GTMLead{
			TenantID:      100,
			Email:         "test@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   true,
			RawEnrichment: `{"test":"data"}`,
		}
		_, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())

		found, err := driver.GetByTenantID(context.Background(), 100)
		Expect(err).ToNot(HaveOccurred())
		Expect(found).ToNot(BeNil())
		Expect(found.TenantID).To(Equal(uint64(100)))
	})

	It("gets a GTM lead by email", func() {
		companyName := "Test Company"
		lead := &ubent.GTMLead{
			TenantID:      100,
			Email:         "test@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   true,
			RawEnrichment: `{"test":"data"}`,
		}
		_, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())

		found, err := driver.GetByEmail(context.Background(), "test@example.com")
		Expect(err).ToNot(HaveOccurred())
		Expect(found).ToNot(BeNil())
		Expect(found.Email).To(Equal("test@example.com"))
	})

	It("updates a GTM lead", func() {
		companyName := "Test Company"
		lead := &ubent.GTMLead{
			TenantID:      100,
			Email:         "test@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   false,
			RawEnrichment: `{"test":"data"}`,
		}
		created, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())

		created.IsQualified = true
		updated, err := driver.Update(context.Background(), created)
		Expect(err).ToNot(HaveOccurred())
		Expect(updated).ToNot(BeNil())
		Expect(updated.IsQualified).To(BeTrue())
	})

	It("lists only qualified leads", func() {
		companyName := "Test Company"
		lead1 := &ubent.GTMLead{
			TenantID:      100,
			Email:         "test1@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   true,
			RawEnrichment: `{"test":"data"}`,
		}
		lead2 := &ubent.GTMLead{
			TenantID:      101,
			Email:         "test2@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   false,
			RawEnrichment: `{"test":"data"}`,
		}
		_, err := driver.Create(context.Background(), lead1)
		Expect(err).ToNot(HaveOccurred())
		_, err = driver.Create(context.Background(), lead2)
		Expect(err).ToNot(HaveOccurred())

		qualified, err := driver.ListQualified(context.Background(), 10)
		Expect(err).ToNot(HaveOccurred())
		Expect(qualified).To(HaveLen(1))
		Expect(qualified[0].IsQualified).To(BeTrue())
	})

	It("updates lead qualification", func() {
		companyName := "Test Company"
		lead := &ubent.GTMLead{
			TenantID:      100,
			Email:         "test@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   false,
			RawEnrichment: `{"test":"data"}`,
		}
		created, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())

		err = driver.UpdateLeadQualification(context.Background(), created.ID, true, "meets criteria")
		Expect(err).ToNot(HaveOccurred())

		updated, err := driver.GetByID(context.Background(), created.ID)
		Expect(err).ToNot(HaveOccurred())
		Expect(updated.IsQualified).To(BeTrue())
		Expect(updated.QualificationReason).ToNot(BeNil())
		Expect(*updated.QualificationReason).To(Equal("meets criteria"))
	})

	It("updates lead use-case match", func() {
		companyName := "Test Company"
		lead := &ubent.GTMLead{
			TenantID:      100,
			Email:         "test@example.com",
			EmailDomain:   "example.com",
			CompanyName:   &companyName,
			IsQualified:   true,
			RawEnrichment: `{"test":"data"}`,
		}
		created, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())

		err = driver.UpdateLeadUseCaseMatch(context.Background(), created.ID, "ai_chatbot", "matches profile")
		Expect(err).ToNot(HaveOccurred())

		updated, err := driver.GetByID(context.Background(), created.ID)
		Expect(err).ToNot(HaveOccurred())
		Expect(updated.MatchedUseCase).ToNot(BeNil())
		Expect(*updated.MatchedUseCase).To(Equal("ai_chatbot"))
		Expect(updated.UseCaseMatchReason).ToNot(BeNil())
		Expect(*updated.UseCaseMatchReason).To(Equal("matches profile"))
	})

	It("persists contact first name across create and reload", func() {
		contactName := "Alex Wang"
		contactFirstName := "Alex"
		companyName := "Test Company"
		lead := &ubent.GTMLead{
			TenantID:         100,
			Email:            "test@example.com",
			EmailDomain:      "example.com",
			ContactName:      &contactName,
			ContactFirstName: &contactFirstName,
			CompanyName:      &companyName,
			IsQualified:      true,
			RawEnrichment:    `{"test":"data"}`,
		}

		created, err := driver.Create(context.Background(), lead)
		Expect(err).ToNot(HaveOccurred())
		Expect(created.ContactFirstName).ToNot(BeNil())
		Expect(*created.ContactFirstName).To(Equal("Alex"))

		found, err := driver.GetByID(context.Background(), created.ID)
		Expect(err).ToNot(HaveOccurred())
		Expect(found).ToNot(BeNil())
		Expect(found.ContactFirstName).ToNot(BeNil())
		Expect(*found.ContactFirstName).To(Equal("Alex"))
	})
})
