import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import Platform from './Platform';

const json = (value: unknown, status = 200) => Promise.resolve(new Response(JSON.stringify(value), {
  status, headers: { 'Content-Type': 'application/json' },
}));

afterEach(() => {
  vi.unstubAllGlobals();
  window.history.replaceState({}, '', '/');
});

describe('public Polyform platform', () => {
  it('renders the landing page and product explanation without an account', async () => {
    vi.stubGlobal('fetch', vi.fn((input: RequestInfo | URL) => String(input).endsWith('/auth/me')
      ? json({ detail: 'sign in required' }, 401) : json([])));
    window.history.replaceState({}, '', '/');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: /Keep one implementation bug from reaching everyone/i })).toBeInTheDocument();
    expect(screen.getByText('Suppose your app needs to decode a filename.')).toBeInTheDocument();
    expect(screen.getByRole('link', { name: 'Create account' })).toHaveAttribute('href', '/signup');
  });

  it('links every documentation topic to a real page', async () => {
    vi.stubGlobal('fetch', vi.fn(() => json({ detail: 'sign in required' }, 401)));
    window.history.replaceState({}, '', '/docs');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: 'Build software that does not depend on one implementation' })).toBeInTheDocument();
    expect(screen.getByRole('link', { name: 'Create a project' })).toHaveAttribute('href', '/docs/create-project');
    expect(screen.getByRole('link', { name: 'Write a specification' })).toHaveAttribute('href', '/docs/specification');
    expect(screen.getByRole('link', { name: 'Generate the code' })).toHaveAttribute('href', '/docs/generate');
    expect(screen.getByRole('link', { name: 'Connect your app' })).toHaveAttribute('href', '/docs/runtime');
    expect(screen.getByRole('link', { name: 'Check and publish' })).toHaveAttribute('href', '/docs/publish');
    expect(screen.getByRole('link', { name: 'Results and quarantine' })).toHaveAttribute('href', '/docs/telemetry');
  });

  it('shows a complete specification example on its own URL', async () => {
    vi.stubGlobal('fetch', vi.fn(() => json({ detail: 'sign in required' }, 401)));
    window.history.replaceState({}, '', '/docs/specification');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: 'Describe the complete behavior before generating code' })).toBeInTheDocument();
    expect(screen.getByText(/raw filename bytes exactly as stored/)).toBeInTheDocument();
    expect(screen.getByRole('heading', { name: 'What becomes an executable test?' })).toBeInTheDocument();
  });

  it('explains the agent-driven generation command on its own URL', async () => {
    vi.stubGlobal('fetch', vi.fn(() => json({ detail: 'sign in required' }, 401)));
    window.history.replaceState({}, '', '/docs/generate');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: 'Ask coding agents to build every implementation' })).toBeInTheDocument();
    expect(screen.getByText('polyform generate --count 5')).toBeInTheDocument();
    expect(screen.getByText(/Codex is the default agent/)).toBeInTheDocument();
  });

  it('walks beginners through an agent-built Fizz Buzz project', async () => {
    vi.stubGlobal('fetch', vi.fn(() => json({ detail: 'sign in required' }, 401)));
    window.history.replaceState({}, '', '/docs/create-project');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: 'Build your first Polyform project: Fizz Buzz' })).toBeInTheDocument();
    expect(screen.getByRole('heading', { name: '1. Start a normal repository' })).toBeInTheDocument();
    expect(screen.getByRole('heading', { name: '3. Have coding agents implement it' })).toBeInTheDocument();
    expect(screen.getByText('polyform generate --count 5')).toBeInTheDocument();
    expect(screen.getByText('Five versions of four functions create 625 combinations')).toBeInTheDocument();
    expect(screen.getAllByText('specs/polyform.toml').length).toBeGreaterThan(0);
    expect(screen.getByText(/location of the file/i)).toBeInTheDocument();
    expect(screen.queryByText(/json-safe/i)).not.toBeInTheDocument();
    expect(screen.queryByText(/state_rule/i)).not.toBeInTheDocument();
  });

  it('has a real signup page', async () => {
    vi.stubGlobal('fetch', vi.fn(() => json({ detail: 'sign in required' }, 401)));
    window.history.replaceState({}, '', '/signup');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: /Create your Polyform account/i })).toBeInTheDocument();
    expect(screen.queryByLabelText('Display name')).not.toBeInTheDocument();
    expect(screen.getByLabelText('Username')).toBeInTheDocument();
    expect(screen.getByLabelText('Email')).toBeRequired();
  });

  it('shows multiple projects in a signed-in user workspace', async () => {
    const user = { id: 1, username: 'ada', created_at: '2026-01-01' };
    const projects = ['zip-safe', 'database-safe'].map((slug, id) => ({ id, owner: 'ada', slug, name: slug, description: '', visibility: 'public', created_at: '', updated_at: '' }));
    vi.stubGlobal('fetch', vi.fn((input: RequestInfo | URL) => String(input).endsWith('/auth/me') ? json(user) : json(projects)));
    window.history.replaceState({}, '', '/dashboard');
    render(<Platform />);
    expect(await screen.findByText('2 owned by @ada')).toBeInTheDocument();
    await waitFor(() => expect(screen.getAllByText('zip-safe').length).toBeGreaterThan(0));
    expect(screen.getAllByText('database-safe').length).toBeGreaterThan(0);
  });

  it('lets an owner edit a project that is missing repository details', async () => {
    const user = { id: 1, username: 'ada', created_at: '2026-01-01' };
    const project = { id: 1, owner: 'ada', slug: 'json-safe', name: 'Safer JSON', description: '', visibility: 'public', created_at: '', updated_at: '', releases: [] };
    vi.stubGlobal('fetch', vi.fn((input: RequestInfo | URL) => String(input).endsWith('/auth/me') ? json(user) : json(project)));
    window.history.replaceState({}, '', '/ada/json-safe');
    render(<Platform />);
    fireEvent.click(await screen.findByRole('button', { name: 'Edit project' }));
    expect(screen.getByRole('heading', { name: 'Edit project' })).toBeInTheDocument();
    expect(screen.getByLabelText(/Public GitHub repository/i)).toBeRequired();
    expect(screen.getByLabelText(/Specification path/i)).toHaveValue('specs/polyform.toml');
  });

  it('shows a public user profile with all of their projects', async () => {
    const profile = { id: 1, username: 'ada', created_at: '2026-01-01', projects: [
      { id: 1, owner: 'ada', slug: 'zip-safe', name: 'Safer ZIP', description: '', visibility: 'public', created_at: '', updated_at: '' },
      { id: 2, owner: 'ada', slug: 'db-safe', name: 'Safer DB', description: '', visibility: 'public', created_at: '', updated_at: '' },
    ] };
    vi.stubGlobal('fetch', vi.fn((input: RequestInfo | URL) => String(input).endsWith('/auth/me') ? json({ detail: 'sign in required' }, 401) : json(profile)));
    window.history.replaceState({}, '', '/ada');
    render(<Platform />);
    expect(await screen.findByRole('heading', { name: '@ada' })).toBeInTheDocument();
    expect(screen.getByText('2 public')).toBeInTheDocument();
    expect(screen.getByRole('heading', { name: 'Safer ZIP' })).toBeInTheDocument();
    expect(screen.getByRole('heading', { name: 'Safer DB' })).toBeInTheDocument();
  });
});
