import { describe, it, expect, vi, beforeEach } from "vitest";
import type { Pool } from "mysql2/promise";
import { handleBetaTesterRegistration, isInBetaPeriod } from "../beta-tester.js";

const makeDb = (executeImpl: (sql: string, params?: unknown[]) => any) =>
  ({
    execute: vi.fn(async (sql: string, params?: unknown[]) =>
      executeImpl(sql, params),
    ),
  }) as unknown as Pool;

describe("beta-tester", () => {
  beforeEach(() => {
    vi.restoreAllMocks();
  });

  it("isInBetaPeriod: true pendant 30 jours après launch_date", async () => {
    const db = makeDb(async () => [[{ config_value: "2026-02-09T00:00:00Z" }]]);
    const createdAt = new Date("2026-03-10T00:00:00Z"); // 29 jours après (février 2026 = 28 jours)
    await expect(isInBetaPeriod(db, createdAt)).resolves.toBe(true);
  });

  it("isInBetaPeriod: false après 30 jours", async () => {
    const db = makeDb(async () => [[{ config_value: "2026-02-09T00:00:00Z" }]]);
    const createdAt = new Date("2026-03-12T00:00:00Z");
    await expect(isInBetaPeriod(db, createdAt)).resolves.toBe(false);
  });

  it("handleBetaTesterRegistration: attribue les avatars si compte en période beta", async () => {
    const db = makeDb(async (sql: string) => {
      if (sql.includes("FROM users") && sql.includes("created_at")) {
        return [[{ createdAt: "2026-02-10T00:00:00Z" }]];
      }
      if (sql.includes("FROM app_config") && sql.includes("'launch_date'")) {
        return [[{ config_value: "2026-02-09T00:00:00Z" }]];
      }
      if (sql.includes("FROM avatars") && sql.includes("beta-testeur")) {
        return [[{ id: 101 }, { id: 102 }]];
      }
      if (sql.includes("INSERT IGNORE INTO user_avatars")) {
        return [[]];
      }
      throw new Error(`SQL inattendu: ${sql}`);
    });

    await handleBetaTesterRegistration(db, 42);

    const calls = (db.execute as unknown as { mock: any }).mock.calls as Array<
      [string, unknown[]?]
    >;
    expect(calls.some(([sql]) => sql.includes("SELECT created_at"))).toBe(true);
    expect(calls.some(([sql]) => sql.includes("FROM app_config"))).toBe(true);
    expect(calls.some(([sql]) => sql.includes("FROM avatars"))).toBe(true);
    expect(
      calls.filter(([sql]) => sql.includes("INSERT IGNORE INTO user_avatars"))
        .length,
    ).toBe(2);
  });

  it("handleBetaTesterRegistration: ne touche pas aux avatars hors période beta", async () => {
    const db = makeDb(async (sql: string) => {
      if (sql.includes("FROM users") && sql.includes("created_at")) {
        return [[{ createdAt: "2026-04-10T00:00:00Z" }]];
      }
      if (sql.includes("FROM app_config") && sql.includes("'launch_date'")) {
        return [[{ config_value: "2026-02-09T00:00:00Z" }]];
      }
      if (sql.includes("FROM avatars") || sql.includes("INSERT IGNORE INTO user_avatars")) {
        throw new Error("Ne devrait pas requêter/insérer des avatars");
      }
      throw new Error(`SQL inattendu: ${sql}`);
    });

    await handleBetaTesterRegistration(db, 42);
    expect(db.execute).toHaveBeenCalledTimes(2);
  });
});

