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

test('login password can be shown and hidden', async ({ page }) => {
  await page.goto('/login');
  const password = page.locator('#login-password');
  await password.fill('secret-password');
  await expect(password).toHaveAttribute('type', 'password');
  await page.getByRole('button', { name: 'نمایش رمز عبور' }).click();
  await expect(password).toHaveAttribute('type', 'text');
  await page.getByRole('button', { name: 'مخفی کردن رمز عبور' }).click();
  await expect(password).toHaveAttribute('type', 'password');
});

test('dashboard command surfaces and settings render without runtime errors', async ({ page }, testInfo) => {
  const runtimeErrors = [];
  page.on('pageerror', (error) => runtimeErrors.push(error.message));
  page.on('console', (message) => {
    if (message.type() === 'error') runtimeErrors.push(message.text());
  });

  const user = { id: 1, name: 'مدیر تست رابط', email: 'ui@example.test', permissions: ['reports.view', 'settings.view', 'notifications.view'] };
  await page.addInitScript(({ testUser }) => {
    localStorage.setItem('token', 'visual-smoke-token');
    localStorage.setItem('user', JSON.stringify(testUser));
  }, { testUser: user });
  await page.route('**/api/**', async (route) => {
    const url = new URL(route.request().url());
    const path = url.pathname;
    if (path === '/api/user') return route.fulfill({ json: { success: true, data: user } });
    if (path === '/api/dashboard/monitoring') return route.fulfill({ json: { success: true, data: {
      generated_at: new Date().toISOString(),
      summary: { active_projects: 4, projects_at_risk: 1, open_tasks: 18, overdue_tasks: 3, blocked_tasks: 2, active_sprints: 2, meetings_today: 3, overdue_action_items: 1, open_blockers: 2 },
      projects: [{ id: 1, title: 'پروژه نمونه رابط', status: 'in_progress', health: 'at_risk', progress: 62, total_tasks: 14, completed_tasks: 8, overdue_tasks: 2, blocked_tasks: 1 }],
      sprints: [{ id: 1, title: 'Sprint رابط', project: 'پروژه نمونه رابط', progress: 58, expected_progress: 65, remaining_days: 5, health: 'on_track', blocked_tasks: 0 }],
      workload: [{ id: 1, name: 'کاربر نمونه', open_tasks: 7, overdue_tasks: 1, load: 'high' }],
      attention: [],
      upcoming_meetings: [],
      trends: [{ month: '2026-06', created: 12, completed: 9 }, { month: '2026-07', created: 14, completed: 13 }],
    } } });
    if (path === '/api/reports/project-status') return route.fulfill({ json: { success: true, data: [
      { status: 'in_progress', label: 'in_progress', count: 3, value: 3 },
      { status: 'cancelled', label: 'cancelled', count: 1, value: 1 },
    ] } });
    if (path === '/api/reports/team-performance') return route.fulfill({ json: { success: true, data: [
      { name: 'عضو نمونه تیم', completed: 8, in_progress: 3, delayed: 1 },
    ] } });
    if (path === '/api/calendar/events') return route.fulfill({ json: { success: true, data: [] } });
    if (path === '/api/notifications') return route.fulfill({ json: { success: true, data: [], meta: { unread_count: 0, archived_count: 0 } } });
    if (path === '/api/settings') return route.fulfill({ json: { success: true, data: [
      { id: 1, key: 'working_days', value: ['saturday', 'sunday'], group: 'calendar', type: 'list' },
      { id: 2, key: 'default_meeting_reminder_minutes', value: 30, group: 'meeting', type: 'number' },
    ] } });
    if (path === '/api/branding') return route.fulfill({ json: { success: true, data: { company_name: 'شرکت آزمون', logo_path: null, logo_url: null } } });
    return route.fulfill({ json: { success: true, data: [] } });
  });

  await page.goto('/');
  await expect(page.getByText('مانیتورینگ عملیاتی')).toBeVisible();
  await expect(page.getByRole('cell', { name: '۱۴۰۵ خرداد', exact: true })).toBeVisible();
  await expect(page.getByText('2026-06')).toHaveCount(0);
  await expect(page.locator('img.sidebar-brand-mark')).toBeVisible();
  await page.getByRole('button', { name: 'جمع کردن منوی اصلی' }).click();
  await expect(page.locator('.main-content')).toHaveClass(/sidebar-collapsed/);
  await page.getByRole('button', { name: 'باز کردن منوی اصلی' }).click();
  await expect(page.locator('.main-content')).not.toHaveClass(/sidebar-collapsed/);

  await page.getByRole('button', { name: 'تقویم رویدادها' }).click();
  await expect(page.getByRole('region', { name: 'تقویم رویدادها' })).toBeVisible();
  await expect(page.getByText('برنامه روز')).toBeVisible();
  await page.keyboard.press('Escape');
  await expect(page.locator('.calendar-popover')).toBeHidden();

  await page.getByRole('button', { name: 'اعلان‌ها' }).click();
  await expect(page.getByLabel('مرکز اعلان‌ها')).toBeVisible();
  await expect(page.getByText(/برای آرشیو به راست/)).toBeVisible();
  await page.keyboard.press('Escape');
  await expect(page.locator('.notification-center')).toBeHidden();

  await page.getByRole('button', { name: 'باز کردن پروفایل کاربری' }).click();
  await expect(page.getByRole('dialog', { name: 'پروفایل کاربری' })).toBeVisible();
  await expect(page.getByRole('button', { name: 'ذخیره هویت' })).toBeVisible();
  await page.getByRole('tab', { name: 'اطلاعات کاری' }).click();
  await expect(page.getByRole('button', { name: 'ذخیره اطلاعات کاری' })).toBeVisible();
  const desktopModalMetrics = await page.getByRole('dialog', { name: 'پروفایل کاربری' }).evaluate((element) => {
    const body = element.querySelector('.modal-body');
    const styles = getComputedStyle(element);
    return {
      overflow: styles.overflowY,
      bodyOverflow: getComputedStyle(body).overflowY,
      radius: [styles.borderTopLeftRadius, styles.borderTopRightRadius, styles.borderBottomRightRadius, styles.borderBottomLeftRadius],
    };
  });
  expect(desktopModalMetrics.overflow).toBe('hidden');
  expect(desktopModalMetrics.bodyOverflow).toBe('hidden');
  expect(desktopModalMetrics.radius.every((value) => parseFloat(value) > 0)).toBe(true);
  await page.getByRole('button', { name: 'بستن', exact: true }).click();
  await expect(page.getByRole('dialog', { name: 'پروفایل کاربری' })).toBeHidden();

  await page.goto('/settings');
  await expect(page.getByRole('heading', { name: 'مرکز تنظیمات' })).toBeVisible();
  await expect(page.getByRole('heading', { name: 'شخصی‌سازی' })).toBeVisible();
  await expect(page.getByRole('button', { name: 'تنظیم جدید' })).toBeVisible();
  await expect(page.getByRole('button', { name: 'ساده' })).toHaveCount(0);
  await expect(page.getByRole('button', { name: 'پیشرفته' })).toHaveCount(0);
  await page.getByRole('button', { name: /تقویم و زمان کاری/ }).click();
  await expect(page.getByText('شنبه', { exact: true })).toBeVisible();
  await page.getByText('جزئیات فنی', { exact: true }).first().click();
  await expect(page.locator('.settings-technical-details').first().locator('input[readonly]')).toBeVisible();

  await page.screenshot({ path: testInfo.outputPath('settings-command-center.png'), fullPage: true });

  await page.goto('/reports');
  await expect(page.getByRole('heading', { name: 'جزئیات' })).toBeVisible();
  await expect(page.getByText('در حال انجام', { exact: true }).last()).toBeVisible();
  await expect(page.getByText('لغوشده', { exact: true }).last()).toBeVisible();
  await expect(page.getByText('in_progress', { exact: true })).toHaveCount(0);
  await page.getByRole('button', { name: 'عملکرد تیم' }).click();
  const teamNameTick = page.locator('.team-performance-chart text').filter({ hasText: 'عضو نمونه تیم' });
  await expect(teamNameTick).toBeVisible();
  const tickAndGrid = await page.locator('.team-performance-chart').evaluate((chart) => {
    const tick = [...chart.querySelectorAll('text')].find((node) => node.textContent.includes('عضو نمونه تیم'));
    const gridLine = chart.querySelector('.recharts-cartesian-grid line');
    return { tickRight: tick.getBoundingClientRect().right, gridLeft: gridLine.getBoundingClientRect().left };
  });
  expect(tickAndGrid.tickRight).toBeLessThanOrEqual(tickAndGrid.gridLeft + 1);

  await page.setViewportSize({ width: 390, height: 844 });
  await page.evaluate(() => localStorage.setItem('preferredAppMode', 'desktop'));
  await page.goto('/');
  await expect(page.getByText('مانیتورینگ عملیاتی')).toBeVisible();
  expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true);
  await page.getByRole('button', { name: 'باز کردن منوی اصلی' }).click();
  await expect(page.locator('.app-sidebar.mobile-open')).toBeVisible();
  await expect(page.locator('.app-sidebar.mobile-open').getByText('پروژه‌ها')).toBeVisible();
  await page.locator('.app-sidebar.mobile-open').getByRole('button', { name: 'بستن منوی اصلی' }).click();
  await expect(page.locator('.app-sidebar.mobile-open')).toHaveCount(0);
  await page.getByRole('button', { name: 'باز کردن پروفایل کاربری' }).click();
  await expect(page.getByRole('dialog', { name: 'پروفایل کاربری' })).toBeVisible();
  expect(await page.getByRole('dialog', { name: 'پروفایل کاربری' }).evaluate((element) => element.getBoundingClientRect().height <= window.innerHeight)).toBe(true);
  await page.getByRole('button', { name: 'بستن', exact: true }).click();
  await page.screenshot({ path: testInfo.outputPath('mobile-dashboard.png'), fullPage: true });

  expect(runtimeErrors).toEqual([]);
});

test('dark projects and task details keep readable centered surfaces', async ({ page }, testInfo) => {
  const user = { id: 1, name: 'مدیر رابط', email: 'manager@example.test' };
  const project = { id: 10, title: 'پروژه خوانا در تاریکی', description: 'شرح نمونه پروژه', status: 'in_progress', priority: 'high', progress: 45, project_manager: user, end_date: '2026-09-20' };
  const task = { id: 20, title: 'تسک مودال مرکزی', description: 'شرح تسک برای بررسی مودال', project_id: project.id, project, assignee: user, assignee_id: user.id, priority: 'medium', status: 'todo', start_date: '2026-09-01', due_date: '2026-09-10', estimated_time: 4 };

  await page.addInitScript(({ testUser }) => {
    localStorage.setItem('token', 'visual-details-token');
    localStorage.setItem('user', JSON.stringify(testUser));
    localStorage.setItem('theme', 'dark');
  }, { testUser: user });

  await page.route('**/api/**', async (route) => {
    const url = new URL(route.request().url());
    if (url.pathname === '/api/user') return route.fulfill({ json: { success: true, data: user } });
    if (url.pathname === '/api/projects' && route.request().method() === 'GET') return route.fulfill({ json: { success: true, data: [project], meta: { current_page: 1, last_page: 1 } } });
    if (url.pathname === '/api/tasks' && route.request().method() === 'GET') return route.fulfill({ json: { success: true, data: [task], meta: { current_page: 1, last_page: 1 } } });
    if (url.pathname === '/api/users') return route.fulfill({ json: { success: true, data: [user] } });
    if (url.pathname === '/api/departments') return route.fulfill({ json: { success: true, data: [], flat: [] } });
    if (url.pathname === `/api/tasks/${task.id}/checklists`) return route.fulfill({ json: { success: true, data: [] } });
    if (url.pathname === '/api/comments') return route.fulfill({ json: { success: true, data: [] } });
    if (url.pathname === '/api/notifications') return route.fulfill({ json: { success: true, data: [], meta: { unread_count: 0 } } });
    return route.fulfill({ json: { success: true, data: [] } });
  });

  await page.goto('/projects');
  const projectTitle = page.getByRole('link', { name: project.title });
  await expect(projectTitle).toBeVisible();
  expect(await projectTitle.evaluate((element) => getComputedStyle(element).color)).toBe('rgb(255, 255, 255)');

  await page.goto('/tasks');
  await page.getByRole('cell', { name: task.title, exact: true }).click();
  const dialog = page.getByRole('dialog', { name: task.title });
  await expect(dialog).toBeVisible();
  const metrics = await dialog.evaluate((element) => {
    const rect = element.getBoundingClientRect();
    const styles = getComputedStyle(element);
    return {
      centerOffsetX: Math.abs((rect.left + rect.width / 2) - window.innerWidth / 2),
      centerOffsetY: Math.abs((rect.top + rect.height / 2) - window.innerHeight / 2),
      radii: [styles.borderTopLeftRadius, styles.borderTopRightRadius, styles.borderBottomRightRadius, styles.borderBottomLeftRadius],
    };
  });
  expect(metrics.centerOffsetX).toBeLessThan(3);
  expect(metrics.centerOffsetY).toBeLessThan(3);
  expect(metrics.radii.every((radius) => parseFloat(radius) >= 18)).toBe(true);
  await page.screenshot({ path: testInfo.outputPath('dark-task-modal.png'), fullPage: true });
});

test('backlog conversion date pickers stay visible inside the modal flow', async ({ page }, testInfo) => {
  const user = { id: 1, name: 'مدیر بک‌لاگ', email: 'backlog@example.test' };
  const member = { id: 2, name: 'عضو پروژه', email: 'member@example.test', status: 'active' };
  const project = { id: 10, title: 'پروژه تقویم', project_manager: user, members: [member] };
  const backlog = {
    id: 30,
    title: 'بک‌لاگ قابل تبدیل',
    description: 'بررسی نمایش تقویم در مودال',
    type: 'feature',
    priority: 'medium',
    project_id: project.id,
    project,
    is_archived: false,
  };
  let conversionPayload;

  await page.addInitScript(({ testUser }) => {
    localStorage.setItem('token', 'backlog-date-token');
    localStorage.setItem('user', JSON.stringify(testUser));
  }, { testUser: user });

  await page.route('**/api/**', async (route) => {
    const url = new URL(route.request().url());
    const method = route.request().method();
    if (url.pathname === '/api/user') return route.fulfill({ json: { success: true, data: user } });
    if (url.pathname === '/api/backlog-items' && method === 'GET') return route.fulfill({ json: { success: true, data: [backlog] } });
    if (url.pathname === '/api/projects' && method === 'GET') return route.fulfill({ json: { success: true, data: [project] } });
    if (url.pathname === '/api/users' && method === 'GET') return route.fulfill({ json: { success: true, data: [user, member] } });
    if (url.pathname === `/api/projects/${project.id}` && method === 'GET') return route.fulfill({ json: { success: true, data: project } });
    if (url.pathname === `/api/backlog-items/${backlog.id}/convert-to-task` && method === 'POST') {
      conversionPayload = route.request().postDataJSON();
      return route.fulfill({ json: { success: true, data: { id: 99 } } });
    }
    if (url.pathname === '/api/notifications') return route.fulfill({ json: { success: true, data: [], meta: { unread_count: 0 } } });
    return route.fulfill({ json: { success: true, data: [] } });
  });

  const assertCalendarIsInViewport = async (calendar) => {
    await expect(calendar).toBeVisible();
    const metrics = await calendar.evaluate((element) => {
      const rect = element.getBoundingClientRect();
      const centerElement = document.elementFromPoint(rect.left + (rect.width / 2), rect.top + 12);
      return {
        top: rect.top,
        left: rect.left,
        right: rect.right,
        bottom: rect.bottom,
        viewportWidth: window.innerWidth,
        viewportHeight: window.innerHeight,
        isTopLayerHit: Boolean(centerElement?.closest('.persian-date-popover')),
      };
    });
    expect(metrics.top).toBeGreaterThanOrEqual(0);
    expect(metrics.left).toBeGreaterThanOrEqual(0);
    expect(metrics.right).toBeLessThanOrEqual(metrics.viewportWidth);
    expect(metrics.bottom).toBeLessThanOrEqual(metrics.viewportHeight);
    expect(metrics.isTopLayerHit).toBe(true);
  };

  await page.goto('/backlog');
  await page.getByRole('button', { name: `تبدیل ${backlog.title} به تسک` }).click();
  const conversionDialog = page.getByRole('dialog', { name: 'تبدیل بک‌لاگ به تسک' });
  await expect(conversionDialog).toBeVisible();
  await conversionDialog.locator('#task-assignee').selectOption(String(member.id));

  const startDateTrigger = conversionDialog.locator('.form-group').filter({ hasText: 'تاریخ شروع' }).locator('.persian-date-input');
  await startDateTrigger.click();
  const startCalendar = page.getByRole('dialog', { name: 'انتخاب تاریخ شمسی' });
  await assertCalendarIsInViewport(startCalendar);
  await page.keyboard.press('Escape');
  await expect(startCalendar).toBeHidden();
  await expect(conversionDialog).toBeVisible();
  await expect(startDateTrigger).toBeFocused();
  await startDateTrigger.click();
  await assertCalendarIsInViewport(startCalendar);
  await startCalendar.locator('button[aria-current="date"]').click();
  await expect(startDateTrigger).toHaveAttribute('aria-expanded', 'false');

  await page.setViewportSize({ width: 390, height: 700 });
  const dueDateTrigger = conversionDialog.locator('.form-group').filter({ hasText: 'تاریخ پایان' }).locator('.persian-date-input');
  await dueDateTrigger.click();
  const dueCalendar = page.getByRole('dialog', { name: 'انتخاب تاریخ شمسی' });
  await assertCalendarIsInViewport(dueCalendar);
  await page.screenshot({ path: testInfo.outputPath('mobile-backlog-date-picker.png'), fullPage: true });
  await dueCalendar.locator('button[aria-current="date"]').click();

  await conversionDialog.getByRole('button', { name: 'ایجاد و تخصیص تسک' }).click();
  await expect(conversionDialog).toBeHidden();
  expect(conversionPayload.assignee_id).toBe(String(member.id));
  expect(conversionPayload.start_date).toBeTruthy();
  expect(conversionPayload.due_date).toBe(conversionPayload.start_date);
});

test('kanban task cards show assignee photos and keep initials as fallback', async ({ page }) => {
  const user = { id: 1, name: 'مدیر کانبان', email: 'kanban@example.test' };
  const avatarDataUrl = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20"%3E%3Crect width="20" height="20" fill="%236366f1"/%3E%3C/svg%3E';
  const tasks = [
    {
      id: 71,
      title: 'تسک دارای عکس',
      status: 'todo',
      priority: 'medium',
      assignee: { id: 2, name: 'علی رضایی', avatar: 'avatars/ali.webp', avatar_url: avatarDataUrl },
      project: { id: 10, title: 'پروژه کانبان' },
    },
    {
      id: 72,
      title: 'تسک بدون عکس',
      status: 'in_progress',
      priority: 'low',
      assignee: { id: 3, name: 'بهار احمدی', avatar: null, avatar_url: null },
      project: { id: 10, title: 'پروژه کانبان' },
    },
  ];

  await page.addInitScript(({ testUser }) => {
    localStorage.setItem('token', 'kanban-avatar-token');
    localStorage.setItem('user', JSON.stringify(testUser));
  }, { testUser: user });

  await page.route('**/api/**', async (route) => {
    const path = new URL(route.request().url()).pathname;
    if (path === '/api/user') return route.fulfill({ json: { success: true, data: user } });
    if (path === '/api/tasks') return route.fulfill({ json: { success: true, data: tasks } });
    if (path === '/api/projects') return route.fulfill({ json: { success: true, data: [{ id: 10, title: 'پروژه کانبان' }] } });
    if (path === '/api/users') return route.fulfill({ json: { success: true, data: tasks.map((task) => task.assignee) } });
    if (path === '/api/branding') return route.fulfill({ json: { success: true, data: { company_name: 'مدیریت پروژه', logo_url: null } } });
    if (path === '/api/notifications') return route.fulfill({ json: { success: true, data: [], meta: { unread_count: 0 } } });
    return route.fulfill({ json: { success: true, data: [] } });
  });

  await page.goto('/kanban');
  const photoCard = page.locator('.kanban-task-card[data-task-id="71"]');
  const fallbackCard = page.locator('.kanban-task-card[data-task-id="72"]');

  await expect(photoCard.getByRole('img', { name: 'عکس پروفایل علی رضایی' })).toBeVisible();
  await expect(fallbackCard.locator('.kanban-assignee-avatar')).toHaveText('ب');
  await expect(fallbackCard.locator('.kanban-assignee-avatar img')).toHaveCount(0);
});

test('project task can be transferred to an approved project member', async ({ page }) => {
  const assignPermission = { id: 1, name: 'tasks.assign', display_name: 'تخصیص وظایف' };
  const user = {
    id: 1,
    name: 'مدیر پروژه',
    email: 'manager@example.test',
    roles: [{ id: 1, name: 'project_manager', permissions: [assignPermission] }],
  };
  const approvedMember = { id: 2, name: 'عضو تأییدشده', email: 'member@example.test', job_title: 'توسعه‌دهنده', status: 'active' };
  const project = {
    id: 10,
    title: 'پروژه انتقال تسک',
    description: 'پروژه تست',
    project_manager_id: user.id,
    project_manager: user,
    members: [approvedMember],
    status: 'in_progress',
    priority: 'high',
    progress: 30,
  };
  const task = {
    id: 50,
    title: 'تسک قابل انتقال',
    project_id: project.id,
    assignee_id: user.id,
    assignee: user,
    priority: 'medium',
    status: 'todo',
    due_date: '2026-09-10',
  };
  let assignmentPayload = null;

  await page.addInitScript(({ testUser }) => {
    localStorage.setItem('token', 'task-assignment-token');
    localStorage.setItem('user', JSON.stringify(testUser));
  }, { testUser: user });

  await page.route('**/api/**', async (route) => {
    const url = new URL(route.request().url());
    if (url.pathname === '/api/user') return route.fulfill({ json: { success: true, data: user } });
    if (url.pathname === `/api/projects/${project.id}`) return route.fulfill({ json: { success: true, data: project } });
    if (url.pathname === '/api/tasks' && route.request().method() === 'GET') return route.fulfill({ json: { success: true, data: [task] } });
    if (url.pathname === `/api/tasks/${task.id}/assignee` && route.request().method() === 'PUT') {
      assignmentPayload = route.request().postDataJSON();
      return route.fulfill({ json: { success: true, data: { ...task, assignee_id: approvedMember.id, assignee: approvedMember } } });
    }
    return route.fulfill({ json: { success: true, data: [] } });
  });

  await page.goto(`/projects/${project.id}`);
  await page.getByRole('button', { name: 'تسک‌ها', exact: true }).click();
  const assigneeSelect = page.getByLabel('انتقال مسئول تسک تسک قابل انتقال');
  await expect(assigneeSelect).toBeVisible();
  await assigneeSelect.selectOption(String(approvedMember.id));

  await expect.poll(() => assignmentPayload?.assignee_id).toBe(approvedMember.id);
  await expect(assigneeSelect).toHaveValue(String(approvedMember.id));
  await expect(page.getByText(/به عضو تأییدشده منتقل شد/)).toBeVisible();
});
