package discovery

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

	"github.com/ultisuite/ulti-backend/internal/llm"
)

const enrichSystemPrompt = `Tu es un assistant qui extrait des informations de contact structurées à partir de signatures d'emails.
Réponds UNIQUEMENT en JSON valide, sans markdown ni texte autour.
Privilégie les informations des signatures les plus récentes (listées en premier).
Ne devine pas : omets les champs incertains.
Format attendu:
{
  "first_name": "",
  "last_name": "",
  "company": "",
  "department": "",
  "job_title": "",
  "emails": [{"value": "", "label": "work|home|other"}],
  "phones": [{"value": "", "label": "work|mobile|home|other"}],
  "addresses": [{"street": "", "city": "", "region": "", "postal_code": "", "country": "", "label": "work|home"}],
  "website": "",
  "social_profiles": [{"value": "https://...", "label": "linkedin|twitter|facebook|instagram|github|other"}],
  "notes": ""
}`

func buildEnrichPrompt(email, displayName string, signatures []SignatureEntry) string {
	var b strings.Builder
	fmt.Fprintf(&b, "Email principal: %s\n", email)
	if displayName != "" {
		fmt.Fprintf(&b, "Nom affiché: %s\n", displayName)
	}
	b.WriteString("\nSignatures (du plus récent au plus ancien):\n")
	for i, sig := range signatures {
		text := sig.SignatureText
		if len(text) > 1500 {
			text = text[:1500]
		}
		fmt.Fprintf(&b, "\n--- Signature %d (%s) ---\n%s\n", i+1, sig.MessageDate.Format("2006-01-02"), text)
	}
	return b.String()
}

func parseEnrichedData(raw string) (*EnrichedContactData, error) {
	raw = strings.TrimSpace(raw)
	raw = strings.TrimPrefix(raw, "```json")
	raw = strings.TrimPrefix(raw, "```")
	raw = strings.TrimSuffix(raw, "```")
	raw = strings.TrimSpace(raw)

	var data EnrichedContactData
	if err := json.Unmarshal([]byte(raw), &data); err != nil {
		return nil, err
	}
	return &data, nil
}

func enrichWithLLMTimeout(ctx context.Context, client *llm.Client, settings llm.Settings, email, displayName string, signatures []SignatureEntry, timeout time.Duration) (*EnrichedContactData, error) {
	enrichCtx, cancel := context.WithTimeout(ctx, timeout)
	defer cancel()

	resultCh := make(chan struct {
		data *EnrichedContactData
		err  error
	}, 1)
	go func() {
		data, err := enrichWithLLM(enrichCtx, client, settings, email, displayName, signatures)
		resultCh <- struct {
			data *EnrichedContactData
			err  error
		}{data, err}
	}()

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case <-enrichCtx.Done():
		if err := enrichCtx.Err(); err != context.DeadlineExceeded {
			return nil, err
		}
		return nil, fmt.Errorf("llm enrichment timed out after %s", timeout)
	case res := <-resultCh:
		return res.data, res.err
	}
}

func enrichWithLLM(ctx context.Context, client *llm.Client, settings llm.Settings, email, displayName string, signatures []SignatureEntry) (*EnrichedContactData, error) {
	if client == nil || len(signatures) == 0 {
		return nil, fmt.Errorf("no signatures to enrich")
	}
	provider, model, err := llm.ResolveProvider(settings, "")
	if err != nil {
		return nil, err
	}
	prompt := buildEnrichPrompt(email, displayName, signatures)
	raw, err := client.Complete(ctx, provider, model, enrichSystemPrompt, prompt)
	if err != nil {
		return nil, err
	}
	return parseEnrichedData(raw)
}

func enrichedDataToSuggestions(userID, profileID string, data *EnrichedContactData) []Suggestion {
	if data == nil {
		return nil
	}
	var out []Suggestion

	addField := func(fieldPath, value, label, sugType string) {
		value = strings.TrimSpace(value)
		if value == "" {
			return
		}
		out = append(out, Suggestion{
			ProfileID:      profileID,
			SuggestionType: sugType,
			FieldPath:      fieldPath,
			SuggestedValue: value,
			SuggestedLabel: label,
			Confidence:     0.75,
			Status:         SuggestionPending,
		})
	}

	addField("first_name", data.FirstName, "", "new_contact")
	addField("last_name", data.LastName, "", "new_contact")
	addField("company", data.Company, "", "new_contact")
	addField("department", data.Department, "", "new_contact")
	addField("job_title", data.JobTitle, "", "new_contact")
	addField("website", data.Website, "", "new_contact")
	addField("notes", data.Notes, "", "new_contact")
	for _, sp := range data.SocialProfiles {
		addField("social_profiles", sp.Value, sp.Label, "new_contact")
	}

	for _, e := range data.Emails {
		addField("emails", e.Value, e.Label, "new_contact")
	}
	for _, p := range data.Phones {
		addField("phones", p.Value, p.Label, "new_contact")
	}
	for _, a := range data.Addresses {
		parts := []string{a.Street, a.City, a.Region, a.PostalCode, a.Country}
		var nonEmpty []string
		for _, p := range parts {
			if strings.TrimSpace(p) != "" {
				nonEmpty = append(nonEmpty, strings.TrimSpace(p))
			}
		}
		if len(nonEmpty) > 0 {
			addField("addresses", strings.Join(nonEmpty, ", "), a.Label, "new_contact")
		}
	}

	_ = userID
	return out
}
