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

const BASE_URL = "http://localhost:3001";
const TEST_MEMO_UID = "_FuPjYWlqiwAHHKbiQ95Mg"; // Use a known public memo UID

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();
    if (await nameInput.isVisible()) {
      await nameInput.fill("PrivateTester");
    }
    
    // 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();
    if (await visibilityButton.isVisible({ 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();
      if (await privateOption.isVisible({ timeout: 2000 })) {
        await privateOption.click();
      }
    }
    
    // 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();
    if (await nameInput.isVisible()) {
      await nameInput.fill("ReloadTester");
    }
    
    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();
      if (await nameInput1.isVisible()) {
        await nameInput1.fill("User1");
      }
      
      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();
      if (await visibilityButton1.isVisible({ timeout: 2000 })) {
        await visibilityButton1.click();
        await page1.waitForTimeout(500);
        const privateOption1 = page1.locator('text=Private, text=Riêng tư').first();
        if (await privateOption1.isVisible({ timeout: 2000 })) {
          await privateOption1.click();
        }
      }
      
      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();
    if (await nameInput1.isVisible()) {
      await nameInput1.fill("MixedTester");
    }
    
    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);
  });
});

