import { defineStory, useSelect, useValue, useBoolean } from '@djangocfg/playground';
import { Playground } from './index';
import { LazyOpenapiViewer } from './lazy';
import type { PlaygroundConfig } from './types';

export default defineStory({
  title: 'Tools/OpenapiViewer',
  component: Playground,
  description:
    'Interactive OpenAPI schema viewer. Sidebar + docs longread with a slide-in two-column playground (Request + Response) when an endpoint is selected.',
});

// ============================================================================
// Schema fixtures
// ============================================================================

// Petstore's own ``servers[0].url`` is just ``/api/v3`` (relative),
// which makes code samples look like they target ``localhost`` when
// viewed from the playground. Override with the canonical public host
// so the generated curl/fetch/etc snippets are runnable as-is.
const PETSTORE_SCHEMA = {
  id: 'petstore',
  name: 'Petstore API',
  url: 'https://petstore3.swagger.io/api/v3/openapi.json',
  baseUrl: 'https://petstore3.swagger.io/api/v3',
} as const;

const HTTPBIN_SCHEMA = {
  id: 'httpbin',
  name: 'HTTPBin API',
  url: 'https://httpbin.org/spec.json',
} as const;

const MULTI_SCHEMAS = [PETSTORE_SCHEMA, HTTPBIN_SCHEMA] as const;

// Simulates a real multi-group setup (like cmdop with 5+ API groups).
// All clones share the canonical Petstore host so code samples
// render with a real runnable URL.
const PETSTORE_BASE = 'https://petstore3.swagger.io/api/v3';
const MANY_SCHEMAS = [
  PETSTORE_SCHEMA,
  HTTPBIN_SCHEMA,
  { id: 'machines', name: 'Machines API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
  { id: 'terminal', name: 'Terminal API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
  { id: 'skills', name: 'Skills API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
  { id: 'system', name: 'System API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
  { id: 'site', name: 'Site API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
] as const;

// ============================================================================
// Stories
// ============================================================================

/**
 * Default — single-schema mode with the most common configuration knobs
 * exposed as toggles. Replaces the earlier Interactive / SingleSchema /
 * WithBaseUrl / NoDefault / CustomUrl stories, which were all "this
 * component with different props" variations.
 */
export const Default = () => {
  const [schemaUrl] = useValue('schemaUrl', {
    defaultValue: PETSTORE_SCHEMA.url,
    label: 'Schema URL',
    description: 'Any OpenAPI 3.x JSON endpoint',
  });

  const [baseUrl] = useValue('baseUrl', {
    defaultValue: '',
    label: 'Base URL override',
    description: 'Empty = use servers[0].url from the schema',
  });

  const [autoSelect] = useBoolean('autoSelectDefault', {
    defaultValue: true,
    label: 'Auto-select default schema',
    description: 'When off, tests the "no defaultSchemaId" code path',
  });

  const config: PlaygroundConfig = {
    schemas: [{ id: 'custom', name: 'Schema', url: schemaUrl }],
    defaultSchemaId: autoSelect ? 'custom' : undefined,
    baseUrl: baseUrl || undefined,
  };

  return (
    <div className="min-h-[600px]">
      <Playground config={config} />
    </div>
  );
};

/**
 * MultiSchema — multiple schemas with the Combobox switcher. Count
 * is adjustable to exercise both the short-list layout and the
 * long-list behaviour (cmdop-style setups with 7+ APIs).
 */
export const MultiSchema = () => {
  const [count] = useSelect('count', {
    options: ['2', '7'] as const,
    defaultValue: '2',
    label: 'Schema count',
    description: '2 uses Petstore+HTTPBin; 7 stress-tests the Combobox',
  });

  const config: PlaygroundConfig = {
    schemas: count === '2' ? [...MULTI_SCHEMAS] : [...MANY_SCHEMAS],
    defaultSchemaId: 'petstore',
  };

  return (
    <div className="min-h-[600px]">
      <Playground config={config} />
    </div>
  );
};

/**
 * SectionsGrouping — alternate layout: every schema's endpoints get
 * rendered on the same page as top-level sections, with a sidebar
 * that stacks them. URL hash sync writes ``#<schemaId>/<anchor>``
 * as the user scrolls so deep-linking keeps working.
 */
export const SectionsGrouping = () => {
  const [urlSync] = useBoolean('urlSync', {
    defaultValue: true,
    label: 'URL hash sync',
    description: 'Writes #<schemaId>/<anchor> as you scroll',
  });

  const config: PlaygroundConfig = {
    schemas: [...MULTI_SCHEMAS],
    defaultSchemaId: 'petstore',
    schemaGrouping: 'sections',
    urlSync,
  };

  return (
    <div className="min-h-[600px]">
      <Playground config={config} />
    </div>
  );
};

/**
 * Errors — consolidated failure paths. Pick a scenario via the toggle:
 *   - ``broken``: single schema that 404s → full-panel error state.
 *   - ``mixed``: valid + broken side-by-side → tests switching between.
 *   - ``empty``: no schemas configured at all → empty-state UI.
 */
export const Errors = () => {
  const [scenario] = useSelect('scenario', {
    options: ['broken', 'mixed', 'empty'] as const,
    defaultValue: 'broken',
    label: 'Failure scenario',
  });

  const config: PlaygroundConfig = (() => {
    switch (scenario) {
      case 'broken':
        return {
          schemas: [{ id: 'broken', name: 'Broken API', url: 'https://httpbin.org/status/404' }],
          defaultSchemaId: 'broken',
        };
      case 'mixed':
        return {
          schemas: [
            PETSTORE_SCHEMA,
            { id: 'broken', name: 'Broken API (404)', url: 'https://httpbin.org/status/404' },
          ],
          defaultSchemaId: 'petstore',
        };
      case 'empty':
        return { schemas: [] };
    }
  })();

  return (
    <div className="min-h-[600px]">
      <Playground config={config} />
    </div>
  );
};

/**
 * Lazy — production lazy-loaded variant. Shows the loading spinner
 * while the ~400 KB OpenAPI viewer chunk is fetched. Only path you
 * should use in an actual app bundle.
 */
export const Lazy = () => {
  const config: PlaygroundConfig = {
    schemas: [...MULTI_SCHEMAS],
    defaultSchemaId: 'petstore',
  };

  return (
    <div className="min-h-[600px]">
      <LazyOpenapiViewer config={config} />
    </div>
  );
};
