import { test, expect, request } from "@playwright/test";

const API_BASE = process.env.TEST_ENV === 'production' 
  ? "https://test111.nxtgauge.com/api" 
  : "http://localhost:3000/api";

async function getAuthToken(): Promise<string | null> {
  const ctx = await request.newContext();
  const res = await ctx.post(`${API_BASE}/auth/login`, {
    data: {
      email: "testtutora2026@example.com",
      password: "Test1234!",
    },
  });
  if (!res.ok()) return null;
  const data = await res.json();
  return data.access_token || null;
}

async function getCompanyAuthToken(): Promise<string | null> {
  const ctx = await request.newContext();
  const res = await ctx.post(`${API_BASE}/auth/login`, {
    data: {
      email: "testcompany@example.com",
      password: "TestPassword123!",
    },
  });
  if (!res.ok()) return null;
  const data = await res.json();
  return data.access_token || null;
}

test.describe("AI API Endpoints", () => {
  let companyToken: string | null;
  let jobSeekerToken: string | null;

  test.beforeAll(async () => {
    companyToken = await getCompanyAuthToken();
    jobSeekerToken = await getAuthToken();
  });

  test.describe("Company AI - Generate Job Field", () => {
    test("POST /ai/generate-job-field returns generated content", async ({ page }) => {
      if (!companyToken) test.skip();

      await page.goto(`${API_BASE}/`);
      await page.evaluate((t: string | null) => {
        window.sessionStorage.setItem("nxtgauge_access_token", t ?? "");
      }, companyToken);

      const ctx = await request.newContext();
      const res = await ctx.post(`${API_BASE}/ai/generate-job-field`, {
        headers: {
          Authorization: `Bearer ${companyToken}`,
        },
        data: {
          field: "title",
          prompt: "Generate a job title for a senior frontend developer position",
        },
      });

      if (res.status() === 404) {
        test.skip();
        return;
      }

      expect(res.status()).toBe(200);
      const body = await res.json();
      expect(body).toHaveProperty("field", "title");
      expect(body).toHaveProperty("content");
      expect(typeof body.content).toBe("string");
      expect(body.content.length).toBeGreaterThan(0);
    });

    test("POST /ai/generate-job-field rejects invalid field", async () => {
      if (!companyToken) test.skip();

      const ctx = await request.newContext();
      const res = await ctx.post(`${API_BASE}/ai/generate-job-field`, {
        headers: {
          Authorization: `Bearer ${companyToken}`,
        },
        data: {
          field: "invalid_field",
          prompt: "test",
        },
      });

      if (res.status() === 404) test.skip();
      else expect(res.status()).toBe(400);
    });

    test("POST /ai/generate-job-field rate limits after daily quota", async () => {
      if (!companyToken) test.skip();

      const ctx = await request.newContext();
      let got429 = false;

      for (let i = 0; i < 6; i++) {
        const res = await ctx.post(`${API_BASE}/ai/generate-job-field`, {
          headers: {
            Authorization: `Bearer ${companyToken}`,
          },
          data: {
            field: "title",
            prompt: `Test prompt ${i}`,
          },
        });

        if (res.status() === 404) {
          test.skip();
          return;
        }

        if (res.status() === 429) {
          got429 = true;
          const body = await res.json();
          expect(body.code).toBe("AI_LIMIT_EXCEEDED");
          break;
        }
      }

      if (!got429) {
        console.warn("Did not hit rate limit within 6 requests - this may indicate the feature is not working or limit is higher than expected");
      }
    });

    test("POST /ai/generate-job-field returns 401 without auth when route exists", async () => {
      const ctx = await request.newContext();
      const res = await ctx.post(`${API_BASE}/ai/generate-job-field`, {
        data: {
          field: "title",
          prompt: "test",
        },
      });

      if (res.status() === 404) {
        test.skip();
        return;
      }
      expect(res.status()).toBe(401);
    });
  });

  test.describe("AI Usage Endpoint", () => {
    test("GET /ai/usage returns usage stats for company", async () => {
      if (!companyToken) test.skip();

      const ctx = await request.newContext();
      const res = await ctx.get(`${API_BASE}/ai/usage`, {
        headers: {
          Authorization: `Bearer ${companyToken}`,
        },
      });

      if (res.status() === 404) {
        test.skip();
        return;
      }

      expect(res.status()).toBe(200);
      const body = await res.json();
      expect(body).toHaveProperty("used_today");
      expect(body).toHaveProperty("limit");
      expect(body).toHaveProperty("has_ai_pack");
      expect(typeof body.used_today).toBe("number");
      expect(typeof body.limit).toBe("number");
    });

    test("GET /ai/usage returns 401 without auth when route exists", async () => {
      const ctx = await request.newContext();
      const res = await ctx.get(`${API_BASE}/ai/usage`);

      if (res.status() === 404) {
        test.skip();
        return;
      }
      expect(res.status()).toBe(401);
    });
  });
});

test.describe("Auth API Endpoints", () => {
  test("POST /auth/login returns token for valid credentials", async () => {
    const ctx = await request.newContext();
    const res = await ctx.post(`${API_BASE}/auth/login`, {
      data: {
        email: "testtutora2026@example.com",
        password: "Test1234!",
      },
    });

    if (res.status() === 429) {
      test.skip();
      return;
    }

    expect(res.status()).toBe(200);
    const body = await res.json();
    expect(body).toHaveProperty("access_token");
    expect(typeof body.access_token).toBe("string");
  });

  test("POST /auth/login returns 401 for invalid credentials", async () => {
    const ctx = await request.newContext();
    const res = await ctx.post(`${API_BASE}/auth/login`, {
      data: {
        email: "invalid@example.com",
        password: "wrongpassword",
      },
    });

    if (res.status() === 429) test.skip();
    else expect(res.status()).toBe(401);
  });

  test("POST /auth/login rate limits after too many attempts", async () => {
    const ctx = await request.newContext();
    for (let i = 0; i < 6; i++) {
      await ctx.post(`${API_BASE}/auth/login`, {
        data: {
          email: "testtutora2026@example.com",
          password: "wrongpassword",
        },
      });
    }

    const res = await ctx.post(`${API_BASE}/auth/login`, {
      data: {
        email: "testtutora2026@example.com",
        password: "Test1234!",
      },
    });

    expect(res.status()).toBe(429);
    const body = await res.json();
    expect(body.code).toBe("RATE_LIMITED");
  });
});

test.describe("Gateway API", () => {
  test("Gateway routes /api/ai/* to users service", async () => {
    const ctx = await request.newContext();
    const res = await ctx.get(`${API_BASE}/ai/usage`, {
      headers: {
        Authorization: `Bearer dummy`,
      },
    });

    if (res.status() === 404) {
      test.skip();
      return;
    }
    expect(res.status()).not.toBe(404);
  });

  test("Gateway returns 404 for unknown routes", async () => {
    const ctx = await request.newContext();
    const res = await ctx.get(`${API_BASE}/nonexistent-route`);

    expect(res.status()).toBe(404);
  });
});
