package worker

import (
	"context"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/zs/InsightReply/internal/model"
	"github.com/zs/InsightReply/internal/repository"
	"github.com/zs/InsightReply/internal/scraper"
	"github.com/zs/InsightReply/internal/service"
)

type PerformanceWorker struct {
	repo       *repository.ReplyRepository
	client     *scraper.ScraperClient
	aiSvc      *service.AIService
	baseUrl    string
}

func NewPerformanceWorker(repo *repository.ReplyRepository, aiSvc *service.AIService) *PerformanceWorker {
	return &PerformanceWorker{
		repo:       repo,
		client:     scraper.NewScraperClient(),
		aiSvc:      aiSvc,
		baseUrl:    "https://x.beenglish.eu.org",
	}
}

// Start begins the 24h retroactive performance checking loop
func (w *PerformanceWorker) Start(ctx context.Context, interval time.Duration) {
	log.Printf("[PerformanceWorker] Starting retroactive engagement tracking every %v", interval)
	
	ticker := time.NewTicker(interval)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			log.Println("[PerformanceWorker] Stopping background performance loop")
			return
		case <-ticker.C:
			w.runCycle(ctx)
		}
	}
}

func (w *PerformanceWorker) runCycle(ctx context.Context) {
	pending, err := w.repo.GetPendingPerformanceChecks()
	if err != nil {
		log.Printf("[PerformanceWorker] Error fetching pending checks: %v", err)
		return
	}

	for _, reply := range pending {
		// Stop processing if context cancelled
		select {
		case <-ctx.Done():
			return
		default:
		}

		xTweetID, err := w.repo.GetTweetXTweetID(reply.TweetID)
		if err != nil {
			continue 
		}

		// Scrape the specific thread
		// Nitter handles /i/status/12345 generic routes
		url := fmt.Sprintf("%s/i/status/%s", w.baseUrl, xTweetID)
		log.Printf("[PerformanceWorker] Checking thread %s for user's AI reply performance", url)

		htmlData, err := w.client.Fetch(url)
		if err != nil {
			w.client.JitterDelay(2000, 5000)
			continue
		}

		threadReplies, err := scraper.ParseTimeline(htmlData)
		if err != nil {
			continue
		}

		// Search for the user's generated text within the thread replies
		found := false
		for _, threadReply := range threadReplies {
			// Basic similarity check: if 50% of the AI sentence is present
			// Real implementation might use Levenshtein distance, but strings.Contains on chunks works for MVP
			snippet := reply.Content
			if len(snippet) > 20 {
				snippet = snippet[:20] 
			}

			if strings.Contains(threadReply.Content, snippet) {
				found = true
				
				// WE FOUND OUR REPLY! Record its metrics
				perf := &model.ReplyPerformance{
					ReplyID:            reply.ID,
					UserID:             reply.UserID,
					LikeCountIncrease:  threadReply.Likes,
					ReplyCountIncrease: threadReply.Replies,
					CheckTime:          time.Now(),
				}
				
				w.repo.SaveReplyPerformance(perf)
				log.Printf("[PerformanceWorker] 🎯 Verified AI reply in wild! Likes: %d, Replies: %d", perf.LikeCountIncrease, perf.ReplyCountIncrease)
				
				// Epic 13 AI Tone Engine: Autonomous Style Cloning for proven viral comments
				if perf.LikeCountIncrease >= 10 {
					log.Printf("[PerformanceWorker] Reply went viral! Asking AI to reverse-engineer linguistic styling.")
					
					styleProfile, err := w.aiSvc.ExtractStyle(ctx, reply.Content)
					if err == nil && styleProfile != "" {
						err = w.repo.SaveStyleExtraction(reply.UserID, styleProfile)
						if err != nil {
							log.Printf("[PerformanceWorker] Error saving style database mapping: %v", err)
						} else {
							log.Printf("[PerformanceWorker] Successfully built user style clone: %s", styleProfile)
						}
					}
				}
				
				break
			}
		}

		// Even if not found (maybe they edited heavily or didn't actually post it), we mark it as checked to prevent infinite re-checking
		if !found {
			perf := &model.ReplyPerformance{
				ReplyID:            reply.ID,
				UserID:             reply.UserID,
				CheckTime:          time.Now(),
			}
			w.repo.SaveReplyPerformance(perf)
		}

		w.client.JitterDelay(3000, 8000)
	}
}
