package services

import (
	"context"
	"sort"
	"strings"
	"wa-assistant/backend/database"
	"wa-assistant/backend/models"
)

// Called under the turn lock. A second lookup replaces the earlier value.
func (s *agentTurnState) recordBusinessFact(key, value string) {
	if s.businessBlocks == nil {
		s.businessBlocks = map[string]string{}
		s.operationalEvidence = s.businessEvidence
	}
	s.businessBlocks[key] = value
	keys := make([]string, 0, len(s.businessBlocks))
	for key := range s.businessBlocks {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	var out strings.Builder
	out.WriteString(s.operationalEvidence)
	for _, key := range keys {
		out.WriteByte('\n')
		out.WriteString(s.businessBlocks[key])
	}
	s.businessEvidence = out.String()
}

func (s *agentTurnState) freshBusinessFacts(ctx context.Context, agentID uint) string {
	sources, issue := s.freshAnswerSources(ctx, agentID, s.calculationSourceIDs)
	if issue != "" {
		return issue
	}
	for _, source := range sources {
		if source.CharCount > 12000 {
			return "source_too_long"
		}
		if source.CharCount > len([]rune(source.Answer)) {
			return "source_incomplete"
		}
	}
	for id, snapshot := range s.productFacts {
		var current models.Product
		if err := database.DB.WithContext(ctx).Select("id", "name", "price", "description", "details_json", "knowledge", "updated_at").Where("id = ? AND agent_id = ?", id, agentID).First(&current).Error; err != nil {
			return "operational_changed"
		}
		if !current.UpdatedAt.Equal(snapshot.UpdatedAt) || current.Name != snapshot.Name || current.Price != snapshot.Price || current.Description != snapshot.Description || current.DetailsJSON != snapshot.DetailsJSON || current.Knowledge != snapshot.Knowledge {
			return "operational_changed"
		}
	}
	for id, snapshot := range s.orderFacts {
		var current models.ProductOrder
		if err := database.DB.WithContext(ctx).Select("id", "order_code", "status", "updated_at").Where("id = ? AND agent_id = ? AND sender = ?", id, agentID, snapshot.Sender).First(&current).Error; err != nil {
			return "operational_changed"
		}
		if !current.UpdatedAt.Equal(snapshot.UpdatedAt) || current.Status != snapshot.Status || current.OrderCode != snapshot.OrderCode {
			return "operational_changed"
		}
	}
	return ""
}
