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 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("Anonymous Comments (Option 3)", () => {
  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());
  });

  test("Test 1: Anonymous identity persistence", async ({ page }) => {
    // Visit memo detail page as logged-out user
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    
    // Wait for page to load
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Check if anonymous comment UI is visible (should show "Write a comment" button)
    const writeCommentButton = page.locator('button:has-text("Write a comment"), button:has-text("write-a-comment")').first();
    await writeCommentButton.waitFor({ state: 'visible', timeout: 5000 }).catch(() => {});
    await expect(writeCommentButton).toBeVisible({ timeout: 5000 });
    
    // Click to show comment editor
    await writeCommentButton.click();
    
    // Wait for comment editor to appear
    await page.waitForSelector('input[id*="anonymous-name"], 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("Tester");
    } catch (e) {
      console.log("Anonymous name input not visible");
    }
    
    // Type comment
    const commentText = `Test anonymous comment at ${new Date().toISOString()}`;
    const commentEditor = page.locator('textarea[placeholder*="comment"], textarea[placeholder*="Comment"]').first();
    await commentEditor.fill(commentText);
    
    // Submit comment (look for save/submit button)
    const saveButton = page.locator('button:has-text("Save"), button:has-text("Post"), button[type="submit"]').first();
    await saveButton.click();
    
    // Wait for comment to appear in the list
    await page.waitForTimeout(2000); // Give time for API call and refetch
    
    // Check that comment appears with anonymous label
    const anonymousLabel = page.locator('text=/Anonymous.*Tester|Anonymous.*#/i').first();
    await expect(anonymousLabel).toBeVisible({ timeout: 10000 });
    
    // Refresh page
    await page.reload();
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Verify anonymous identity persisted (same anonymous ID should be used)
    // Check localStorage for anonymous_id
    const anonymousId = await page.evaluate(() => localStorage.getItem("anonymous_id"));
    expect(anonymousId).toBeTruthy();
    expect(anonymousId).toMatch(/^anonymous_/);
    
    // Verify comment still shows with same anonymous label
    const persistedLabel = page.locator('text=/Anonymous.*Tester|Anonymous.*#/i').first();
    await expect(persistedLabel).toBeVisible({ timeout: 5000 });
  });

  test("Test 2: Multiple anonymous comments in one session", async ({ page }) => {
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Post first comment
    const writeCommentButton = page.locator('button:has-text("Write a comment"), 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("MultiTester");
    } catch (e) {
      console.log("Anonymous name input not visible");
    }
    
    const commentEditor1 = page.locator('textarea[placeholder*="comment"]').first();
    await commentEditor1.fill("First anonymous comment");
    
    const saveButton1 = page.locator('button:has-text("Save"), button:has-text("Post")').first();
    await saveButton1.click();
    await page.waitForTimeout(2000);
    
    // Post second comment (should use same anonymous identity)
    const writeCommentButton2 = page.locator('button:has-text("Write a comment")').first();
    await writeCommentButton2.click();
    await page.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
    
    const commentEditor2 = page.locator('textarea[placeholder*="comment"]').first();
    await commentEditor2.fill("Second anonymous comment");
    
    const saveButton2 = page.locator('button:has-text("Save"), button:has-text("Post")').first();
    await saveButton2.click();
    await page.waitForTimeout(2000);
    
    // Verify both comments show same anonymous label
    const anonymousLabels = page.locator('text=/Anonymous.*MultiTester|Anonymous.*#/i');
    const count = await anonymousLabels.count();
    expect(count).toBeGreaterThanOrEqual(1); // At least one should match
    
    // Verify both comments are visible
    const comments = page.locator('text=/First anonymous comment|Second anonymous comment/');
    const commentCount = await comments.count();
    expect(commentCount).toBeGreaterThanOrEqual(1);
  });

  test("Test 3: Different sessions produce different identities", async ({ browser }) => {
    // Create two separate browser contexts (simulating different sessions)
    const context1 = await browser.newContext();
    const context2 = await browser.newContext();
    
    const page1 = await context1.newPage();
    const page2 = await context2.newPage();
    
    try {
      // Session 1: Post 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 editor1 = page1.locator('textarea[placeholder*="comment"]').first();
      await editor1.fill("Comment from session 1");
      
      const save1 = page1.locator('button:has-text("Save"), button:has-text("Post")').first();
      await save1.click();
      await page1.waitForTimeout(2000);
      
      // Get anonymous ID from session 1
      const anonymousId1 = await page1.evaluate(() => localStorage.getItem("anonymous_id"));
      
      // Session 2: Post comment
      await page2.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
      await page2.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
      
      const writeButton2 = page2.locator('button:has-text("Write a comment")').first();
      await writeButton2.click();
      await page2.waitForSelector('textarea[placeholder*="comment"]', { timeout: 5000 });
      
      const editor2 = page2.locator('textarea[placeholder*="comment"]').first();
      await editor2.fill("Comment from session 2");
      
      const save2 = page2.locator('button:has-text("Save"), button:has-text("Post")').first();
      await save2.click();
      await page2.waitForTimeout(2000);
      
      // Get anonymous ID from session 2
      const anonymousId2 = await page2.evaluate(() => localStorage.getItem("anonymous_id"));
      
      // Verify different anonymous IDs
      expect(anonymousId1).toBeTruthy();
      expect(anonymousId2).toBeTruthy();
      expect(anonymousId1).not.toBe(anonymousId2);
      
      // Verify both comments are visible on the page
      await page1.reload();
      await page1.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
      
      const comment1 = page1.locator('text=/Comment from session 1/');
      const comment2 = page1.locator('text=/Comment from session 2/');
      
      await expect(comment1).toBeVisible({ timeout: 5000 });
      await expect(comment2).toBeVisible({ timeout: 5000 });
    } finally {
      await context1.close();
      await context2.close();
    }
  });

  test("Test 4: Logged-in vs anonymous behavior", async ({ page, browser }) => {
    // Start as anonymous user
    await page.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
    await page.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
    
    // Verify anonymous comment UI is visible
    const anonymousUI = page.locator('button:has-text("Write a comment"), input[id*="anonymous-name"]').first();
    await expect(anonymousUI).toBeVisible({ timeout: 5000 });
    
    // Verify sign in button is also visible
    const signInButton = page.locator('button:has-text("Sign In"), button:has-text("sign-in")').first();
    await expect(signInButton).toBeVisible({ timeout: 5000 });
    
    // Note: Actual login flow would require Clerk authentication setup
    // For now, we verify that anonymous UI is shown when not logged in
    
    // Create incognito context (simulating logged-out state)
    const incognitoContext = await browser.newContext();
    const incognitoPage = await incognitoContext.newPage();
    
    try {
      await incognitoPage.goto(`${BASE_URL}/memos/${TEST_MEMO_UID}`);
      await incognitoPage.waitForSelector('[data-testid="memo-content"], .memo-view, article', { timeout: 10000 });
      
      // Verify anonymous comment UI is visible in incognito
      const incognitoAnonymousUI = incognitoPage.locator('button:has-text("Write a comment"), input[id*="anonymous-name"]').first();
      await expect(incognitoAnonymousUI).toBeVisible({ timeout: 5000 });
    } finally {
      await incognitoContext.close();
    }
  });
});

