import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import {
  AiEngineClient,
  AiEngineRequestError,
} from "../common/utils/ai-engine-client";

export interface AIPredictionResult {
  matchId: string;
  matchName: string;
  predictions: {
    betType: string;
    prediction: string;
    confidence: number;
    probabilities?: Record<string, number>;
    reasoning?: string;
    odd?: number;
    valueBet?: { isValue: boolean; edge: number };
  }[];
  recommendedBets: string[];
  homeAnalysis?: {
    teamName: string;
    formText: string;
    goalsAvg: number;
    formRating: string;
    squadStrength?: number;
  };
  awayAnalysis?: {
    teamName: string;
    formText: string;
    goalsAvg: number;
    formRating: string;
    squadStrength?: number;
  };
  expertComment: string;
  modelVersion: string;
  confidenceScore: number;
  expectedGoals?: number;
}

@Injectable()
export class AiService {
  private readonly logger = new Logger(AiService.name);
  private readonly pythonEngineUrl: string;
  private readonly aiEngineClient: AiEngineClient;

  constructor(private readonly configService: ConfigService) {
    this.pythonEngineUrl =
      this.configService.get("AI_ENGINE_URL") || "http://127.0.0.1:8000";
    this.aiEngineClient = new AiEngineClient({
      baseUrl: this.pythonEngineUrl,
      logger: this.logger,
      serviceName: AiService.name,
      timeoutMs: 30000,
      maxRetries: 2,
      retryDelayMs: 500,
    });
  }

  /**
   * Call the Python match analysis engine and map the result to stable frontend contract.
   */
  async callPythonEngine(
    matchDetails: any,
    _odds: any[],
    _lineups: { home: any[]; away: any[] },
    _substitutes: { home: any[]; away: any[] } | null,
    _stats: any,
    _eventData: any[],
  ): Promise<AIPredictionResult | null> {
    try {
      const matchId = String(matchDetails?.matchId || "").trim();
      if (!matchId) {
        this.logger.warn("Skipping AI call: missing matchId");
        return null;
      }

      this.logger.log(
        `Calling Python V28 Pro Max Engine for ${matchDetails.homeTeam} vs ${matchDetails.awayTeam}`,
      );

      const response = await this.aiEngineClient.post(
        `/v20plus/analyze/${matchId}`,
        {},
      );

      if (response.data) {
        return this.mapPythonResponse(response.data, matchDetails);
      }

      return null;
    } catch (error: unknown) {
      const message =
        error instanceof AiEngineRequestError
          ? error.message
          : error instanceof Error
            ? error.message
            : "Unknown AI engine error";
      this.logger.warn(`Python Engine error: ${message}`);
      return null;
    }
  }

  /**
   * Map Python response to our interface
   */
  private mapPythonResponse(data: any, matchDetails: any): AIPredictionResult {
    const picks = Array.isArray(data?.bet_summary) ? data.bet_summary : [];
    const recommendedBets = picks
      .filter((p: any) => p?.playable)
      .map((p: any) => `${p.market}: ${p.pick}`);

    const mappedPredictions = picks.map((p: any) => ({
      betType: String(p.market || ""),
      prediction: String(p.pick || ""),
      confidence: Number(p.calibrated_confidence ?? p.confidence ?? 0),
      probabilities: {},
      reasoning: Array.isArray(p.reasons)
        ? p.reasons.join(" | ")
        : Array.isArray(p.decision_reasons)
          ? p.decision_reasons.join(" | ")
          : "",
      odd: typeof p.odds === "number" ? p.odds : undefined,
      valueBet:
        typeof p.edge === "number"
          ? {
              isValue: p.edge > 0,
              edge: p.edge,
            }
          : undefined,
    }));

    const matchInfo = data?.match_info || {};
    const confidenceScore = Number(
      data?.main_pick?.calibrated_confidence ??
        data?.main_pick?.confidence ??
        0,
    );

    return {
      matchId: matchDetails.matchId || matchInfo.match_id || data.match_id,
      matchName: `${matchDetails.homeTeam} vs ${matchDetails.awayTeam}`,
      predictions: mappedPredictions,
      recommendedBets:
        data.recommended_bets && Array.isArray(data.recommended_bets)
          ? data.recommended_bets
          : recommendedBets,
      homeAnalysis: undefined,
      awayAnalysis: undefined,
      expertComment: data.ai_commentary || data.expert_comment || "",
      modelVersion: "v28-pro-max",
      confidenceScore:
        confidenceScore > 1 ? confidenceScore : confidenceScore * 100,
      expectedGoals: data?.score_prediction?.xg_total,
    };
  }

  /**
   * Get mapped prediction response from the AI package.
   */
  getPredictionForMatch(analysisData: any): any {
    const pyData = analysisData.liveMatchData?.pythonEnginePrediction;

    if (!pyData || !Array.isArray(pyData.bet_summary)) {
      return this.getEmptyPrediction();
    }

    const allPredictions = pyData.bet_summary.map((p: any) => ({
      betType: p.market,
      prediction: p.pick,
      confidence: p.calibrated_confidence ?? p.confidence ?? 0,
      probabilities: {},
      reasoning: Array.isArray(p.reasons) ? p.reasons.join(" | ") : "",
      odd: p.odds || 0,
      valueBet: {
        is_value: typeof p.edge === "number" ? p.edge > 0 : false,
        edge: p.edge || 0,
      },
    }));
    const firstPick = allPredictions[0];

    return {
      predictions: allPredictions,
      recommendedBets: pyData.recommended_bets || [],
      valueBets: allPredictions.filter((p: any) => p.valueBet?.is_value),
      homeAnalysis: null,
      awayAnalysis: null,
      expertComment: pyData.ai_commentary || "",
      winnerPrediction: firstPick?.prediction || "N/A",
      scorePrediction: pyData.score_prediction?.ft || "-",
      confidenceScore:
        typeof firstPick?.confidence === "number" ? firstPick.confidence : 0,
      modelVersion: "v28-pro-max",
      expectedGoals: pyData.score_prediction?.xg_total || 0,
      keyInsights: [
        `Model: v28-pro-max`,
        `Risk: ${pyData.risk?.level || "N/A"} (${pyData.risk?.score ?? 0})`,
        `Data Quality: ${pyData.data_quality?.label || "N/A"}`,
        `xG Beklentisi: ${
          typeof pyData.score_prediction?.xg_total === "number"
            ? pyData.score_prediction.xg_total.toFixed(2)
            : "N/A"
        }`,
      ],
    };
  }

  /**
   * Generate analysis strategy (replaces Gemini)
   */
  getAnalysisStrategy(matchDNA: any): { analysisTactics: any[] } {
    const tactics: any[] = [];
    const odds = matchDNA?.odds || [];

    // MS 1 oranını bul
    const ms1 = odds.find(
      (o: any) =>
        o.category?.toLowerCase().includes("maç sonucu") && o.selection === "1",
    );

    // KG Var oranını bul
    const kgVar = odds.find(
      (o: any) =>
        o.category?.toLowerCase().includes("karşılıklı gol") &&
        o.selection?.toLowerCase() === "var",
    );

    // Alt 2.5 oranını bul
    const alt25 = odds.find(
      (o: any) =>
        o.category?.toLowerCase().includes("alt/üst") &&
        o.selection?.toLowerCase() === "alt",
    );

    // Tactic 1: Benzer MS oranları
    if (ms1?.odd_value) {
      tactics.push({
        tacticName: "Benzer Maç Sonucu Oranları",
        description:
          "Ev sahibi galibiyeti için benzer oran aralığındaki maçlar",
        odds: [
          {
            categoryName: "Maç Sonucu",
            selectionName: "1",
            value: parseFloat(ms1.odd_value),
            tolerance: 0.3,
          },
        ],
      });
    }

    // Tactic 2: Benzer KG + AU oranları
    if (kgVar?.odd_value && alt25?.odd_value) {
      tactics.push({
        tacticName: "Benzer Gol Beklentisi",
        description: "Karşılıklı gol ve toplam gol benzerliği",
        odds: [
          {
            categoryName: "Karşılıklı Gol",
            selectionName: "Var",
            value: parseFloat(kgVar.odd_value),
            tolerance: 0.4,
          },
          {
            categoryName: "2,5 Alt/Üst",
            selectionName: "Alt",
            value: parseFloat(alt25.odd_value),
            tolerance: 0.3,
          },
        ],
      });
    }

    // Tactic 3: Favori analizi
    if (ms1?.odd_value && parseFloat(ms1.odd_value) < 1.8) {
      tactics.push({
        tacticName: "Favori Takım Analizi",
        description: "Benzer şekilde favori olan ev sahibi takımların maçları",
        odds: [
          {
            categoryName: "Maç Sonucu",
            selectionName: "1",
            value: parseFloat(ms1.odd_value),
            tolerance: 0.2,
          },
        ],
      });
    }

    return { analysisTactics: tactics };
  }

  /**
   * Check Python engine health
   */
  async checkHealth(): Promise<boolean> {
    try {
      const response = await this.aiEngineClient.get<{ status?: string }>(
        "/health",
        {
          timeout: 5000,
          retryCount: 0,
        },
      );
      return response.data?.status === "healthy";
    } catch {
      return false;
    }
  }

  /**
   * Get empty prediction fallback
   */
  private getEmptyPrediction() {
    return {
      predictions: [],
      recommendedBets: [],
      valueBets: [],
      homeAnalysis: null,
      awayAnalysis: null,
      expertComment: "Analiz verisi alınamadı (Python Servis Hatası).",
      winnerPrediction: "N/A",
      scorePrediction: "-",
      confidenceScore: 0,
      modelVersion: "v28-pro-max",
      expectedGoals: 0,
      keyInsights: [],
    };
  }
}
