package usecase

import (
	"context"
	"fmt"
	"strings"

	"apps/backend/internal/module/radar/domain"
	usageDomain "apps/backend/internal/module/usage/domain"
)

func (s *Service) ListReplies(ctx context.Context, ownerUID int64, opportunityID string) ([]*domain.ReplyVariant, error) {
	if _, err := s.GetOpportunity(ctx, ownerUID, opportunityID); err != nil {
		return nil, err
	}
	return s.Repo.ListReplies(ctx, ownerUID, opportunityID)
}

/*
GenerateReply creates one reply variant with forbidden-word filter.
DM variants are copy-only: never claim auto-send (spec 送出閘).
*/
func (s *Service) GenerateReply(ctx context.Context, ownerUID int64, opportunityID, variant string) (_ *domain.ReplyVariant, err error) {
	if !domain.IsReplyVariant(variant) {
		return nil, fmt.Errorf("%w: unknown variant %q", domain.ErrValidation, variant)
	}
	o, err := s.GetOpportunity(ctx, ownerUID, opportunityID)
	if err != nil {
		return nil, err
	}
	profile, _ := s.Repo.GetServiceProfile(ctx, ownerUID)

	charge, err := s.bill(ctx, ownerUID, usageDomain.MeterAICopy, "雷達回覆生成", "radar.reply")
	if err != nil {
		return nil, err
	}
	defer charge.Settle(ctx, &err)

	text, err := s.completeAI(ctx, ownerUID, replyPrompt(profile, o, variant))
	if err != nil {
		// heuristic fallback
		text = heuristicReply(profile, o, variant)
	}
	text = strings.TrimSpace(text)
	if profile != nil {
		text = filterForbidden(text, profile.Forbidden)
	}
	if text == "" {
		return nil, fmt.Errorf("%w: empty reply after forbidden filter", domain.ErrValidation)
	}

	r := &domain.ReplyVariant{
		ID:            domain.NewID(),
		OwnerUID:      ownerUID,
		OpportunityID: opportunityID,
		Variant:       variant,
		Text:          text,
		CreatedAt:     domain.NowNano(),
	}
	if err := r.Normalize(); err != nil {
		return nil, err
	}
	if err := s.Repo.SaveReply(ctx, r); err != nil {
		return nil, err
	}
	return r, nil
}

func replyPrompt(profile *domain.ServiceProfile, o *domain.Opportunity, variant string) string {
	var b strings.Builder
	b.WriteString("為以下商機寫一則繁中台灣語氣的回覆草稿，只輸出正文。\n")
	b.WriteString("版本：" + variant + "\n")
	if variant == domain.ReplyDM {
		b.WriteString("這是私訊草稿，使用者會手動複製送出，不要寫「已自動送出」。\n")
	}
	if profile != nil {
		if len(profile.Forbidden) > 0 {
			b.WriteString("禁止使用：" + strings.Join(profile.Forbidden, "、") + "\n")
		}
		if profile.ToneNote != "" {
			b.WriteString("語氣：" + profile.ToneNote + "\n")
		}
	}
	b.WriteString("貼文：\n" + o.Text + "\n")
	return b.String()
}

func heuristicReply(profile *domain.ServiceProfile, o *domain.Opportunity, variant string) string {
	svc := "我們的服務"
	if profile != nil && len(profile.Services) > 0 {
		svc = profile.Services[0].Name
	}
	switch variant {
	case domain.ReplyNoSales:
		return "看到你的需求了，先分享一點實務上常見的做法給你參考，有問題再問我。"
	case domain.ReplyProfessional:
		return fmt.Sprintf("您好，關於「%s」，我這邊有%s的經驗，若方便可再補充你的時間與預算範圍。", trimRunes(o.Text, 40), svc)
	case domain.ReplyHumorous:
		return "懂你的痛苦！這題我遇過幾次，願意的話我可以幫你釐清怎麼選比較不踩雷。"
	case domain.ReplyDM:
		return fmt.Sprintf("你好，我做%s，看到你的貼文想私訊給你更完整的說明（請手動貼上傳送）。", svc)
	default:
		return fmt.Sprintf("嗨，看到你在找相關協助。我這邊有%s可以幫忙，若還在比較歡迎問我細節。", svc)
	}
}

func filterForbidden(text string, forbidden []string) string {
	out := text
	for _, f := range forbidden {
		f = strings.TrimSpace(f)
		if f == "" {
			continue
		}
		out = strings.ReplaceAll(out, f, "…")
	}
	return out
}

func trimRunes(s string, n int) string {
	r := []rune(s)
	if len(r) <= n {
		return s
	}
	return string(r[:n]) + "…"
}
