package activeemeatenant

import (
	"context"
	"errors"
	"fmt"

	activeemeamod "github.com/tidbcloud/devops/models/activeemea"
	"github.com/tidbcloud/pkgv2/db"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type Repository interface {
	GetTenantCandidate(ctx context.Context, tenantID uint64) (*activeemeamod.TenantCandidate, error)
	UpsertTenantCandidateSnapshots(ctx context.Context, candidates []*activeemeamod.TenantCandidate) error
	UpsertTenantCandidates(ctx context.Context, candidates []*activeemeamod.TenantCandidate) error
	GetDomainEnrichment(ctx context.Context, domain string) (*activeemeamod.CompanyDomainEnrichment, error)
	UpsertDomainEnrichment(ctx context.Context, enrichment *activeemeamod.CompanyDomainEnrichment) error
}

type repository struct {
	dbProvider db.Provider
}

func NewRepository(dbProvider db.Provider) Repository {
	return &repository{dbProvider: dbProvider}
}

func (r *repository) GetTenantCandidate(ctx context.Context, tenantID uint64) (*activeemeamod.TenantCandidate, error) {
	var candidate activeemeamod.TenantCandidate
	err := r.dbProvider.ReadDB(ctx).
		Model(&activeemeamod.TenantCandidate{}).
		Where("tenant_id = ?", tenantID).
		First(&candidate).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, fmt.Errorf("get active EMEA tenant candidate %d failed: %w", tenantID, err)
	}
	return &candidate, nil
}

func (r *repository) UpsertTenantCandidateSnapshots(ctx context.Context, candidates []*activeemeamod.TenantCandidate) error {
	if len(candidates) == 0 {
		return nil
	}
	err := r.dbProvider.WriteDB(ctx).Clauses(clause.OnConflict{
		Columns: []clause.Column{{Name: "tenant_id"}},
		DoUpdates: clause.AssignmentColumns([]string{
			"tenant_name",
			"tenant_email",
			"tenant_status",
			"tenant_kind",
			"tenant_region",
			"last_candidate_at",
			"updated_at",
		}),
	}).Create(&candidates).Error
	if err != nil {
		return fmt.Errorf("upsert active EMEA tenant candidate snapshots failed: %w", err)
	}
	return nil
}

func (r *repository) UpsertTenantCandidates(ctx context.Context, candidates []*activeemeamod.TenantCandidate) error {
	if len(candidates) == 0 {
		return nil
	}
	err := r.dbProvider.WriteDB(ctx).Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "tenant_id"}},
		UpdateAll: true,
	}).Create(&candidates).Error
	if err != nil {
		return fmt.Errorf("upsert active EMEA tenant candidates failed: %w", err)
	}
	return nil
}

func (r *repository) GetDomainEnrichment(ctx context.Context, domain string) (*activeemeamod.CompanyDomainEnrichment, error) {
	var enrichment activeemeamod.CompanyDomainEnrichment
	err := r.dbProvider.ReadDB(ctx).
		Model(&activeemeamod.CompanyDomainEnrichment{}).
		Where("domain = ?", domain).
		First(&enrichment).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, fmt.Errorf("get company domain enrichment %s failed: %w", domain, err)
	}
	return &enrichment, nil
}

func (r *repository) UpsertDomainEnrichment(ctx context.Context, enrichment *activeemeamod.CompanyDomainEnrichment) error {
	if enrichment == nil {
		return fmt.Errorf("domain enrichment is nil")
	}
	err := r.dbProvider.WriteDB(ctx).Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "domain"}},
		UpdateAll: true,
	}).Create(enrichment).Error
	if err != nil {
		return fmt.Errorf("upsert company domain enrichment %s failed: %w", enrichment.Domain, err)
	}
	return nil
}
