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

const BASE_URL = process.env.BASE_URL || "http://127.0.0.1:3001";
let TEST_MEMO_UID = "";

test.beforeAll(async ({ browser }) => {
  const context = await browser.newContext();
  const page = await context.newPage();
  
  await page.goto(`${BASE_URL}/auth`);
  
  // Create test user if needed
  try {
    const isSignUpVisible = await page.getByRole('button', { name: "Sign Up" }).isVisible({ timeout: 2000 });
    if (isSignUpVisible) {
      await page.waitForTimeout(1000);
      const emailInput = page.getByRole('textbox', { name: /email/i }).or(page.locator('input[type="email"]')).first();
      await emailInput.fill('e2etest@test.com');
      
      const pwdInput = page.getByRole('textbox', { name: /password/i }).or(page.locator('input[type="password"]')).first();
      await pwdInput.fill('Test12345!');
      
      await page.getByRole('button', { name: "Sign Up" }).click();
      await page.waitForTimeout(2000);
    }
  } catch (e) {
    console.log("Signup not visible or error:", e);
  }

  // Standard login fallback
  const isSignInVisible = await page.getByRole('button', { name: "Sign In" }).isVisible({ timeout: 2000 }).catch(() => false);
  if (isSignInVisible) {
    const emailInput = page.getByRole('textbox', { name: /email/i }).or(page.locator('input[type="email"], input[name="email"], input[type="text"][placeholder*="username" i], input[type="text"][placeholder*="Username" i]')).first();
    const pwdInput = page.locator('input[type="password"]').first();
    
    await emailInput.fill('e2etest');
    await pwdInput.fill('Test12345!');
    await page.getByRole('button', { name: /sign in/i }).or(page.locator('button[type="submit"]')).first().click();
    
    try {
        await page.waitForURL(/.*app.*/, { timeout: 10000 });
    } catch (e) {
        console.log("URL didn't change to /app, maybe already logged in");
    }
  }

  await page.goto(`${BASE_URL}/app`);
  
  try {
      await page.waitForSelector('textarea', { timeout: 5000 });
      const editor = page.locator('textarea').first();
      await editor.fill('Test public memo for anonymous private comments ' + Date.now());
      const postBtn = page.getByRole('button', { name: /save|post|submit/i }).first();
      await postBtn.click();
      await page.waitForTimeout(2000);
  } catch (e) {
      console.log("Could not post test memo:", e);
  }

  try {
      await page.waitForSelector('[data-testid="memo-card"], article', { timeout: 5000 });
      const firstMemo = page.locator('[data-testid="memo-card"]').or(page.locator('article').first()).first();
      await firstMemo.click();
      await page.waitForURL(/.*memos\/.*/, { timeout: 5000 });
      
      const match = page.url().match(/\/memos\/(.+)/);
      if (match) {
        TEST_MEMO_UID = match[1];
      } else {
        TEST_MEMO_UID = "_FuPjYWlqiwAHHKbiQ95Mg";
      }
  } catch (e) {
      TEST_MEMO_UID = "_FuPjYWlqiwAHHKbiQ95Mg"; // fallback
  }
  await context.close();
});

test.describe("Private Comments for Anonymous Users", () => {
  test.beforeEach(async ({ page }) => {
    // Clear localStorage to ensure fresh anonymous session
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.evaluate(() => localStorage.clear());
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
  });

  test("Test 1: Anonymous user can create PRIVATE comment and see it", async ({ page }) => {
    // Visit memo detail page as logged-out user
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Click to show comment editor
    const writeCommentButton = page.locator('button:has-text("Write a comment")').first();
    await expect(writeCommentButton).toBeVisible({ timeout: 5000 });
    await writeCommentButton.click();
    
    // Wait for comment editor to appear
    await page.waitForSelector('textarea[placeholder*="comment"], textarea[placeholder*="Comment"]', { timeout: 5000 });
    
    // Type display name
    const nameInput = page.locator('input[id*="anonymous-name"]').first();
    try {
      await nameInput.waitFor({ state: 'visible', timeout: 2000 });
      await nameInput.fill("PrivateTester");
    } catch (e) {
      console.log("Anonymous name input not visible");
    }
    
    // Type comment
    const commentText = `PRIVATE comment test at ${new Date().toISOString()}`;
    const commentEditor = page.locator('textarea[placeholder*="comment"], textarea[placeholder*="Comment"]').first();
    await commentEditor.fill(commentText);
    
    // Find visibility selector and change to PRIVATE
    // Look for visibility dropdown/button (usually has lock icon or "Private" text)
    const visibilityButton = page.locator('button:has-text("Public"), button:has-text("Private"), button:has-text("Riêng tư")').first();
    try {
      await visibilityButton.waitFor({ state: 'visible', timeout: 2000 });
      await visibilityButton.click();
      // Wait for dropdown menu
      await page.waitForTimeout(500);
      // Click on Private option
      const privateOption = page.locator('text=Private, text=Riêng tư, text=PRIVATE').first();
      try {
        await privateOption.waitFor({ state: 'visible', timeout: 2000 });
        await privateOption.click();
      } catch (e) {}
    } catch (e) {}
    
    // Submit comment
    const saveButton = page.locator('button:has-text("Save")').first();
    await saveButton.click();
    
    // Wait for comment to appear
    await page.waitForTimeout(3000);
    
    // Verify comment appears (user should see their own PRIVATE comment)
    const commentTextElement = page.locator(`text=${commentText}`);
    await expect(commentTextElement).toBeVisible({ timeout: 10000 });
    
    // Verify anonymous label
    const anonymousLabel = page.locator('text=/Anonymous.*PrivateTester|Anonymous.*#/i').first();
    await expect(anonymousLabel).toBeVisible({ timeout: 5000 });
  });

  test("Test 2: Anonymous user sees their PRIVATE comment after page reload", async ({ page }) => {
    // Get anonymous ID first
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Create PRIVATE comment
    const writeCommentButton = page.locator('button:has-text("Write a comment")').first();
    await writeCommentButton.click();
    await page.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
    
    const nameInput = page.locator('input[id*="anonymous-name"]').first();
    try {
      await nameInput.waitFor({ state: 'visible', timeout: 2000 });
      await nameInput.fill("ReloadTester");
    } catch (e) {
      console.log("Anonymous name input not visible");
    }
    
    const commentText = `PRIVATE comment for reload test ${Date.now()}`;
    const commentEditor = page.locator('textarea[placeholder*="comment"]').first();
    await commentEditor.fill(commentText);
    
    // Set to PRIVATE
    const visibilityButton = page.locator('button:has-text("Public"), button:has-text("Private")').first();
    if (await visibilityButton.isVisible({ timeout: 2000 })) {
      await visibilityButton.click();
      await page.waitForTimeout(500);
      const privateOption = page.locator('text=Private, text=Riêng tư').first();
      if (await privateOption.isVisible({ timeout: 2000 })) {
        await privateOption.click();
      }
    }
    
    const saveButton = page.locator('button:has-text("Save")').first();
    await saveButton.click();
    await page.waitForTimeout(3000);
    
    // Verify comment is visible
    await expect(page.locator(`text=${commentText}`)).toBeVisible({ timeout: 5000 });
    
    // Get anonymous ID
    const anonymousId = await page.evaluate(() => localStorage.getItem("anonymous_id"));
    expect(anonymousId).toBeTruthy();
    expect(anonymousId).toMatch(/^anonymous_/);
    
    // Reload page
    await page.reload();
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Verify PRIVATE comment is still visible (same anonymous ID)
    await expect(page.locator(`text=${commentText}`)).toBeVisible({ timeout: 10000 });
    
    // Verify anonymous ID persisted
    const persistedId = await page.evaluate(() => localStorage.getItem("anonymous_id"));
    expect(persistedId).toBe(anonymousId);
  });

  test("Test 3: Different anonymous user cannot see PRIVATE comment from another user", async ({ browser }) => {
    // Create two separate browser contexts (different anonymous users)
    const context1 = await browser.newContext();
    const context2 = await browser.newContext();
    
    const page1 = await context1.newPage();
    const page2 = await context2.newPage();
    
    try {
      // User 1: Create PRIVATE comment
      await page1.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
      await page1.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
      
      const writeButton1 = page1.locator('button:has-text("Write a comment")').first();
      await writeButton1.click();
      await page1.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
      
      const nameInput1 = page1.locator('input[id*="anonymous-name"]').first();
      try {
        await nameInput1.waitFor({ state: 'visible', timeout: 2000 });
        await nameInput1.fill("User1");
      } catch (e) {
        console.log("Anonymous name input not visible");
      }
      
      const commentText = `PRIVATE comment from User1 ${Date.now()}`;
      const editor1 = page1.locator('textarea[placeholder*="comment"]').first();
      await editor1.fill(commentText);
      
      // Set to PRIVATE
      const visibilityButton1 = page1.locator('button:has-text("Public"), button:has-text("Private")').first();
      try {
        await visibilityButton1.waitFor({ state: 'visible', timeout: 2000 });
        await visibilityButton1.click();
        await page1.waitForTimeout(500);
        const privateOption1 = page1.locator('text=Private, text=Riêng tư').first();
        try {
          await privateOption1.waitFor({ state: 'visible', timeout: 2000 });
          await privateOption1.click();
        } catch(e) {}
      } catch(e) {}
      
      const save1 = page1.locator('button:has-text("Save")').first();
      await save1.click();
      await page1.waitForTimeout(3000);
      
      // Verify User1 sees their PRIVATE comment
      await expect(page1.locator(`text=${commentText}`)).toBeVisible({ timeout: 5000 });
      
      // Get User1's anonymous ID
      const anonymousId1 = await page1.evaluate(() => localStorage.getItem("anonymous_id"));
      
      // User 2: Visit same memo (different anonymous ID)
      await page2.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
      await page2.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
      
      // Get User2's anonymous ID (should be different)
      const anonymousId2 = await page2.evaluate(() => localStorage.getItem("anonymous_id"));
      expect(anonymousId2).toBeTruthy();
      expect(anonymousId2).not.toBe(anonymousId1);
      
      // User2 should NOT see User1's PRIVATE comment
      // Wait a bit for comments to load
      await page2.waitForTimeout(2000);
      
      // The PRIVATE comment should NOT be visible to User2
      const privateComment = page2.locator(`text=${commentText}`);
      await expect(privateComment).not.toBeVisible({ timeout: 5000 });
      
      // But User2 should see PUBLIC comments if any exist
      // (This test assumes there might be other PUBLIC comments)
    } finally {
      await context1.close();
      await context2.close();
    }
  });

  test("Test 4: Anonymous user can create both PUBLIC and PRIVATE comments", async ({ page }) => {
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Create PUBLIC comment
    const writeButton1 = page.locator('button:has-text("Write a comment")').first();
    await writeButton1.click();
    await page.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
    
    const nameInput1 = page.locator('input[id*="anonymous-name"]').first();
    try {
      await nameInput1.waitFor({ state: 'visible', timeout: 2000 });
      await nameInput1.fill("MixedTester");
    } catch (e) {
      console.log("Anonymous name input not visible");
    }
    
    const publicComment = `PUBLIC comment ${Date.now()}`;
    const editor1 = page.locator('textarea[placeholder*="comment"]').first();
    await editor1.fill(publicComment);
    
    // Ensure it's PUBLIC (default)
    const saveButton1 = page.locator('button:has-text("Save")').first();
    await saveButton1.click();
    await page.waitForTimeout(3000);
    
    // Create PRIVATE comment
    const writeButton2 = page.locator('button:has-text("Write a comment")').first();
    await writeButton2.click();
    await page.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
    
    const privateComment = `PRIVATE comment ${Date.now()}`;
    const editor2 = page.locator('textarea[placeholder*="comment"]').first();
    await editor2.fill(privateComment);
    
    // Set to PRIVATE
    const visibilityButton = page.locator('button:has-text("Public"), button:has-text("Private")').first();
    if (await visibilityButton.isVisible({ timeout: 2000 })) {
      await visibilityButton.click();
      await page.waitForTimeout(500);
      const privateOption = page.locator('text=Private, text=Riêng tư').first();
      if (await privateOption.isVisible({ timeout: 2000 })) {
        await privateOption.click();
      }
    }
    
    const saveButton2 = page.locator('button:has-text("Save")').first();
    await saveButton2.click();
    await page.waitForTimeout(3000);
    
    // User should see both comments (their own PUBLIC and PRIVATE)
    await expect(page.locator(`text=${publicComment}`)).toBeVisible({ timeout: 5000 });
    await expect(page.locator(`text=${privateComment}`)).toBeVisible({ timeout: 5000 });
  });

  test("Test 5: Visibility selector is visible in comment editor", async ({ page }) => {
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Open comment editor
    const writeButton = page.locator('button:has-text("Write a comment")').first();
    await writeButton.click();
    await page.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
    
    // Check if visibility selector is visible
    // It should be a button with "Public" or "Private" text, or a lock icon
    const visibilitySelector = page.locator(
      'button:has-text("Public"), button:has-text("Private"), button:has-text("Riêng tư"), button:has-text("Công khai"), [aria-label*="visibility"], button svg[class*="lock"]'
    ).first();
    
    await expect(visibilitySelector).toBeVisible({ timeout: 5000 });
    
    // Click it to verify dropdown opens
    await visibilitySelector.click();
    await page.waitForTimeout(500);
    
    // Check if dropdown menu appears with visibility options
    const privateOption = page.locator('text=Private, text=Riêng tư, text=PRIVATE').first();
    const publicOption = page.locator('text=Public, text=Công khai, text=PUBLIC').first();
    
    // At least one option should be visible
    const hasPrivate = await privateOption.isVisible({ timeout: 1000 }).catch(() => false);
    const hasPublic = await publicOption.isVisible({ timeout: 1000 }).catch(() => false);
    
    expect(hasPrivate || hasPublic).toBe(true);
  });
});

