import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { GeminiService } from "../gemini/gemini.service";
import { PredictionCardDto } from "./dto/prediction-card.dto";
import axios from "axios";

const SYSTEM_PROMPT = `Sen profesyonel bir spor analisti ve sosyal medya içerik üreticisisin.
Verilen maç tahmin verisini kullanarak kısa, etkili ve ilgi çekici sosyal medya postları yazıyorsun.

KURALLAR:
- Türkçe yaz
- Maximum 250 karakter (X/Twitter uyumlu)
- Emoji kullan ama abartma (2-4 emoji yeterli)
- Skor tahminini vurgula
- Güven yüzdesini belirt
- Lig, ülke, takım adları ve ana tahminleri SEO için doğal şekilde geçir
- İlgili hashtag'leri ekle (#PremierLeague, #SüperLig vb.)
- KESİNLİKLE "kesin kazanır", "garanti" gibi ifadeler KULLANMA
- "Tahminimiz", "Beklentimiz", "Analizimiz" gibi ifadeler kullan
- Farklı maçlar için farklı tarzda yaz, tekdüze olma
- Son satıra her zaman hashtag'leri koy`;

@Injectable()
export class CaptionGeneratorService {
  private readonly logger = new Logger(CaptionGeneratorService.name);
  private readonly ollamaBaseUrl: string;
  private readonly ollamaModel: string;

  constructor(
    private readonly geminiService: GeminiService,
    private readonly configService: ConfigService,
  ) {
    this.ollamaBaseUrl =
      this.configService.get<string>("OLLAMA_BASE_URL") ||
      "http://localhost:11434";
    this.ollamaModel =
      this.configService.get<string>("OLLAMA_MODEL") ||
      this.configService.get<string>("SOCIAL_POSTER_OLLAMA_MODEL") ||
      "";
  }

  /**
   * Generate a social media caption for a match prediction using Gemini AI.
   */
  async generateCaption(card: PredictionCardDto): Promise<string> {
    if (this.ollamaModel) {
      const caption = await this.generateWithOllama(card);
      if (caption) return caption;
    }

    if (!this.geminiService.isAvailable()) {
      this.logger.warn("Gemini not available, using template caption");
      return this.generateFallbackCaption(card);
    }

    const prompt = this.buildPrompt(card);

    try {
      const { text } = await this.geminiService.generateText(prompt, {
        systemPrompt: SYSTEM_PROMPT,
        temperature: 0.8,
        maxTokens: 300,
      });

      // Ensure hashtags are present
      const caption = this.ensureHashtags(text, card);
      this.logger.log(
        `Caption generated for ${card.homeTeam} vs ${card.awayTeam}`,
      );
      return caption;
    } catch (error) {
      this.logger.error("Gemini caption generation failed", error);
      return this.generateFallbackCaption(card);
    }
  }

  private async generateWithOllama(card: PredictionCardDto): Promise<string> {
    const prompt = `${SYSTEM_PROMPT}

${this.buildPrompt(card)}`;

    try {
      const response = await axios.post(
        `${this.ollamaBaseUrl.replace(/\/$/, "")}/api/generate`,
        {
          model: this.ollamaModel,
          prompt,
          stream: false,
          options: {
            temperature: 0.7,
            num_predict: 260,
          },
        },
        { timeout: 20000 },
      );

      const text = String(response.data?.response || "").trim();
      if (!text) return "";

      this.logger.log(
        `Ollama caption generated for ${card.homeTeam} vs ${card.awayTeam}`,
      );
      return this.ensureHashtags(text, card);
    } catch (error) {
      this.logger.warn(`Ollama caption generation failed: ${error.message}`);
      return "";
    }
  }

  private buildPrompt(card: PredictionCardDto): string {
    const topPicksText = card.topPicks
      .map(
        (p, i) =>
          `${i + 1}. ${p.market} (${p.marketEn}) — ${p.pick} — Güven: %${p.confidence} — Oran: ${p.odds}`,
      )
      .join("\n");

    return `Aşağıdaki maç tahmin verisini kullanarak bir sosyal medya postu oluştur:

MAÇ: ${card.homeTeam} vs ${card.awayTeam}
SPOR: ${card.sport === "basketball" ? "Basketbol" : "Futbol"}
LİG: ${card.leagueName}
ÜLKE/BÖLGE: ${card.countryName || "-"}
TARİH: ${card.matchDate}
${card.sport === "basketball" ? "İLK DEVRE" : "İLK YARI"} SKOR TAHMİNİ: ${card.htScore}
MAÇ SONU SKOR TAHMİNİ: ${card.ftScore}
SKOR GÜVEN: %${card.scoreConfidence}
RİSK SEVİYESİ: ${card.riskLevel}

EN İYİ TAHMİNLER:
${topPicksText}

Sadece post metnini yaz, başka hiçbir şey ekleme.`;
  }

  private ensureHashtags(text: string, card: PredictionCardDto): string {
    // Always strip any LLM-emitted hashtags then append our curated SEO set,
    // so we control the canonical tags the post is indexed under.
    const stripped = text.replace(/(^|\s)#[^\s#]+/g, "").trim();
    const tags = this.buildSeoHashtags(card);
    return `${stripped}\n\n${tags}`.trim();
  }

  /**
   * Build the canonical SEO hashtag set for a prediction card.
   * Combines: league, country, teams, sport, betting keywords, day-of-week,
   * top-pick market, and evergreen brand tags. Capped at ~12 tags
   * (over-tagging gets penalised on X / IG).
   */
  private buildSeoHashtags(card: PredictionCardDto): string {
    const slug = (s: string) =>
      (s || "")
        .replace(/[^\p{L}\p{N}]/gu, "")
        .replace(/\s+/g, "");

    const tags = new Set<string>();
    const push = (t: string) => {
      if (t && t.length > 1 && t.length <= 30) tags.add(`#${t}`);
    };

    // Brand / vertical
    push("MaçTahmini");
    push("İddaa");
    push("BugünMaç");
    push(card.sport === "basketball" ? "Basketbol" : "Futbol");
    push(card.sport === "basketball" ? "BasketTahmin" : "FutbolTahmin");

    // Region / league
    if (card.countryName) push(slug(card.countryName));
    if (card.leagueName) {
      push(slug(card.leagueName));
      // Common popular shorthands
      const ln = card.leagueName.toLowerCase();
      if (ln.includes("süper")) push("SüperLig");
      if (ln.includes("premier")) push("PremierLeague");
      if (ln.includes("şampiyonlar")) push("ŞampiyonlarLigi");
      if (ln.includes("euroleague")) push("EuroLeague");
      if (ln.includes("nba")) push("NBA");
    }

    // Teams
    push(slug(card.homeTeam));
    push(slug(card.awayTeam));
    if (card.homeTeam && card.awayTeam) {
      push(slug(`${card.homeTeam}${card.awayTeam}`));
    }

    // Day of week (Turkish)
    const dayTags = ["Pazar", "Pazartesi", "Salı", "Çarşamba",
                     "Perşembe", "Cuma", "Cumartesi"];
    push(`${dayTags[new Date().getDay()]}Tahmini`);

    // Market-driven tags
    const top = card.topPicks?.[0];
    if (top) {
      const m = (top.marketEn || "").toLowerCase();
      if (m.includes("over") || m.includes("under")) push("AltÜst");
      if (m.includes("both teams")) push("KGVar");
      if (m.includes("double chance")) push("ÇifteŞans");
      if (m.includes("match result")) push("MaçSonucu");
      if (m.includes("handicap") || m.includes("spread")) push("Handikap");
    }

    return Array.from(tags).slice(0, 12).join(" ");
  }

  /**
   * Fallback caption when Gemini is not available.
   * Designed to be informative + scannable + indexable; expanded vs the
   * old one-liner so the post still ranks even without LLM enrichment.
   */
  private generateFallbackCaption(card: PredictionCardDto): string {
    const sportLabel = card.sport === "basketball" ? "Basketbol" : "Futbol";
    const halfLabel = card.sport === "basketball" ? "İlk Devre" : "İlk Yarı";
    const top = card.topPicks || [];

    const lines: string[] = [];
    const flag = card.countryName ? `🌍 ${card.countryName}` : "🌍";
    lines.push(`${flag} | ${card.leagueName}`);
    lines.push(`⚽ ${card.homeTeam} 🆚 ${card.awayTeam}`);
    lines.push(`🗓️ ${card.matchDate}`);
    lines.push("");
    lines.push(`🎯 ${sportLabel} Skor Tahmini`);
    lines.push(`  • ${halfLabel}: ${card.htScore}`);
    lines.push(`  • Maç Sonu: ${card.ftScore}`);
    lines.push(`  • Skor Güveni: %${card.scoreConfidence}`);

    if (top.length) {
      lines.push("");
      lines.push("🔥 En İyi Tahminler:");
      top.slice(0, 3).forEach((p, i) => {
        const stars = "⭐".repeat(Math.min(3, Math.max(1, Math.round(p.confidence / 30))));
        lines.push(`  ${i + 1}. ${p.market} (%${p.confidence}) ${stars}`);
      });
    }

    return lines.join("\n");
  }
}
