package overlay

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/standardbeagle/agnt/internal/aichannel"
	"github.com/standardbeagle/agnt/internal/proxy"
)

// AuditSummarizer uses an AI channel to generate high-quality audit reports.
type AuditSummarizer struct {
	channel *aichannel.Channel
	timeout time.Duration
}

// AuditSummarizerConfig configures the audit summarizer.
type AuditSummarizerConfig struct {
	// Agent type for AI summarization (default: uses API mode with Anthropic)
	Agent aichannel.AgentType
	// Optional custom command (overrides agent default)
	Command string
	// Optional additional args
	Args []string
	// Timeout for AI response (default 30 seconds)
	Timeout time.Duration

	// --- API Mode Configuration ---
	// UseAPI forces API mode (default: true for audit summarization)
	UseAPI bool
	// LLMProvider specifies which provider to use (auto-detected if empty)
	LLMProvider aichannel.LLMProvider
	// APIKey overrides environment variable lookup
	APIKey string
	// Model overrides the provider's default model
	Model string
}

// NewAuditSummarizer creates a new audit summarizer.
func NewAuditSummarizer(config AuditSummarizerConfig) *AuditSummarizer {
	timeout := config.Timeout
	if timeout == 0 {
		timeout = 30 * time.Second
	}

	// Default to API mode for audit summarization (faster than CLI)
	useAPI := config.UseAPI
	if !useAPI && config.Agent == "" {
		useAPI = true
	}

	channelConfig := aichannel.Config{
		Agent:        config.Agent,
		Command:      config.Command,
		Args:         config.Args,
		Timeout:      timeout,
		UseAPI:       useAPI,
		LLMProvider:  config.LLMProvider,
		APIKey:       config.APIKey,
		Model:        config.Model,
		SystemPrompt: buildAuditSystemPrompt(),
	}

	return &AuditSummarizer{
		channel: aichannel.NewWithConfig(channelConfig),
		timeout: timeout,
	}
}

// IsAvailable returns true if the AI channel is available.
func (s *AuditSummarizer) IsAvailable() bool {
	return s.channel.IsAvailable()
}

// AuditData represents the audit data to summarize.
type AuditData struct {
	AuditType string          `json:"auditType"`
	Label     string          `json:"label"`
	Summary   string          `json:"summary"`
	Result    json.RawMessage `json:"result"`
}

// SummarizeAudit generates a high-quality report from audit data.
// It also saves the full audit data to .agnt/audit/ for later reference.
func (s *AuditSummarizer) SummarizeAudit(ctx context.Context, audit AuditData, userMessage string) (string, error) {
	// Save audit data to file for later reference
	auditFilePath := ""
	if filePath, err := proxy.SaveAuditData(audit.AuditType, audit.Label, audit.Result); err == nil {
		auditFilePath = filePath
		log.Printf("Audit data saved to: %s", filePath)
		// Update summary after saving
		_ = proxy.UpdateAuditSummary()
	} else {
		log.Printf("Failed to save audit data: %v", err)
	}

	if !s.IsAvailable() {
		// Fallback: return a basic formatted summary
		report := s.fallbackSummary(audit, userMessage)
		if auditFilePath != "" {
			report += fmt.Sprintf("\n\n📁 %s", auditFilePath)
		}
		return report, nil
	}

	// Build context with audit data
	contextData := s.buildAuditContext(audit)

	// Build the prompt
	prompt := s.buildPrompt(audit.AuditType, userMessage)

	// Use timeout from config
	ctx, cancel := context.WithTimeout(ctx, s.timeout)
	defer cancel()

	response, err := s.channel.SendAndParse(ctx, prompt, contextData)
	if err != nil {
		// On error, fallback to basic summary
		report := s.fallbackSummary(audit, userMessage)
		if auditFilePath != "" {
			report += fmt.Sprintf("\n\n📁 %s", auditFilePath)
		}
		return report, nil
	}

	// Add file reference to the AI-generated report
	report := response.Result
	if auditFilePath != "" {
		report += fmt.Sprintf("\n\n📁 %s", auditFilePath)
	}

	return report, nil
}

// buildAuditSystemPrompt returns the system prompt for audit summarization.
func buildAuditSystemPrompt() string {
	return `You are an expert web accessibility and security auditor. Your role is to analyze audit results and produce clear, actionable reports for AI coding assistants.

CRITICAL RULES:
1. Be concise but thorough - the report should be 5-15 lines max
2. Prioritize by severity: critical > serious > moderate > minor
3. Focus on actionable fixes, not just problem descriptions
4. Include specific selectors/elements when available
5. Group related issues together
6. Never include raw JSON - always produce human-readable prose

OUTPUT FORMAT:
Start with a grade/severity assessment (1 line)
Then list top 3-5 issues with:
- Issue type and count
- Specific fix instructions
- Target selector if available

Example good output:
"⚠️ ACCESSIBILITY: Grade C - 3 critical issues require immediate attention

1. **Missing alt text** (4 instances) - images lack descriptions
   Fix: Add descriptive alt attributes to <img> elements
   Targets: img.hero-image, img.product-thumb

2. **Color contrast** (2 instances) - text fails WCAG AA
   Fix: Increase contrast ratio to 4.5:1 minimum
   Targets: .subtitle, .footer-text

3. **Missing form labels** (1 instance)
   Fix: Associate <label> elements with form inputs
   Target: input#email"

Keep the report focused and actionable. The AI receiving this will implement fixes.`
}

func (s *AuditSummarizer) buildAuditContext(audit AuditData) string {
	// Pretty-print the audit result for context
	var prettyResult []byte
	if len(audit.Result) > 0 {
		var parsed interface{}
		if err := json.Unmarshal(audit.Result, &parsed); err == nil {
			var marshalErr error
			prettyResult, marshalErr = json.MarshalIndent(parsed, "", "  ")
			if marshalErr != nil {
				prettyResult = audit.Result
			}
		} else {
			prettyResult = audit.Result
		}
	}

	// Limit context size to avoid token overflow
	resultStr := string(prettyResult)
	if len(resultStr) > 8000 {
		resultStr = resultStr[:8000] + "\n... (truncated)"
	}

	return fmt.Sprintf(`=== AUDIT DATA ===
Type: %s
Label: %s
Quick Summary: %s

Full Results:
%s`, audit.AuditType, audit.Label, audit.Summary, resultStr)
}

func (s *AuditSummarizer) buildPrompt(auditType, userMessage string) string {
	base := fmt.Sprintf("Analyze this %s audit and produce a clear, actionable report.", auditType)
	if userMessage != "" {
		base += fmt.Sprintf("\n\nUser's request context: %s", userMessage)
	}
	return base
}

func (s *AuditSummarizer) fallbackSummary(audit AuditData, userMessage string) string {
	// Basic fallback when LLM is not available
	text := fmt.Sprintf("**%s Audit**: %s", audit.Label, audit.Summary)
	if userMessage != "" {
		text = userMessage + "\n\n" + text
	}
	return text
}
