import { test, expect } from './msw-setup'
import type { StoredEvent } from '../src/composables/useEventStorage'

const STORAGE_KEY = 'fete:events'

const organizerEvent: StoredEvent = {
  eventToken: 'org-event-aaa',
  title: 'Summer BBQ',
  dateTime: '2027-06-15T18:00:00Z',
  organizerToken: 'org-secret-token',
}

const attendeeEvent: StoredEvent = {
  eventToken: 'att-event-bbb',
  title: 'Team Meeting',
  dateTime: '2027-01-10T09:00:00Z',
  rsvpToken: 'rsvp-token-1',
  rsvpName: 'Alice',
}

function seedEvents(events: StoredEvent[]): string {
  return `window.localStorage.setItem('${STORAGE_KEY}', ${JSON.stringify(JSON.stringify(events))})`
}

test.describe('US1: Organizer Cancels Event from List', () => {
  test('T001: organizer taps delete, confirms, event is removed after successful API call', async ({
    page,
    network,
  }) => {
    await page.addInitScript(seedEvents([organizerEvent, attendeeEvent]))

    const { http, HttpResponse } = await import('msw')
    let patchCalled = false
    network.use(
      http.patch('*/api/events/:token', ({ request, params }) => {
        const url = new URL(request.url)
        if (
          params['token'] === organizerEvent.eventToken &&
          url.searchParams.get('organizerToken') === organizerEvent.organizerToken
        ) {
          patchCalled = true
          return new HttpResponse(null, { status: 204 })
        }
        return HttpResponse.json(
          { type: 'about:blank', title: 'Forbidden', status: 403 },
          { status: 403, headers: { 'Content-Type': 'application/problem+json' } },
        )
      }),
    )

    await page.goto('/')
    await expect(page.getByText('Summer BBQ')).toBeVisible()

    // Click delete on organizer event
    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()

    // Confirmation dialog appears with organizer-specific text
    await expect(page.getByRole('alertdialog')).toBeVisible()

    // Confirm cancellation
    await page.getByRole('button', { name: 'Remove', exact: true }).click()

    // Event is removed from list
    await expect(page.getByText('Summer BBQ')).not.toBeVisible()
    // Other event remains
    await expect(page.getByText('Team Meeting')).toBeVisible()

    expect(patchCalled).toBe(true)
  })

  test('T002: organizer confirms cancellation, API fails, event stays in list and error shown', async ({
    page,
    network,
  }) => {
    await page.addInitScript(seedEvents([organizerEvent]))

    const { http, HttpResponse } = await import('msw')
    network.use(
      http.patch('*/api/events/:token', () => {
        return HttpResponse.json(
          {
            type: 'about:blank',
            title: 'Internal Server Error',
            status: 500,
          },
          { status: 500, headers: { 'Content-Type': 'application/problem+json' } },
        )
      }),
    )

    await page.goto('/')
    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()
    await expect(page.getByRole('alertdialog')).toBeVisible()

    await page.getByRole('button', { name: 'Remove', exact: true }).click()

    // Event stays in list
    await expect(page.getByText('Summer BBQ')).toBeVisible()
  })

  test('T003: organizer confirms cancellation, API returns 409 Conflict, event is silently removed', async ({
    page,
    network,
  }) => {
    await page.addInitScript(seedEvents([organizerEvent]))

    const { http, HttpResponse } = await import('msw')
    network.use(
      http.patch('*/api/events/:token', () => {
        return HttpResponse.json(
          {
            type: 'about:blank',
            title: 'Conflict',
            status: 409,
            detail: 'Event is already cancelled.',
          },
          { status: 409, headers: { 'Content-Type': 'application/problem+json' } },
        )
      }),
    )

    await page.goto('/')
    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()
    await expect(page.getByRole('alertdialog')).toBeVisible()

    await page.getByRole('button', { name: 'Remove', exact: true }).click()

    // 409 treated as success — event removed
    await expect(page.getByText('Summer BBQ')).not.toBeVisible()
  })

  test('T004: organizer opens cancel dialog then dismisses (cancel button), event remains', async ({
    page,
  }) => {
    await page.addInitScript(seedEvents([organizerEvent]))
    await page.goto('/')

    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()
    await expect(page.getByRole('alertdialog')).toBeVisible()

    // Dismiss via Cancel button
    await page.getByRole('button', { name: 'Cancel' }).click()

    await expect(page.getByRole('alertdialog')).not.toBeVisible()
    await expect(page.getByText('Summer BBQ')).toBeVisible()
  })

  test('T004b: organizer opens cancel dialog then dismisses via Escape', async ({ page }) => {
    await page.addInitScript(seedEvents([organizerEvent]))
    await page.goto('/')

    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()
    await expect(page.getByRole('alertdialog')).toBeVisible()

    await page.keyboard.press('Escape')

    await expect(page.getByRole('alertdialog')).not.toBeVisible()
    await expect(page.getByText('Summer BBQ')).toBeVisible()
  })

  test('T004c: organizer opens cancel dialog then dismisses via overlay click', async ({
    page,
  }) => {
    await page.addInitScript(seedEvents([organizerEvent]))
    await page.goto('/')

    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()
    await expect(page.getByRole('alertdialog')).toBeVisible()

    // Click on overlay (outside dialog)
    await page.locator('.confirm-dialog__overlay').click({ position: { x: 10, y: 10 } })

    await expect(page.getByRole('alertdialog')).not.toBeVisible()
    await expect(page.getByText('Summer BBQ')).toBeVisible()
  })
})

test.describe('US2: Distinct Dialog for Organizer vs. Attendee', () => {
  test('T011: organizer dialog shows event-cancellation warning', async ({ page }) => {
    await page.addInitScript(seedEvents([organizerEvent]))
    await page.goto('/')

    await page.getByRole('button', { name: /Remove Summer BBQ/ }).click()
    const dialog = page.getByRole('alertdialog')
    await expect(dialog).toBeVisible()

    // Organizer-specific title and message
    await expect(dialog.locator('.confirm-dialog__title')).toHaveText('Cancel event?')
    await expect(dialog.locator('.confirm-dialog__message')).toContainText(
      'all attendees',
    )
  })

  test('T012: attendee dialog preserves existing RSVP-cancellation message', async ({
    page,
  }) => {
    await page.addInitScript(seedEvents([attendeeEvent]))
    await page.goto('/')

    await page.getByRole('button', { name: /Remove Team Meeting/ }).click()
    const dialog = page.getByRole('alertdialog')
    await expect(dialog).toBeVisible()

    // Attendee-specific title and message
    await expect(dialog.locator('.confirm-dialog__title')).toHaveText('Remove event?')
    await expect(dialog.locator('.confirm-dialog__message')).toContainText(
      'attendance will be cancelled',
    )
  })
})
