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

const STORAGE_KEY = 'fete:events'

const fullEvent = {
  eventToken: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
  title: 'Summer BBQ',
  description: 'Bring your own drinks!',
  dateTime: '2026-03-15T20:00:00+01:00',
  timezone: 'Europe/Berlin',
  location: 'Central Park, NYC',
  attendeeCount: 12,
  cancelled: false,
  cancellationReason: null,
}

const organizerToken = '550e8400-e29b-41d4-a716-446655440001'

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

function organizerSeed(): StoredEvent {
  return {
    eventToken: fullEvent.eventToken,
    organizerToken,
    title: fullEvent.title,
    dateTime: fullEvent.dateTime,
  }
}

test.describe('US1: Organizer cancels event with reason', () => {
  test('organizer opens cancel bottom sheet, enters reason, confirms — event shows as cancelled on reload', async ({
    page,
    network,
  }) => {
    let cancelled = false
    network.use(
      http.get('*/api/events/:token', () => {
        if (cancelled) {
          return HttpResponse.json({
            ...fullEvent,
            cancelled: true,
            cancellationReason: 'Venue closed',
          })
        }
        return HttpResponse.json(fullEvent)
      }),
      http.patch('*/api/events/:token', ({ request }) => {
        const url = new URL(request.url)
        const token = url.searchParams.get('organizerToken')
        if (token === organizerToken) {
          cancelled = true
          return new HttpResponse(null, { status: 204 })
        }
        return HttpResponse.json(
          { type: 'urn:problem-type:invalid-organizer-token', title: 'Forbidden', status: 403 },
          { status: 403 },
        )
      }),
    )
    await page.addInitScript(seedEvents([organizerSeed()]))
    await page.goto(`/events/${fullEvent.eventToken}`)

    // Open kebab menu, then cancel event
    const kebabBtn = page.getByRole('button', { name: /Event actions/i })
    await expect(kebabBtn).toBeVisible()
    await kebabBtn.click()

    const cancelItem = page.getByRole('menuitem', { name: /Cancel event/i })
    await expect(cancelItem).toBeVisible()
    await cancelItem.click()

    // Fill in reason
    const reasonField = page.getByLabel(/reason/i)
    await expect(reasonField).toBeVisible()
    await reasonField.fill('Venue closed')

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

    // Event should show as cancelled
    await expect(page.getByText(/This event has been cancelled/i)).toBeVisible()
    await expect(page.getByText('Venue closed')).toBeVisible()

    // Kebab menu should be gone (event is cancelled)
    await expect(kebabBtn).not.toBeVisible()
  })
})

test.describe('US1: Organizer cancels event without reason', () => {
  test('organizer cancels without reason — event shows as cancelled', async ({
    page,
    network,
  }) => {
    let cancelled = false
    network.use(
      http.get('*/api/events/:token', () => {
        if (cancelled) {
          return HttpResponse.json({
            ...fullEvent,
            cancelled: true,
            cancellationReason: null,
          })
        }
        return HttpResponse.json(fullEvent)
      }),
      http.patch('*/api/events/:token', ({ request }) => {
        const url = new URL(request.url)
        const token = url.searchParams.get('organizerToken')
        if (token === organizerToken) {
          cancelled = true
          return new HttpResponse(null, { status: 204 })
        }
        return HttpResponse.json({}, { status: 403 })
      }),
    )
    await page.addInitScript(seedEvents([organizerSeed()]))
    await page.goto(`/events/${fullEvent.eventToken}`)

    await page.getByRole('button', { name: /Event actions/i }).click()
    await page.getByRole('menuitem', { name: /Cancel event/i }).click()

    // Don't fill in reason, just confirm
    await page.getByRole('button', { name: /Confirm cancellation/i }).click()

    // Event should show as cancelled without reason text
    await expect(page.getByText(/This event has been cancelled/i)).toBeVisible()
  })
})

test.describe('US1: Cancel API failure', () => {
  test('cancel API fails — error displayed in bottom sheet, button re-enabled for retry', async ({
    page,
    network,
  }) => {
    network.use(
      http.get('*/api/events/:token', () => HttpResponse.json(fullEvent)),
      http.patch('*/api/events/:token', () => {
        return HttpResponse.json(
          {
            type: 'about:blank',
            title: 'Internal Server Error',
            status: 500,
            detail: 'Something went wrong',
          },
          { status: 500, headers: { 'Content-Type': 'application/problem+json' } },
        )
      }),
    )
    await page.addInitScript(seedEvents([organizerSeed()]))
    await page.goto(`/events/${fullEvent.eventToken}`)

    await page.getByRole('button', { name: /Event actions/i }).click()
    await page.getByRole('menuitem', { name: /Cancel event/i }).click()
    await page.getByRole('button', { name: /Confirm cancellation/i }).click()

    // Error message in bottom sheet
    await expect(page.getByText(/Could not cancel event/i)).toBeVisible()

    // Confirm button should be re-enabled
    await expect(page.getByRole('button', { name: /Confirm cancellation/i })).toBeEnabled()
  })
})
