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

/**
 * E2E test helpers for LeoCRM.
 *
 * These helpers provide login automation, API mocking, and common
 * fixtures used across all spec files. Since the container has no
 * PostgreSQL/Redis, API calls are intercepted with mock responses.
 */

// ── Test credentials ──
export const TEST_USER = {
  email: 'admin@leocrm.test',
  password: 'TestPass123!',
  firstName: 'Admin',
  lastName: 'User',
  id: 'user-001',
  role: 'system_admin',
};

export const TEST_TENANT = {
  id: 'tenant-001',
  name: 'Test Tenant',
  slug: 'test-tenant',
};

// ── Mock data ──
export const MOCK_CONTACTS = {
  items: [
    {
      id: 'contact-001',
      type: 'company' as const,
      name: 'TechCorp GmbH',
      displayname: 'TechCorp GmbH',
      code: 'K-00123',
      email_1: 'info@techcorp.test',
      phone_1: '+49 30 12345678',
      mailing_city: 'Berlin',
      mailing_postalcode: '10115',
      mailing_street: 'Hauptstrasse',
      mailing_number: '1',
      tags: 'kunde, premium',
      contact_persons: [],
    },
    {
      id: 'contact-002',
      type: 'person' as const,
      firstname: 'Max',
      surname: 'Mustermann',
      displayname: 'Max Mustermann',
      email_1: 'max@mustermann.test',
      phone_1: '+49 170 9876543',
      contact_persons: [],
    },
  ],
  total: 2,
};

export const MOCK_MAIL_ACCOUNTS = [
  {
    id: 'acc-001',
    email: 'test@leocrm.test',
    display_name: 'Test Account',
    imap_host: 'imap.test.test',
    imap_port: 993,
    smtp_host: 'smtp.test.test',
    smtp_port: 587,
    is_shared: false,
  },
];

export const MOCK_MAIL_FOLDERS = [
  { id: 'folder-001', name: 'INBOX', unread_count: 3, account_id: 'acc-001' },
  { id: 'folder-002', name: 'Sent', unread_count: 0, account_id: 'acc-001' },
  { id: 'folder-003', name: 'Drafts', unread_count: 0, account_id: 'acc-001' },
];

export const MOCK_MAILS = [
  {
    id: 'mail-001',
    subject: 'Welcome to LeoCRM',
    from: 'noreply@leocrm.test',
    to: 'test@leocrm.test',
    date: '2026-07-23T10:00:00Z',
    body_text: 'Welcome to LeoCRM! Your account is ready.',
    is_read: false,
    flags: [],
    attachments: [],
  },
  {
    id: 'mail-002',
    subject: 'Meeting Tomorrow',
    from: 'boss@leocrm.test',
    to: 'test@leocrm.test',
    date: '2026-07-23T09:00:00Z',
    body_text: 'Don\'t forget the meeting tomorrow at 10 AM.',
    is_read: true,
    flags: [],
    attachments: [],
  },
];

export const MOCK_DMS_FOLDERS = [
  { id: 'folder-001', name: 'Documents', parent_id: null },
  { id: 'folder-002', name: 'Images', parent_id: null },
  { id: 'folder-003', name: 'Contracts', parent_id: 'folder-001' },
];

export const MOCK_DMS_FILES = [
  {
    id: 'file-001',
    name: 'contract.pdf',
    folder_id: 'folder-001',
    size: 102400,
    mime_type: 'application/pdf',
    created_at: '2026-07-23T10:00:00Z',
    updated_at: '2026-07-23T10:00:00Z',
  },
  {
    id: 'file-002',
    name: 'photo.jpg',
    folder_id: 'folder-002',
    size: 204800,
    mime_type: 'image/jpeg',
    created_at: '2026-07-23T11:00:00Z',
    updated_at: '2026-07-23T11:00:00Z',
  },
];

export const MOCK_CALENDARS = [
  { id: 'cal-001', name: 'Personal', color: '#3b82f6' },
  { id: 'cal-002', name: 'Work', color: '#10b981' },
];

export const MOCK_CALENDAR_ENTRIES = [
  {
    id: 'entry-001',
    calendar_id: 'cal-001',
    entry_type: 'appointment',
    title: 'Team Meeting',
    description: 'Weekly team sync',
    start_at: '2026-07-24T09:00:00Z',
    end_at: '2026-07-24T10:00:00Z',
    all_day: false,
    priority: 'medium',
    status: 'open',
    subtype: 'normal',
  },
];

export const MOCK_PLUGINS = [
  {
    name: 'tags',
    display_name: 'Tags',
    description: 'Tag management plugin',
    version: '1.0.0',
    active: true,
    installed: true,
    status: 'active',
  },
  {
    name: 'entity_links',
    display_name: 'Entity Links',
    description: 'Link entities together',
    version: '1.0.0',
    active: false,
    installed: true,
    status: 'inactive',
  },
];

export const MOCK_SEARCH_RESULTS = {
  contact: [
    { id: 'contact-001', type: 'contact', title: 'TechCorp GmbH', snippet: 'Company in Berlin' },
  ],
  company: [],
  mail: [
    { id: 'mail-001', type: 'mail', title: 'Welcome to LeoCRM', snippet: 'Welcome email' },
  ],
  file: [],
  event: [],
};

// ── API mock setup ──

/**
 * Intercept all API calls with mock responses.
 * Call this in beforeEach to set up a fully mocked environment.
 */
export async function setupApiMocks(page: Page) {
  // Auth: login
  await page.route('**/api/v1/auth/login', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        user: {
          id: TEST_USER.id,
          email: TEST_USER.email,
          first_name: TEST_USER.firstName,
          last_name: TEST_USER.lastName,
          role: TEST_USER.role,
          tenants: [TEST_TENANT],
          permissions: ['*'],
          is_system_admin: true,
        },
        csrf_token: 'mock-csrf-token',
      }),
    });
  });

  // Auth: me (current user)
  await page.route('**/api/v1/auth/me', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        id: TEST_USER.id,
        email: TEST_USER.email,
        first_name: TEST_USER.firstName,
        last_name: TEST_USER.lastName,
        role: TEST_USER.role,
        tenants: [TEST_TENANT],
        permissions: ['*'],
        is_system_admin: true,
      }),
    });
  });

  // Auth: logout
  await page.route('**/api/v1/auth/logout', (route) => {
    route.fulfill({ status: 200, contentType: 'application/json', body: '{}' });
  });

  // Contacts list
  await page.route('**/api/v1/contacts*', (route) => {
    const url = route.request().url();
    if (url.includes('/contact_persons')) {
      route.fulfill({ status: 200, contentType: 'application/json', body: '[]' });
      return;
    }
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_CONTACTS),
      });
    } else if (route.request().method() === 'POST') {
      const body = route.request().postDataJSON();
      route.fulfill({
        status: 201,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 'contact-new',
          contact_persons: [],
          displayname: body?.name || `${body?.firstname || ''} ${body?.surname || ''}`.trim(),
          ...body,
        }),
      });
    } else {
      route.fulfill({ status: 200, contentType: 'application/json', body: '{}' });
    }
  });

  // Contact detail
  await page.route('**/api/v1/contacts/*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_CONTACTS.items[0]),
      });
    } else if (route.request().method() === 'PUT') {
      const body = route.request().postDataJSON();
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ ...MOCK_CONTACTS.items[0], ...body }),
      });
    } else if (route.request().method() === 'DELETE') {
      route.fulfill({ status: 204, body: '' });
    } else {
      route.continue();
    }
  });

  // Mail accounts
  await page.route('**/api/v1/mail/accounts*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_MAIL_ACCOUNTS),
      });
    } else if (route.request().method() === 'POST') {
      const body = route.request().postDataJSON();
      route.fulfill({
        status: 201,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 'acc-new',
          display_name: body?.display_name || body?.email,
          ...body,
        }),
      });
    } else {
      route.continue();
    }
  });

  // Mail folders
  await page.route('**/api/v1/mail/accounts/*/folders*', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify(MOCK_MAIL_FOLDERS),
    });
  });

  // Mail list
  await page.route('**/api/v1/mail/accounts/*/mails*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ items: MOCK_MAILS, total: MOCK_MAILS.length }),
      });
    } else {
      route.continue();
    }
  });

  // Mail detail
  await page.route('**/api/v1/mail/*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_MAILS[0]),
      });
    } else {
      route.continue();
    }
  });

  // DMS folders
  await page.route('**/api/v1/dms/folders*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_DMS_FOLDERS),
      });
    } else if (route.request().method() === 'POST') {
      const body = route.request().postDataJSON();
      route.fulfill({
        status: 201,
        contentType: 'application/json',
        body: JSON.stringify({ id: 'folder-new', name: body?.name, parent_id: body?.parent_id ?? null }),
      });
    } else {
      route.continue();
    }
  });

  // DMS files
  await page.route('**/api/v1/dms/files*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_DMS_FILES),
      });
    } else {
      route.continue();
    }
  });

  // DMS shared files
  await page.route('**/api/v1/dms/shared*', (route) => {
    route.fulfill({ status: 200, contentType: 'application/json', body: '[]' });
  });

  // Calendar list
  await page.route('**/api/v1/calendar/calendars*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_CALENDARS),
      });
    } else {
      route.continue();
    }
  });

  // Calendar entries
  await page.route('**/api/v1/calendar/entries*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_CALENDAR_ENTRIES),
    });
    } else if (route.request().method() === 'POST') {
      const body = route.request().postDataJSON();
      route.fulfill({
        status: 201,
        contentType: 'application/json',
        body: JSON.stringify({ id: 'entry-new', ...body }),
      });
    } else {
      route.continue();
    }
  });

  // Calendar kanban
  await page.route('**/api/v1/calendar/kanban*', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        open: MOCK_CALENDAR_ENTRIES,
        in_progress: [],
        done: [],
        cancelled: [],
      }),
    });
  });

  // Plugins
  await page.route('**/api/v1/plugins*', (route) => {
    if (route.request().method() === 'GET') {
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify(MOCK_PLUGINS),
      });
    } else if (route.request().method() === 'POST') {
      route.fulfill({ status: 200, contentType: 'application/json', body: '{}' });
    } else {
      route.continue();
    }
  });

  // Plugin activate/deactivate
  await page.route('**/api/v1/plugins/*/activate', (route) => {
    route.fulfill({ status: 200, contentType: 'application/json', body: '{}' });
  });
  await page.route('**/api/v1/plugins/*/deactivate', (route) => {
    route.fulfill({ status: 200, contentType: 'application/json', body: '{}' });
  });

  // Search
  await page.route('**/api/v1/search*', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify(MOCK_SEARCH_RESULTS),
    });
  });

  // User preferences
  await page.route('**/api/v1/user/preferences*', (route) => {
    route.fulfill({ status: 200, contentType: 'application/json', body: '{}' });
  });

  // Generic catch-all for other API endpoints
  await page.route('**/api/v1/**', (route) => {
    if (!route.request().url().includes('/auth/') &&
        !route.request().url().includes('/contacts') &&
        !route.request().url().includes('/mail/') &&
        !route.request().url().includes('/dms/') &&
        !route.request().url().includes('/calendar/') &&
        !route.request().url().includes('/plugins') &&
        !route.request().url().includes('/search')) {
      route.fulfill({ status: 200, contentType: 'application/json', body: '[]' });
    } else {
      route.continue();
    }
  });
}

/**
 * Perform login via the login form.
 * Assumes API mocks are already set up.
 */
export async function login(page: Page) {
  await page.goto('/login');
  await expect(page.locator('[data-testid="login-page"]')).toBeVisible();

  // Fill email and password using label-based selectors
  await page.locator('input[type="email"]').fill(TEST_USER.email);
  await page.locator('input[type="password"]').fill(TEST_USER.password);

  // Submit the form
  await page.locator('button[type="submit"]').click();

  // Wait for redirect to dashboard
  await page.waitForURL('**/dashboard', { timeout: 10_000 });
  await expect(page.locator('[data-testid="topbar"]')).toBeVisible();
}

/**
 * Perform logout via the user menu.
 */
export async function logout(page: Page) {
  // Open user menu
  await page.locator('[data-testid="topbar"] button[aria-haspopup="menu"]').click();
  // Click logout button (text-based since no data-testid on logout button)
  await page.locator('[role="menuitem"]').filter({ hasText: /logout|abmelden/i }).click();
  await page.waitForURL('**/login', { timeout: 10_000 });
}

/**
 * Navigate to a specific route after login.
 */
export async function navigateTo(page: Page, path: string) {
  await page.goto(path);
  await page.waitForLoadState('networkidle');
}
