import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
import { useState } from 'react';
import { JsonSchemaForm } from './index';

export default defineStory({
  title: 'Tools/Json Schema Form',
  component: JsonSchemaForm,
  description:
    'Dynamic form generator from JSON Schema using react-jsonschema-form. Supports density (compact), conditional disable via `ui:disabledWhen`, and collapsible sub-sections via `ui:groups`.',
});

const SCHEMAS = {
  simple: {
    schema: {
      type: 'object' as const,
      required: ['name', 'email'],
      properties: {
        name: { type: 'string' as const, title: 'Name' },
        email: { type: 'string' as const, title: 'Email', format: 'email' },
        age: { type: 'integer' as const, title: 'Age', minimum: 0, maximum: 120 },
      },
    },
    uiSchema: {},
  },
  vehicle: {
    schema: {
      type: 'object' as const,
      required: ['make', 'model', 'year'],
      properties: {
        make: {
          type: 'string' as const,
          title: 'Make',
          enum: ['BMW', 'Mercedes', 'Audi', 'Porsche', 'Tesla'],
        },
        model: { type: 'string' as const, title: 'Model' },
        year: { type: 'integer' as const, title: 'Year', minimum: 1990, maximum: 2025 },
        price: { type: 'number' as const, title: 'Price ($)' },
        features: {
          type: 'array' as const,
          title: 'Features',
          items: {
            type: 'string' as const,
            enum: ['Leather', 'Navigation', 'Sunroof', 'Heated Seats', 'Parking Sensors'],
          },
          uniqueItems: true,
        },
        description: { type: 'string' as const, title: 'Description' },
      },
    },
    uiSchema: {
      description: { 'ui:widget': 'textarea' },
      features: { 'ui:widget': 'checkboxes' },
    },
  },
  contact: {
    schema: {
      type: 'object' as const,
      required: ['firstName', 'lastName', 'email'],
      properties: {
        firstName: { type: 'string' as const, title: 'First Name' },
        lastName: { type: 'string' as const, title: 'Last Name' },
        email: { type: 'string' as const, title: 'Email', format: 'email' },
        phone: { type: 'string' as const, title: 'Phone' },
        message: { type: 'string' as const, title: 'Message' },
        subscribe: { type: 'boolean' as const, title: 'Subscribe to newsletter' },
      },
    },
    uiSchema: {
      message: { 'ui:widget': 'textarea' },
    },
  },
};

export const Interactive = () => {
  const [schemaType] = useSelect('schemaType', {
    options: ['simple', 'vehicle', 'contact'] as const,
    defaultValue: 'vehicle',
    label: 'Schema Type',
    description: 'Select form schema',
  });

  const [density] = useSelect('density', {
    options: ['comfortable', 'compact'] as const,
    defaultValue: 'comfortable',
    label: 'Density',
    description: '`compact` shrinks rows and moves description into label tooltip.',
  });

  const [liveValidate] = useBoolean('liveValidate', {
    defaultValue: false,
    label: 'Live Validate',
    description: 'Validate on every change',
  });

  const config = SCHEMAS[schemaType];

  return (
    <div className="max-w-lg">
      <JsonSchemaForm
        schema={config.schema}
        uiSchema={config.uiSchema}
        liveValidate={liveValidate}
        density={density}
        onSubmit={(data) => console.log('Submitted:', data.formData)}
      />
    </div>
  );
};

export const SimpleForm = () => (
  <div className="max-w-md">
    <JsonSchemaForm
      schema={SCHEMAS.simple.schema}
      onSubmit={(data) => console.log('Submitted:', data.formData)}
    />
  </div>
);

export const VehicleForm = () => (
  <div className="max-w-lg">
    <JsonSchemaForm
      schema={SCHEMAS.vehicle.schema}
      uiSchema={SCHEMAS.vehicle.uiSchema}
      onSubmit={(data) => console.log('Submitted:', data.formData)}
    />
  </div>
);

export const WithDefaultValues = () => (
  <div className="max-w-lg">
    <JsonSchemaForm
      schema={SCHEMAS.vehicle.schema}
      uiSchema={SCHEMAS.vehicle.uiSchema}
      formData={{
        make: 'BMW',
        model: 'X5',
        year: 2023,
        price: 65000,
        features: ['Leather', 'Navigation'],
      }}
      onSubmit={(data) => console.log('Submitted:', data.formData)}
    />
  </div>
);

/**
 * Compact density — shrinks rows, moves description into a tooltip on the
 * label. Pair with `ui:groups` for dense sidebar / playground configurators.
 */
export const Compact = () => (
  <div className="max-w-md">
    <JsonSchemaForm
      schema={SCHEMAS.simple.schema}
      density="compact"
      showSubmitButton={false}
      onSubmit={(data) => console.log('Submitted:', data.formData)}
    />
  </div>
);

/**
 * `ui:disabledWhen` greys out a field based on another field's value.
 * Here `phone` is disabled until `subscribe` is checked, and `email` is
 * disabled when `firstName` is empty.
 */
export const ConditionalDisable = () => {
  const [data, setData] = useState<Record<string, unknown>>({
    firstName: '',
    subscribe: false,
  });
  return (
    <div className="max-w-lg">
      <JsonSchemaForm
        schema={SCHEMAS.contact.schema}
        uiSchema={{
          ...SCHEMAS.contact.uiSchema,
          email: {
            'ui:disabledWhen': { path: 'firstName', falsy: true },
          },
          phone: {
            'ui:disabledWhen': { path: 'subscribe', falsy: true },
          },
          subscribe: { 'ui:widget': 'switch' },
        }}
        formData={data}
        onChange={(e) => setData(e.formData ?? {})}
        showSubmitButton={false}
      />
      <pre className="mt-3 text-[11px] text-muted-foreground">
        {JSON.stringify(data, null, 2)}
      </pre>
    </div>
  );
};

/**
 * `ui:groups` splits a flat object into collapsible sub-sections without
 * restructuring the schema. Fields not listed in any group render flat above
 * the groups.
 */
export const CollapsibleGroups = () => (
  <div className="max-w-lg">
    <JsonSchemaForm
      schema={{
        type: 'object',
        properties: {
          identity: { type: 'string', title: 'Display name' },
          firstName: { type: 'string', title: 'First name' },
          lastName: { type: 'string', title: 'Last name' },
          email: { type: 'string', title: 'Email', format: 'email' },
          phone: { type: 'string', title: 'Phone' },
          newsletter: { type: 'boolean', title: 'Newsletter' },
          marketing: { type: 'boolean', title: 'Marketing emails' },
          tracking: { type: 'boolean', title: 'Usage analytics' },
        },
      }}
      uiSchema={{
        'ui:groups': [
          {
            title: 'Personal',
            fields: ['firstName', 'lastName'],
            defaultOpen: true,
          },
          { title: 'Contact', fields: ['email', 'phone'], defaultOpen: false },
          {
            title: 'Preferences',
            fields: ['newsletter', 'marketing', 'tracking'],
            defaultOpen: false,
          },
        ],
        newsletter: { 'ui:widget': 'switch' },
        marketing: { 'ui:widget': 'switch' },
        tracking: { 'ui:widget': 'switch' },
      }}
      density="compact"
      showSubmitButton={false}
      onChange={(e) => console.log('changed:', e.formData)}
    />
  </div>
);

/**
 * Empty-string enum values are now allowed — Radix `<Select.Item value="" />`
 * is reserved, so the ui-core `Select` wrapper substitutes a sentinel
 * internally. From the schema's perspective `''` is just another option.
 */
export const EmptyStringSelect = () => {
  const [data, setData] = useState<Record<string, unknown>>({ plan: '' });
  return (
    <div className="max-w-md">
      <JsonSchemaForm
        schema={{
          type: 'object',
          properties: {
            plan: {
              type: 'string',
              title: 'Plan',
              enum: ['', 'Free', 'Pro', 'Max', 'Enterprise'],
              description: 'An empty string is a valid enum value here.',
            },
          },
        }}
        uiSchema={{
          plan: {
            'ui:enumNames': ['— none —', 'Free', 'Pro', 'Max', 'Enterprise'],
          },
        }}
        formData={data}
        onChange={(e) => setData(e.formData ?? {})}
        showSubmitButton={false}
      />
      <pre className="mt-3 text-[11px] text-muted-foreground">
        {JSON.stringify(data, null, 2)}
      </pre>
    </div>
  );
};

/**
 * Live demo of all extensions wired together — compact density, collapsible
 * groups, conditional disable, slider with unit. Mirrors what the layouts
 * playground sidebar uses.
 */
export const PlaygroundStyle = () => {
  const [data, setData] = useState<Record<string, unknown>>({
    shell: { variant: 'boxed', inset: 12, radius: '2xl', border: true },
    sidebar: {
      density: 'default',
      activeIndicator: 'background',
      collapsibleGroups: false,
    },
  });
  return (
    <div className="max-w-md">
      <JsonSchemaForm
        schema={{
          type: 'object',
          properties: {
            shell: {
              type: 'object',
              title: 'Shell',
              properties: {
                variant: { type: 'string', title: 'Variant', enum: ['full-bleed', 'boxed'] },
                inset: { type: 'integer', title: 'Inset', minimum: 0, maximum: 32 },
                radius: { type: 'string', title: 'Radius', enum: ['sm', 'md', 'lg', 'xl', '2xl', '3xl'] },
                border: { type: 'boolean', title: 'Border' },
              },
            },
            sidebar: {
              type: 'object',
              title: 'Sidebar',
              properties: {
                density: { type: 'string', title: 'Density', enum: ['sparse', 'default', 'dense'] },
                activeIndicator: {
                  type: 'string',
                  title: 'Active indicator',
                  enum: ['background', 'rail', 'both'],
                },
                collapsibleGroups: { type: 'boolean', title: 'Collapsible groups' },
              },
            },
          },
        }}
        uiSchema={{
          shell: {
            'ui:collapsible': true,
            inset: {
              'ui:widget': 'slider',
              'ui:options': { unit: 'px', step: 2, showInput: false },
              'ui:disabledWhen': { path: 'shell.variant', notEq: 'boxed' },
            },
            radius: { 'ui:disabledWhen': { path: 'shell.variant', notEq: 'boxed' } },
            border: {
              'ui:widget': 'switch',
              'ui:disabledWhen': { path: 'shell.variant', notEq: 'boxed' },
            },
          },
          sidebar: {
            'ui:collapsible': true,
            collapsibleGroups: { 'ui:widget': 'switch' },
          },
        }}
        formData={data}
        onChange={(e) => setData(e.formData ?? {})}
        density="compact"
        showSubmitButton={false}
      />
    </div>
  );
};
