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

const REQUESTS_HAR = 'e2e/settings/requests/api-settings.har'
const REQUESTS_HAR2 = 'e2e/settings/requests/api-settings2.har'
const REQUESTS_HAR3 = 'e2e/settings/requests/api-settings3.har'

test('should post settings on save', async ({ page }) => {
  await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
  await page.goto('/settings')
  await page.getByLabel('Use system setting').click()
  await page.getByRole('button', { name: 'Save' }).scrollIntoViewIfNeeded()
  const updatePromise = page.waitForRequest((request) => {
    const data = request.postDataJSON()
    const isValid = data['settings'] != null
    return (
      isValid &&
      request.method() === 'POST' &&
      request.url().includes('/api/ui_settings/')
    )
  })
  await page.getByRole('button', { name: 'Save' }).click()
  await updatePromise
})

test('should activate / deactivate save button when settings change', async ({
  page,
}) => {
  await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
  await page.goto('/settings')
  await expect(page.getByRole('button', { name: 'Save' })).toBeDisabled()
  await page.getByLabel('Use system setting').click()
  await page.getByRole('button', { name: 'Save' }).scrollIntoViewIfNeeded()
  await expect(page.getByRole('button', { name: 'Save' })).toBeEnabled()
})

test('should warn on unsaved changes', async ({ page }) => {
  await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
  await page.goto('/settings')
  await page.getByLabel('Use system setting').click()
  await page.getByRole('link', { name: 'Dashboard' }).click()
  await expect(page.getByRole('dialog')).toHaveText(/unsaved changes/)
  await page.getByRole('button', { name: 'Cancel' }).click()
  await page.getByLabel('Use system setting').click()
  await page.getByRole('link', { name: 'Dashboard' }).click()
  await expect(page.getByRole('dialog')).toHaveCount(0)
})

test('should apply appearance changes when set', async ({ page }) => {
  await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
  await page.goto('/settings')
  await expect(page.locator('body')).toHaveClass(/color-scheme-system/)
  await page.getByLabel('Use system setting').click()
  await page.getByLabel('Enable dark mode').click()
  await expect(page.locator('body')).toHaveClass(/color-scheme-dark/)
})

test('should toggle saved view options when set & saved', async ({ page }) => {
  await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
  await page.goto('/settings/savedviews')
  await page.getByLabel('Show on dashboard').first().click()
  await page.getByLabel('Show in sidebar').first().click()
  const updatePromise = page.waitForRequest((request) => {
    if (!request.url().includes('8')) return true // skip other saved views
    const data = request.postDataJSON()
    const isValid =
      data['show_on_dashboard'] === true && data['show_in_sidebar'] === true
    return (
      isValid &&
      request.method() === 'PATCH' &&
      request.url().includes('/api/saved_views/')
    )
  })
  await page.getByRole('button', { name: 'Save' }).scrollIntoViewIfNeeded()
  await page.getByRole('button', { name: 'Save' }).click()
  await updatePromise
})

test('should support tab direct navigation', async ({ page }) => {
  await page.routeFromHAR(REQUESTS_HAR, { notFound: 'fallback' })
  await page.goto('/settings/general')
  await expect(page.getByRole('tab', { name: 'General' })).toHaveAttribute(
    'aria-selected',
    'true'
  )
  await page.goto('/settings/notifications')
  await expect(
    page.getByRole('tab', { name: 'Notifications' })
  ).toHaveAttribute('aria-selected', 'true')
  await page.goto('/settings/savedviews')
  await expect(page.getByRole('tab', { name: 'Saved Views' })).toHaveAttribute(
    'aria-selected',
    'true'
  )
  await page.goto('/settings/mail')
  await expect(page.getByRole('tab', { name: 'Mail' })).toHaveAttribute(
    'aria-selected',
    'true'
  )
  await page.goto('/settings/usersgroups')
  await expect(
    page.getByRole('tab', { name: 'Users & Groups' })
  ).toHaveAttribute('aria-selected', 'true')
})

test('should show a list of mail accounts & support creation', async ({
  page,
}) => {
  await page.routeFromHAR(REQUESTS_HAR2, { notFound: 'fallback' })
  await page.goto('/settings/mail')
  await expect(
    page.getByRole('listitem').filter({ hasText: 'imap.gmail.com' })
  ).toHaveCount(1)
  await expect(
    page.getByRole('listitem').filter({ hasText: 'imap.domain.com' })
  ).toHaveCount(1)
  await page.getByRole('button', { name: /Add Account/ }).click()
  await expect(page.getByRole('dialog')).toHaveCount(1)
  await page.getByLabel('Name', { exact: true }).fill('Test Account')
  await page.getByLabel('IMAP Server', { exact: true }).fill('imap.server.com')
  await page.getByLabel('IMAP Port', { exact: true }).fill('993')
  await page.getByLabel('Username', { exact: true }).fill('username')
  await page.getByLabel('Password', { exact: true }).fill('password')
  const createPromise = page.waitForRequest((request) => {
    const data = request.postDataJSON()
    const isValid = data['imap_server'] === 'imap.server.com'
    return (
      isValid &&
      request.method() === 'POST' &&
      request.url().includes('/api/mail_accounts/')
    )
  })
  await page.getByRole('button', { name: 'Save' }).click()
  await createPromise
})

test('should show a list of mail rules & support creation', async ({
  page,
}) => {
  await page.routeFromHAR(REQUESTS_HAR3, { notFound: 'fallback' })
  await page.goto('/settings/mail')
  await expect(
    page.getByRole('listitem').filter({ hasText: 'domain' })
  ).toHaveCount(2)
  await expect(
    page.getByRole('listitem').filter({ hasText: 'gmail' })
  ).toHaveCount(2)
  await page.getByRole('button', { name: /Add Rule/ }).click()
  await expect(page.getByRole('dialog')).toHaveCount(1)
  await page.getByLabel('Name', { exact: true }).fill('Test Rule')
  await page.getByTitle('Account').locator('span').first().click()
  await page.getByRole('option', { name: 'gmail' }).click()
  await page.getByLabel('Maximum age (days)').fill('0')
  const createPromise = page.waitForRequest((request) => {
    const data = request.postDataJSON()
    const isValid = data['name'] === 'Test Rule'
    return (
      isValid &&
      request.method() === 'POST' &&
      request.url().includes('/api/mail_rules/')
    )
  })
  await page.getByRole('button', { name: 'Save' }).scrollIntoViewIfNeeded()
  await page.getByRole('button', { name: 'Save' }).click()
  await createPromise
})