package migration

import (
	"encoding/json"
	"strings"

	"github.com/ultisuite/ulti-backend/internal/mail/hosted"
)

func projectSelectSQL(tablePrefix string) string {
	if tablePrefix != "" && !strings.HasSuffix(tablePrefix, ".") {
		tablePrefix += "."
	}
	p := tablePrefix
	cols := []string{
		p + "id::text",
		"COALESCE(" + p + "domain_id::text, '')",
		p + "name",
		p + "source_provider",
		p + "auth_mode",
		p + "status",
		p + "cutover_at::text",
		p + "delta_mode",
		p + "shared_drive_mode",
		p + "created_at::text",
		"COALESCE(NULLIF(" + p + "microsoft_tenant_id, ''), '')",
		p + "microsoft_admin_consent_at::text",
		"COALESCE(NULLIF(" + p + "microsoft_admin_consent_error, ''), '')",
		p + "cutover_dns_json",
	}
	return strings.Join(cols, ", ")
}

type projectScanner struct {
	project       Project
	cutoverDNSRaw []byte
}

func newProjectScanner() *projectScanner {
	return &projectScanner{}
}

func (s *projectScanner) targets() []any {
	return []any{
		&s.project.ID, &s.project.DomainID, &s.project.Name, &s.project.SourceProvider,
		&s.project.AuthMode, &s.project.Status, &s.project.CutoverAt, &s.project.DeltaMode,
		&s.project.SharedDriveMode, &s.project.CreatedAt, &s.project.MicrosoftTenantID, &s.project.MicrosoftAdminConsentAt,
		&s.project.MicrosoftAdminConsentError, &s.cutoverDNSRaw,
	}
}

func (s *projectScanner) result() Project {
	applyCutoverDNS(&s.project, s.cutoverDNSRaw)
	return s.project
}

func applyCutoverDNS(p *Project, raw []byte) {
	p.CutoverDNS = nil
	raw = bytesTrimSpace(raw)
	if len(raw) == 0 || string(raw) == "{}" || string(raw) == "null" {
		return
	}
	var report hosted.DNSCheckReport
	if err := json.Unmarshal(raw, &report); err != nil {
		return
	}
	if !dnsReportHasContent(report) {
		return
	}
	p.CutoverDNS = &report
}

func dnsReportHasContent(r hosted.DNSCheckReport) bool {
	if strings.TrimSpace(r.Domain) != "" {
		return true
	}
	if len(r.Errors) > 0 || len(r.Warnings) > 0 {
		return true
	}
	if len(r.MXRecords) > 0 || len(r.TXTRecords) > 0 || len(r.ExpectedMX) > 0 {
		return true
	}
	if r.TXTVerified || r.MXVerified {
		return true
	}
	return strings.TrimSpace(r.TXTExpected) != ""
}

func bytesTrimSpace(b []byte) []byte {
	return []byte(strings.TrimSpace(string(b)))
}
