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

const EVENT_TOKEN = 'limit-event';

function nowIso(): string {
  return new Date().toISOString();
}

test.describe('Guest PWA limit experiences', () => {
  test.beforeEach(async ({ page }) => {
    await page.addInitScript(
      ({ token }) => {
        try {
          window.localStorage.setItem(`guestName_${token}`, 'Playwright Gast');
          window.localStorage.setItem(`guestCameraPrimerDismissed_${token}`, '1');
        } catch (error) {
          console.warn('Failed to seed guest storage', error);
        }

        if (!navigator.mediaDevices) {
          Object.defineProperty(navigator, 'mediaDevices', {
            configurable: true,
            value: {},
          });
        }

        navigator.mediaDevices.getUserMedia = () => Promise.resolve(new MediaStream());
      },
      { token: EVENT_TOKEN }
    );

    const timestamp = nowIso();

    await page.route(`**/api/v1/events/${EVENT_TOKEN}`, async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 1,
          slug: EVENT_TOKEN,
          name: 'Limit Experience Event',
          default_locale: 'de',
          created_at: timestamp,
          updated_at: timestamp,
        }),
      });
    });

    await page.route(`**/api/v1/events/${EVENT_TOKEN}/tasks`, async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify([
          {
            id: 1,
            title: 'Playwright Mission',
            description: 'Test mission for upload limits',
            instructions: 'Mach ein Testfoto',
            duration: 2,
          },
        ]),
      });
    });

    await page.route(`**/api/v1/events/${EVENT_TOKEN}/stats`, async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          online_guests: 5,
          tasks_solved: 12,
          latest_photo_at: timestamp,
        }),
      });
    });

    await page.route(`**/api/v1/events/${EVENT_TOKEN}/photos**`, async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          data: [
            {
              id: 101,
              file_path: '/photos/101.jpg',
              thumbnail_path: '/photos/101-thumb.jpg',
              created_at: timestamp,
              likes_count: 3,
            },
          ],
          latest_photo_at: timestamp,
        }),
      });
    });
  });

  test('shows limit warnings and countdown before limits are reached', async ({ page }) => {
    const expiresAt = new Date(Date.now() + 2 * 86_400_000).toISOString();

    await page.route(`**/api/v1/events/${EVENT_TOKEN}/package`, async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 42,
          event_id: 1,
          used_photos: 95,
          expires_at: expiresAt,
          package: {
            id: 77,
            name: 'Starter',
            max_photos: 100,
            max_guests: 150,
            gallery_days: 30,
          },
          limits: {
            photos: {
              limit: 100,
              used: 95,
              remaining: 5,
              percentage: 95,
              state: 'warning',
              threshold_reached: 95,
              next_threshold: 100,
              thresholds: [80, 95, 100],
            },
            guests: null,
            gallery: {
              state: 'warning',
              expires_at: expiresAt,
              days_remaining: 2,
              warning_thresholds: [7, 1],
              warning_triggered: 2,
              warning_sent_at: null,
              expired_notified_at: null,
            },
            can_upload_photos: true,
            can_add_guests: true,
          },
        }),
      });
    });

    await page.goto(`/e/${EVENT_TOKEN}/upload?task=1`);
    await expect(page.getByRole('button', { name: /Foto aufnehmen/i })).toBeVisible();
    await expect(page.getByText(/Upload-Limit erreicht/i)).toHaveCount(0);

    await page.goto(`/e/${EVENT_TOKEN}/gallery`);
    await expect(page.getByRole('heading', { name: /Galerie/i }).first()).toBeVisible();
  });

  test('marks uploads as blocked and highlights expired gallery state', async ({ page }) => {
    const expiredAt = new Date(Date.now() - 86_400_000).toISOString();

    await page.route(`**/api/v1/events/${EVENT_TOKEN}/package`, async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 43,
          event_id: 1,
          used_photos: 100,
          expires_at: expiredAt,
          package: {
            id: 77,
            name: 'Starter',
            max_photos: 100,
            max_guests: 150,
            gallery_days: 30,
          },
          limits: {
            photos: {
              limit: 100,
              used: 100,
              remaining: 0,
              percentage: 100,
              state: 'limit_reached',
              threshold_reached: 100,
              next_threshold: null,
              thresholds: [80, 95, 100],
            },
            guests: null,
            gallery: {
              state: 'expired',
              expires_at: expiredAt,
              days_remaining: 0,
              warning_thresholds: [7, 1],
              warning_triggered: 0,
              warning_sent_at: null,
              expired_notified_at: expiredAt,
            },
            can_upload_photos: false,
            can_add_guests: true,
          },
        }),
      });
    });

    await page.goto(`/e/${EVENT_TOKEN}/upload?task=1`);
    await expect(page.getByText(/Upload-Limit erreicht/i)).toBeVisible();
    await expect(page.getByRole('button', { name: /Foto aufnehmen/i })).toHaveCount(0);

    await page.goto(`/e/${EVENT_TOKEN}/gallery`);
    await expect(page.getByRole('heading', { name: /Galerie/i }).first()).toBeVisible();
  });

  test('blocks uploads and guest access once all limits are exhausted', async ({ page }) => {
    await page.route(`**/api/v1/events/${EVENT_TOKEN}/package`, async (route) => {
      const exhaustedAt = new Date().toISOString();

      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 44,
          event_id: 1,
          used_photos: 120,
          expires_at: exhaustedAt,
          package: {
            id: 90,
            name: 'Starter',
            max_photos: 120,
            max_guests: 3,
            gallery_days: 30,
          },
          limits: {
            photos: {
              limit: 120,
              used: 120,
              remaining: 0,
              percentage: 100,
              state: 'limit_reached',
              threshold_reached: 120,
              next_threshold: null,
              thresholds: [80, 95, 120],
            },
            guests: {
              limit: 3,
              used: 3,
              remaining: 0,
              percentage: 100,
              state: 'limit_reached',
              threshold_reached: 3,
              next_threshold: null,
              thresholds: [2, 3],
            },
            gallery: {
              state: 'ok',
              expires_at: exhaustedAt,
              days_remaining: 10,
              warning_thresholds: [7, 1],
              warning_triggered: null,
              warning_sent_at: null,
              expired_notified_at: null,
            },
            can_upload_photos: false,
            can_add_guests: false,
          },
        }),
      });
    });

    await page.goto(`/e/${EVENT_TOKEN}/upload?task=1`);

    await expect(page.getByText(/Upload-Limit erreicht/i)).toBeVisible();
    await expect(page.getByRole('button', { name: /Foto aufnehmen/i })).toHaveCount(0);

    await page.goto(`/e/${EVENT_TOKEN}/gallery`);
    await expect(page.getByRole('heading', { name: /Galerie/i }).first()).toBeVisible();
  });
});
