import { describe, it, expect, beforeAll, afterAll } from "vitest";
import * as pf from "./platformFeatures.ts";

describe("Platform Features", () => {
  const testUserId = 9999;
  const testLeaderId = 9998;
  const testGuildName = `TestGuild-${Date.now()}`;
  const testTournamentName = `TestTournament-${Date.now()}`;

  describe("Guild Management", () => {
    let guildId: number;

    it("should create a guild", async () => {
      const result = await pf.createGuild(testLeaderId, testGuildName, "A test guild");
      expect(result).toBeDefined();
      expect(result.name).toBe(testGuildName);
      expect(result.leaderId).toBe(testLeaderId);
      guildId = result.id;
    });

    it("should get guild by ID", async () => {
      const guild = await pf.getGuildById(guildId);
      expect(guild).toBeDefined();
      expect(guild?.name).toBe(testGuildName);
      expect(guild?.leaderId).toBe(testLeaderId);
    });

    it("should get guild members", async () => {
      const members = await pf.getGuildMembers(guildId);
      expect(Array.isArray(members)).toBe(true);
      expect(members.length).toBeGreaterThan(0);
      expect(members.some((m) => m.userId === testLeaderId && m.role === "leader")).toBe(true);
    });

    it("should join guild", async () => {
      const result = await pf.joinGuild(guildId, testUserId);
      expect(result).toBeDefined();
      expect(result.guildId).toBe(guildId);
      expect(result.userId).toBe(testUserId);
      expect(result.role).toBe("member");
    });

    it("should prevent duplicate guild membership", async () => {
      try {
        await pf.joinGuild(guildId, testUserId);
        expect.fail("Should have thrown an error");
      } catch (error: any) {
        expect(error.message).toContain("already a member");
      }
    });

    it("should leave guild", async () => {
      const result = await pf.leaveGuild(guildId, testUserId);
      expect(result.success).toBe(true);
    });
  });

  describe("Player Statistics", () => {
    it("should get or create player stats", async () => {
      const stats = await pf.getPlayerStats(testUserId);
      expect(stats).toBeDefined();
      expect(stats.userId).toBe(testUserId);
      expect(stats.pokerWins).toBe(0);
      expect(stats.bingoWins).toBe(0);
      expect(stats.poolSharkWins).toBe(0);
    });

    it("should record poker game result", async () => {
      await pf.recordGameResult(testUserId, "poker", true, 100, 250);
      const stats = await pf.getPlayerStats(testUserId);
      expect(stats.pokerWins).toBe(1);
      expect(parseFloat(stats.pokerTotalBet as any)).toBe(100);
      expect(parseFloat(stats.pokerTotalWon as any)).toBe(250);
    });

    it("should record bingo game result", async () => {
      await pf.recordGameResult(testUserId, "bingo", true, 50, 150);
      const stats = await pf.getPlayerStats(testUserId);
      expect(stats.bingoWins).toBe(1);
      expect(parseFloat(stats.bingoTotalBet as any)).toBe(50);
      expect(parseFloat(stats.bingoTotalWon as any)).toBe(150);
    });

    it("should record pool shark game result", async () => {
      await pf.recordGameResult(testUserId, "poolShark", true, 75, 200);
      const stats = await pf.getPlayerStats(testUserId);
      expect(stats.poolSharkWins).toBe(1);
      expect(parseFloat(stats.poolSharkTotalBet as any)).toBe(75);
      expect(parseFloat(stats.poolSharkTotalWon as any)).toBe(200);
    });

    it("should record losing game", async () => {
      await pf.recordGameResult(testUserId, "poker", false, 100, 0);
      const stats = await pf.getPlayerStats(testUserId);
      expect(stats.pokerLosses).toBe(1);
    });
  });

  describe("Referral System", () => {
    let referralId: number;

    it("should create referral code", async () => {
      const result = await pf.createReferralCode(testLeaderId, testUserId);
      expect(result).toBeDefined();
      expect(result.code).toBeDefined();
      expect(result.link).toBeDefined();
      expect(result.link).toContain(result.code);
      referralId = result.id;
    });

    it("should activate referral", async () => {
      const result = await pf.activateReferral(referralId);
      expect(result).toBeDefined();
    });

    it("should get referrals by referrer", async () => {
      const referrals = await pf.getReferralsByReferrer(testLeaderId);
      expect(Array.isArray(referrals)).toBe(true);
      expect(referrals.length).toBeGreaterThan(0);
    });
  });

  describe("VIP Tier Management", () => {
    it("should get user VIP status", async () => {
      const status = await pf.getUserVipStatus(testUserId);
      expect(status).toBeDefined();
      expect(status.userId).toBe(testUserId);
    });

    it("should update VIP tier based on winnings", async () => {
      const tier = await pf.updateVipTier(testUserId, 1000);
      // Tier might be null if no tier matches the winnings
      if (tier) {
        expect(tier.id).toBeDefined();
      }
    });
  });

  describe("Tournament Management", () => {
    let tournamentId: number;

    it("should create tournament", async () => {
      const startAt = new Date(Date.now() + 86400000); // Tomorrow
      const endAt = new Date(Date.now() + 172800000); // Day after tomorrow
      const result = await pf.createTournament(
        testTournamentName,
        "poker",
        startAt,
        endAt,
        100,
        50,
        5000,
        "A test tournament"
      );
      expect(result).toBeDefined();
      expect(result.name).toBe(testTournamentName);
      tournamentId = result.id;
    });

    it("should get tournament by ID", async () => {
      const tournament = await pf.getTournamentById(tournamentId);
      expect(tournament).toBeDefined();
      expect(tournament?.name).toBe(testTournamentName);
    });

    it("should join tournament", async () => {
      const result = await pf.joinTournament(tournamentId, testUserId);
      expect(result).toBeDefined();
      expect(result.tournamentId).toBe(tournamentId);
      expect(result.userId).toBe(testUserId);
    });

    it("should get tournament participants", async () => {
      const participants = await pf.getTournamentParticipants(tournamentId);
      expect(Array.isArray(participants)).toBe(true);
      expect(participants.length).toBeGreaterThan(0);
    });

    it("should complete tournament match", async () => {
      const result = await pf.completeTournamentMatch(tournamentId, testUserId, 1, 1000);
      expect(result).toBeDefined();
    });

    it("should get upcoming tournaments", async () => {
      const tournaments = await pf.getUpcomingTournaments(5);
      expect(Array.isArray(tournaments)).toBe(true);
    });
  });
});
