import { expect, test, type Page, type Route } from '@playwright/test';

const adminAuth = {
  authenticated: true,
  csrfToken: 'test-csrf',
  user: { id: 1, email: 'admin@learnitive.test', displayName: 'CMS Admin', avatarUrl: null, role: 'admin', status: 'active' },
  entitlement: { tier: 'pro', pro: true, blocked: false, quota: 1000, usage: 0, remaining: 1000 },
} as const;

const document = {
  schemaVersion: 1,
  time: 1,
  blocks: [
    { id: 'intro', type: 'paragraph', data: { text: 'Interactive CMS paragraph' } },
    { id: 'run-me', type: 'code', data: { language: 'python', projectModeId: 'python', filename: 'main.py', code: 'print("hello")', stdin: '', allowStdin: false, runnable: true, lineNumbers: true } },
  ],
};

function json(route: Route, status: number, body: unknown) {
  return route.fulfill({ status, contentType: 'application/json', body: JSON.stringify(body) });
}

async function mockAdminCms(page: Page) {
  await page.route('**/api/**', async (route) => {
    const request = route.request();
    const url = new URL(request.url());
    if (url.pathname === '/api/config/public') return json(route, 200, { saasEnabled: true, googleAuthEnabled: true, githubAuthEnabled: true, magicEmailEnabled: false, contactEnabled: false, shopUrl: '' });
    if (url.pathname === '/api/auth/me') return json(route, 200, adminAuth);
    if (url.pathname === '/api/user/settings' && request.method() === 'GET') return json(route, 200, { settings: {} });
    if (url.pathname === '/api/admin/blog' && request.method() === 'GET') return json(route, 200, { items: [{ id: 41, slug: 'interactive-post', title: 'Interactive post', excerpt: 'Example', status: 'published', updated_at: '2026-09-10T00:00:00.000Z' }] });
    if (url.pathname === '/api/admin/blog/41' && request.method() === 'GET') return json(route, 200, { item: { id: 41, slug: 'interactive-post', title: 'Interactive post', excerpt: 'Example', status: 'published', tags: ['interactive'], content_format: 'blocks', content_document: document, edit_version: 3, migration_warnings: [] } });
    if (url.pathname === '/api/admin/cms/preview' && request.method() === 'POST') return json(route, 200, { contentHtml: '<p>Interactive CMS paragraph</p>', contentDocument: document });
    if (url.pathname === '/api/admin/cms/preview/runtime' && request.method() === 'POST') return json(route, 200, { result: { status: 'ok', exitCode: 0, stdout: 'hello\n', stderr: '' } });
    if (url.pathname === '/api/admin/blog/41' && request.method() === 'PATCH') return json(route, 200, { item: { id: 41, editVersion: 4 } });
    return json(route, 404, { error: 'not_mocked' });
  });
}

test('Blog admin is list-only and Edit opens a dedicated interactive builder with Preview', async ({ page }) => {
  await mockAdminCms(page);
  await page.goto('/admin/blog');

  await expect(page.getByRole('heading', { level: 1, name: 'Blog CMS' })).toBeVisible();
  await expect(page.getByText('Interactive post', { exact: true })).toBeVisible();
  await expect(page.locator('.interactive-content-editorjs-shell')).toHaveCount(0);

  await page.getByRole('link', { name: 'Edit' }).click();
  await expect(page).toHaveURL(/\/admin\/blog\/41\/edit$/u);
  await expect(page.getByRole('heading', { level: 1, name: 'Edit post' })).toBeVisible();
  await expect(page.getByRole('heading', { name: 'Content builder' })).toBeVisible();
  await expect(page.locator('.interactive-content-editorjs-shell')).toBeVisible();

  await page.getByRole('button', { name: 'Preview' }).first().click();
  const preview = page.getByRole('dialog').filter({ hasText: 'Draft preview' });
  await expect(preview).toBeVisible();
  await expect(preview.getByText('Interactive CMS paragraph')).toBeVisible();
  await preview.getByRole('button', { name: 'Run' }).click();
  await expect(preview.getByText('hello')).toBeVisible();
});

async function mockAnonymousDocs(page: Page) {
  await page.route('**/api/**', async (route) => {
    const request = route.request();
    const url = new URL(request.url());
    if (url.pathname === '/api/config/public') return json(route, 200, { saasEnabled: true, googleAuthEnabled: true, githubAuthEnabled: true, magicEmailEnabled: false, contactEnabled: false, shopUrl: '', freePlanProjectLimit: 5 });
    if (url.pathname === '/api/auth/me') return json(route, 200, { authenticated: false });
    if (url.pathname === '/api/docs') return json(route, 200, { items: [{ id: 42, slug: 'interactive-doc', title: 'Interactive doc', category: 'Getting Started', status: 'published', excerpt: '', tags: [] }] });
    if (url.pathname === '/api/docs/interactive-doc') return json(route, 200, { item: { id: 42, slug: 'interactive-doc', title: 'Interactive doc', category: 'Getting Started', status: 'published', excerpt: '', tags: [], content_format: 'blocks', content_document: document, content_html: '<p>fallback</p>', previous: null, next: null } });
    return json(route, 404, { error: 'not_mocked' });
  });
}

test('public structured Docs stay readable anonymously and gate only execution with return-to-page auth', async ({ page }) => {
  await mockAnonymousDocs(page);
  await page.goto('/docs/interactive-doc?from=e2e#run');

  await expect(page.getByRole('heading', { level: 1, name: 'Interactive doc' })).toBeVisible();
  await expect(page.getByText('Interactive CMS paragraph')).toBeVisible();
  await expect(page.getByRole('button', { name: 'Run' })).toBeVisible();

  await page.getByRole('button', { name: 'Run' }).click();
  const dialog = page.getByRole('dialog').filter({ hasText: 'Sign in' });
  await expect(dialog).toBeVisible();
  const returnTo = '/docs/interactive-doc?from=e2e#block-run-me';
  await expect(page).toHaveURL(/#block-run-me$/u);
  await expect(dialog.getByRole('link', { name: 'Continue with Google' })).toHaveAttribute('href', `/api/auth/google?returnTo=${encodeURIComponent(returnTo)}`);
  await expect(dialog.getByRole('link', { name: 'Continue with GitHub' })).toHaveAttribute('href', `/api/auth/github?returnTo=${encodeURIComponent(returnTo)}`);
});
