import { test, expect, chromium, Page, Browser, BrowserContext } from "@playwright/test";
import { randomUUID } from "crypto";
import * as fs from "fs";
import * as path from "path";

const SCREENSHOT_DIR = "./test-results";
const VIDEO_DIR = "./test-videos";

// Ensure directories exist
if (!fs.existsSync(SCREENSHOT_DIR)) fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
if (!fs.existsSync(VIDEO_DIR)) fs.mkdirSync(VIDEO_DIR, { recursive: true });

export interface TestUser {
  email: string;
  password: string;
  firstName: string;
  lastName: string;
  intent: string;
  userId?: string;
  accessToken?: string;
}

export interface CompanyUser extends TestUser {
  companyName: string;
}

export interface JobSeekerUser extends TestUser {
  education?: string;
  skills?: string[];
  resumePath?: string;
}

async function generateTestEmail(): Promise<string> {
  return `test_${randomUUID().slice(0, 8)}@test.com`;
}

async function apiRegister(user: TestUser): Promise<{ user_id: string }> {
  const response = await fetch("http://localhost:9100/api/auth/register", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(user),
  });
  return response.json();
}

async function apiVerifyOtp(): Promise<boolean> {
  const response = await fetch("http://localhost:9100/api/auth/verify-email", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ otp: "123456" }),
  });
  return response.ok;
}

async function apiLogin(email: string, password: string): Promise<{ access_token: string }> {
  const response = await fetch("http://localhost:9100/api/auth/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password }),
  });
  return response.json();
}

async function setRedisOtp(userId: string): Promise<void> {
  const { execSync } = await import("child_process");
  try {
    execSync(`redis-cli SETEX "otp:code:123456" 900 "${userId}"`, { encoding: "utf8" });
  } catch (e) {
    console.log("⚠️ Could not set OTP in Redis:", e);
  }
}

async function takeScreenshot(page: Page, name: string): Promise<void> {
  const filePath = path.join(SCREENSHOT_DIR, `${name}.png`);
  await page.screenshot({ path: filePath, fullPage: true });
  console.log(`📸 Screenshot: ${name}`);
}

export async function registerCompany(): Promise<CompanyUser> {
  const email = await generateTestEmail();
  const companyName = `Test Company ${randomUUID().slice(0, 6)}`;
  const user: TestUser = {
    email,
    password: "TestPassword123!",
    firstName: "John",
    lastName: "Doe",
    intent: "company",
  };

  console.log("\n📝 Step 1: Registering company via API...");
  const regData = await apiRegister(user);
  user.userId = regData.user_id;
  console.log("   ✅ Registered, user_id:", regData.user_id);

  console.log("\n🔐 Step 2: Setting test OTP in Redis...");
  await setRedisOtp(regData.user_id);
  console.log("   ✅ Set test OTP: 123456");

  console.log("\n✅ Step 3: Verifying OTP via API...");
  const verified = await apiVerifyOtp();
  if (!verified) throw new Error("OTP verification failed");
  console.log("   ✅ OTP verified!");

  console.log("\n🔑 Step 4: Logging in via API...");
  const loginData = await apiLogin(email, user.password);
  user.accessToken = loginData.access_token;
  console.log("   ✅ Logged in via API!");

  return { ...user, companyName };
}

export async function registerJobSeeker(): Promise<JobSeekerUser> {
  const email = await generateTestEmail();
  const user: TestUser = {
    email,
    password: "TestPassword123!",
    firstName: "Jane",
    lastName: "Smith",
    intent: "job_seeker",
  };

  console.log("\n📝 Step 1: Registering job seeker via API...");
  const regData = await apiRegister(user);
  user.userId = regData.user_id;
  console.log("   ✅ Registered, user_id:", regData.user_id);

  console.log("\n🔐 Step 2: Setting test OTP in Redis...");
  await setRedisOtp(regData.user_id);
  console.log("   ✅ Set test OTP: 123456");

  console.log("\n✅ Step 3: Verifying OTP via API...");
  const verified = await apiVerifyOtp();
  if (!verified) throw new Error("OTP verification failed");
  console.log("   ✅ OTP verified!");

  console.log("\n🔑 Step 4: Logging in via API...");
  const loginData = await apiLogin(email, user.password);
  user.accessToken = loginData.access_token;
  console.log("   ✅ Logged in via API!");

  return user;
}

export async function loginViaBrowser(
  context: BrowserContext,
  email: string,
  password: string
): Promise<Page> {
  const page = await context.newPage();

  console.log("\n🌐 Opening login page...");
  await page.goto("http://localhost:3000/login");
  await page.waitForLoadState("networkidle");
  await takeScreenshot(page, "01-login-page");

  console.log("✍️ Filling login form...");
  await page.fill('input[type="email"], input[name="email"]', email);
  await page.fill('input[type="password"], input[name="password"]', password);
  await takeScreenshot(page, "02-login-filled");

  console.log("🔐 Handling CAPTCHA (manual entry required)...");
  console.log("   Please enter CAPTCHA in the browser window...");

  await page.waitForFunction(
    () => {
      const btn = document.querySelector(".auth-submit-btn, button[type='submit']");
      return btn && !(btn as HTMLButtonElement).disabled;
    },
    { timeout: 60000 }
  );

  await page.click(".auth-submit-btn, button[type='submit']");
  await page.waitForTimeout(3000);
  await takeScreenshot(page, "03-after-login");

  return page;
}

export async function setSessionToken(page: Page, token: string): Promise<void> {
  await page.evaluate(
    (t) => {
      window.sessionStorage.setItem("nxtgauge_access_token", t);
      window.sessionStorage.setItem("nxtgauge_frontend_access_token", t);
    },
    token
  );
  console.log("   ✅ Session token set");
}

export async function navigateToDashboard(page: Page, role?: string): Promise<void> {
  const url = role
    ? `http://localhost:3000/dashboard?role=${role}`
    : "http://localhost:3000/dashboard";
  await page.goto(url);
  await page.waitForLoadState("networkidle");
  await page.waitForTimeout(2000);
  await takeScreenshot(page, "04-dashboard");
  console.log("   ✅ Navigated to dashboard");
}

export async function fillCompanyProfile(page: Page, companyName: string): Promise<void> {
  console.log("\n🏢 Filling company profile...");

  await page.goto("http://localhost:3000/dashboard/profile?role=COMPANY");
  await page.waitForLoadState("networkidle");
  await page.waitForTimeout(2000);
  await takeScreenshot(page, "05-company-profile");

  const nameInput = await page.locator('input[name="companyName"], input[name="name"]').first();
  if (await nameInput.isVisible().catch(() => false)) {
    await nameInput.fill(companyName);
    console.log("   ✅ Company name filled");
  }

  const websiteInput = await page.locator('input[name="website"], input[placeholder*="website"]').first();
  if (await websiteInput.isVisible().catch(() => false)) {
    await websiteInput.fill("https://testcompany.com");
    console.log("   ✅ Website filled");
  }

  const phoneInput = await page.locator('input[name="phone"], input[name="companyPhone"]').first();
  if (await phoneInput.isVisible().catch(() => false)) {
    await phoneInput.fill("+91 9876543210");
    console.log("   ✅ Phone filled");
  }

  await takeScreenshot(page, "06-company-profile-filled");

  const submitBtn = await page.locator('button[type="submit"], button:has-text("Submit")').first();
  if (await submitBtn.isVisible().catch(() => false)) {
    await submitBtn.click();
    await page.waitForTimeout(3000);
    console.log("   ✅ Profile submitted");
    await takeScreenshot(page, "07-company-profile-submitted");
  }
}

export async function fillJobSeekerProfile(page: Page): Promise<void> {
  console.log("\n👤 Filling job seeker profile...");

  await page.goto("http://localhost:3000/dashboard/profile?role=JOB_SEEKER");
  await page.waitForLoadState("networkidle");
  await page.waitForTimeout(2000);
  await takeScreenshot(page, "08-jobseeker-profile");

  const firstNameInput = await page.locator('input[name="firstName"], input[name="first_name"]').first();
  if (await firstNameInput.isVisible().catch(() => false)) {
    await firstNameInput.fill("Jane");
    console.log("   ✅ First name filled");
  }

  const lastNameInput = await page.locator('input[name="lastName"], input[name="last_name"]').first();
  if (await lastNameInput.isVisible().catch(() => false)) {
    await lastNameInput.fill("Smith");
    console.log("   ✅ Last name filled");
  }

  const bioInput = await page.locator('textarea[name="bio"], textarea[name="about"]').first();
  if (await bioInput.isVisible().catch(() => false)) {
    await bioInput.fill("Experienced software developer with 5+ years in the industry.");
    console.log("   ✅ Bio filled");
  }

  await takeScreenshot(page, "09-jobseeker-profile-filled");

  const submitBtn = await page.locator('button[type="submit"], button:has-text("Submit")').first();
  if (await submitBtn.isVisible().catch(() => false)) {
    await submitBtn.click();
    await page.waitForTimeout(3000);
    console.log("   ✅ Profile submitted");
    await takeScreenshot(page, "10-jobseeker-profile-submitted");
  }
}

export async function adminLogin(context: BrowserContext): Promise<Page> {
  console.log("\n🔐 Opening admin panel...");
  const adminPage = await context.newPage();
  await adminPage.goto("http://localhost:3001/login");
  await adminPage.waitForLoadState("networkidle");
  await takeScreenshot(adminPage, "11-admin-login");

  console.log("✍️ Filling admin credentials...");
  await adminPage.fill('input[type="email"], input[name="email"]', "admin@nxtgauge.com");
  await adminPage.fill('input[type="password"], input[name="password"]', "Admin@nxtgauge1");
  await adminPage.click('button[type="submit"], button:has-text("Login"), button:has-text("Sign In")');
  await adminPage.waitForTimeout(3000);
  await takeScreenshot(adminPage, "12-admin-dashboard");
  console.log("   ✅ Admin logged in");

  return adminPage;
}

export async function findUserInAdminVerification(
  adminPage: Page,
  email: string
): Promise<boolean> {
  console.log(`\n🔍 Searching for ${email} in admin verification...`);

  const verificationLinks = [
    "text=Verifications",
    'a:has-text("Verifications")',
    '[href*="verification"]',
    "text=Pending",
  ];

  for (const selector of verificationLinks) {
    const link = adminPage.locator(selector).first();
    if (await link.isVisible().catch(() => false)) {
      await link.click();
      await adminPage.waitForTimeout(2000);
      break;
    }
  }

  await takeScreenshot(adminPage, "13-verification-list");

  const searchInput = adminPage.locator('input[placeholder*="search" i], input[name="search"]').first();
  if (await searchInput.isVisible().catch(() => false)) {
    await searchInput.fill(email);
    await adminPage.waitForTimeout(2000);
    await takeScreenshot(adminPage, "14-search-results");
  }

  const content = await adminPage.locator("body").innerText();
  return content.includes(email);
}

test.describe("Nxtgauge E2E Verification Flows", () => {
  test.setTimeout(600000);

  test("Company Registration → Profile → Admin Verification", async () => {
    const browser = await chromium.launch({ headless: false, slowMo: 100 });
    const context = await browser.newContext({
      viewport: { width: 1400, height: 900 },
      recordVideo: { dir: VIDEO_DIR, size: { width: 1400, height: 900 } },
    });

    try {
      const company = await registerCompany();

      console.log("\n🌐 MANUAL STEP: Open browser and:");
      console.log("   1. Go to http://localhost:3000/login");
      console.log("   2. Login with:");
      console.log("      Email:", company.email);
      console.log("      Password:", company.password);
      console.log("   3. Complete CAPTCHA");
      console.log("   4. Fill company profile at /dashboard/profile?role=COMPANY");
      console.log("   5. Upload business documents");
      console.log("   6. Submit for verification");
      console.log("   Then press Enter to continue to admin verification...");

      await context.close();
      await browser.close();

      console.log("\n⏳ Waiting 120 seconds for manual browser steps...");
      await new Promise((r) => setTimeout(r, 120000));

    } catch (error) {
      console.error("❌ Test failed:", error);
      throw error;
    }
  });

  test("Job Seeker Registration → Profile → Admin Verification", async () => {
    const browser = await chromium.launch({ headless: false, slowMo: 100 });
    const context = await browser.newContext({
      viewport: { width: 1400, height: 900 },
      recordVideo: { dir: VIDEO_DIR, size: { width: 1400, height: 900 } },
    });

    try {
      const jobSeeker = await registerJobSeeker();

      console.log("\n🌐 MANUAL STEP: Open browser and:");
      console.log("   1. Go to http://localhost:3000/login");
      console.log("   2. Login with:");
      console.log("      Email:", jobSeeker.email);
      console.log("      Password:", jobSeeker.password);
      console.log("   3. Complete CAPTCHA");
      console.log("   4. Fill job seeker profile at /dashboard/profile?role=JOB_SEEKER");
      console.log("   5. Add education, skills, resume");
      console.log("   6. Submit for verification");
      console.log("   Then press Enter to continue to admin verification...");

      await context.close();
      await browser.close();

      console.log("\n⏳ Waiting 120 seconds for manual browser steps...");
      await new Promise((r) => setTimeout(r, 120000));

    } catch (error) {
      console.error("❌ Test failed:", error);
      throw error;
    }
  });
});
