import { Injectable, Logger } from "@nestjs/common";
import { PrismaService } from "../../../database/prisma.service";
import { User, UserCoupon, Match } from "@prisma/client";

export class CreateCouponDto {
  strategy: string; // 'SAFE', 'VALUE', 'CUSTOM'
  items: {
    matchId: string;
    selection: string; // 'MS 1', '2.5 UST'
    odd: number;
  }[];
  isPublic?: boolean;
}

export interface UserStatsDto {
  totalCoupons: number;
  wonCoupons: number;
  winRate: number; // Percentage
  totalInvested: number; // Unit based (1 unit per coupon)
  totalReturn: number;
  roi: number; // Return on Investment %
}

@Injectable()
export class UserCouponService {
  private readonly logger = new Logger(UserCouponService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * Kullanıcı için yeni bir kupon oluşturur ve kaydeder.
   */
  async createCoupon(user: User, dto: CreateCouponDto): Promise<UserCoupon> {
    const totalOdds = dto.items.reduce((acc, item) => acc * item.odd, 1);

    const coupon = await this.prisma.userCoupon.create({
      data: {
        userId: user.id,
        strategy: dto.strategy,
        totalOdds: parseFloat(totalOdds.toFixed(2)),
        isPublic: dto.isPublic || false,
        status: "PENDING",
        couponItems: {
          create: dto.items.map((item) => ({
            matchId: item.matchId,
            selection: item.selection,
            oddAtTime: item.odd,
          })),
        },
      },
      include: {
        couponItems: true,
      },
    });

    this.logger.log(
      `Coupon created for user ${user.email} with odds ${totalOdds}`,
    );
    return coupon;
  }

  /**
   * Bekleyen kuponların sonuçlarını kontrol eder ve günceller.
   * Bu metod bir Cron Job tarafından periyodik olarak çağrılmalıdır.
   */
  async updatePendingCoupons(): Promise<void> {
    // Sadece bitmiş (FT) maçları içeren PENDING kuponları çek
    const pendingCoupons = await this.prisma.userCoupon.findMany({
      where: { status: "PENDING" },
      include: {
        couponItems: {
          include: { match: true },
        },
      },
    });

    for (const coupon of pendingCoupons) {
      let isCouponWon = true;
      let isCouponLost = false;
      let allMatchesFinished = true;

      for (const item of coupon.couponItems) {
        if (item.match.status !== "FT") {
          allMatchesFinished = false;
          break; // Henüz bitmemiş maç var, kuponu güncelleme
        }

        const isItemWon = this.checkSelection(item.selection, item.match);

        // Sonucu item bazında güncelle
        if (item.isCorrect !== isItemWon) {
          await this.prisma.userCouponItem.update({
            where: { id: item.id },
            data: { isCorrect: isItemWon },
          });
        }

        if (!isItemWon) {
          isCouponLost = true;
          isCouponWon = false;
        }
      }

      if (isCouponLost) {
        await this.prisma.userCoupon.update({
          where: { id: coupon.id },
          data: { status: "LOST" },
        });
      } else if (allMatchesFinished && isCouponWon) {
        await this.prisma.userCoupon.update({
          where: { id: coupon.id },
          data: { status: "WON" },
        });
      }
    }
  }

  /**
   * Basit bir kural seti ile bahsin tutup tutmadığını kontrol eder.
   * Gerçek dünyada bu daha karmaşık bir 'BetSettlementService' olmalıdır.
   */
  private checkSelection(selection: string, match: Match): boolean {
    const home = match.scoreHome ?? 0;
    const away = match.scoreAway ?? 0;
    const total = home + away;

    switch (selection) {
      case "MS 1":
        return home > away;
      case "MS X":
        return home === away;
      case "MS 2":
        return away > home;
      case "1.5 UST":
        return total > 1.5;
      case "2.5 UST":
        return total > 2.5;
      case "3.5 UST":
        return total > 3.5;
      case "2.5 ALT":
        return total < 2.5;
      case "KG VAR":
        return home > 0 && away > 0;
      case "KG YOK":
        return home === 0 || away === 0;
      default:
        return false; // Bilinmeyen market
    }
  }

  /**
   * Kullanıcının bahis performans istatistiklerini getirir.
   */
  async getUserStatistics(userId: string): Promise<UserStatsDto> {
    const coupons = await this.prisma.userCoupon.findMany({
      where: {
        userId,
        status: { in: ["WON", "LOST"] },
      },
    });

    const totalCoupons = coupons.length;
    if (totalCoupons === 0) {
      return {
        totalCoupons: 0,
        wonCoupons: 0,
        winRate: 0,
        totalInvested: 0,
        totalReturn: 0,
        roi: 0,
      };
    }

    const wonCoupons = coupons.filter((c) => c.status === "WON");
    const totalInvested = totalCoupons; // Her kupona 1 birim yatırıldığını varsayıyoruz
    const totalReturn = wonCoupons.reduce((acc, c) => acc + c.totalOdds, 0);
    const winRate = (wonCoupons.length / totalCoupons) * 100;
    const roi = ((totalReturn - totalInvested) / totalInvested) * 100;

    return {
      totalCoupons,
      wonCoupons: wonCoupons.length,
      winRate: parseFloat(winRate.toFixed(2)),
      totalInvested,
      totalReturn: parseFloat(totalReturn.toFixed(2)),
      roi: parseFloat(roi.toFixed(2)),
    };
  }
}
