import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
import Mermaid, {
  FlowDiagram,
  SequenceDiagram,
  JourneyDiagram,
  useStylePresets,
  useBoxColors,
} from './index';

export default defineStory({
  title: 'Tools/Mermaid',
  component: Mermaid,
  description: 'Mermaid diagram renderer with declarative type-safe builders.',
});

// ============================================================================
// Diagram Generators
// ============================================================================

function useFlowDiagram() {
  type Nodes = 'start' | 'check' | 'success' | 'debug' | 'finish';
  const flow = FlowDiagram<Nodes>({ direction: 'TB' });
  const presets = useStylePresets();

  flow.node('start').rect('Start');
  flow.node('check').rhombus('Is it working?');
  flow.node('success').rect('Great!');
  flow.node('debug').rect('Debug');
  flow.node('finish').stadium('End');

  flow.edge('start').to('check').solid();
  flow.edge('check').to('success').solid('Yes');
  flow.edge('check').to('debug').solid('No');
  flow.edge('debug').to('check').dotted();
  flow.edge('success').to('finish').solid();

  flow.style.define('success', presets.success);
  flow.style.define('primary', presets.primary);
  flow.style.apply('success', 'success', 'finish');
  flow.style.apply('primary', 'start');

  return flow.toString();
}

function useSequenceDiagram() {
  const boxes = useBoxColors();

  const { d, rect, alt, loop, blank, toString } = SequenceDiagram({
    User: 'actor',
    App: 'participant',
    Auth: 'participant',
    DB: 'participant',
  }, { autoNumber: true });

  rect(boxes.primary, () => {
    d.User.sync.App.msg('Enter credentials');
    d.App.sync.Auth.msg('Validate credentials');

    alt('Valid credentials', () => {
      d.Auth.sync.DB.msg('Get user profile');
      d.DB.syncReply.Auth.msg('Profile data');
      d.Auth.syncReply.App.msg('Auth token');
      d.App.syncReply.User.msg('Welcome!');
    }).else('Invalid credentials', () => {
      d.Auth.syncReply.App.msg('Auth failed');
      d.App.syncReply.User.msg('Error message');
    });
  });

  blank();

  loop('Every 15 minutes', () => {
    d.App.async.Auth.msg('Refresh token');
    d.Auth.asyncReply.App.msg('New token');
  });

  return toString();
}

function useJourneyDiagram() {
  const journey = JourneyDiagram({ title: 'User Onboarding' });

  journey.section('Discovery')
    .task('Visit landing page', 5, 'User')
    .task('Read features', 4, 'User');

  journey.section('Sign Up')
    .task('Click Sign Up', 5, 'User')
    .task('Fill form', 2, 'User')
    .task('Verify email', 4, ['User', 'System']);

  journey.section('Onboarding')
    .task('Complete profile', 3, 'User')
    .task('Create first project', 5, 'User');

  return journey.toString();
}

/**
 * Example using dynamic methods for runtime participant names
 * Useful when participants are not known at compile time
 */
function useDynamicSequenceDiagram() {
  const boxes = useBoxColors();

  // Participants from dynamic data (e.g., from API)
  const participants = ['Alice', 'Bob', 'Charlie'];
  const participantsObj: Record<string, 'participant'> = {};
  participants.forEach(p => { participantsObj[p] = 'participant'; });

  const seq = SequenceDiagram(participantsObj, { autoNumber: true });

  // Using dynamic methods - no type assertions needed
  seq.rect(boxes.primary, () => {
    seq.noteOver('Alice', 'Starting conversation');
    seq.message('Alice', 'Bob', 'Hello Bob!');
    seq.message('Bob', 'Alice', 'Hi Alice!', 'syncReply');
  });

  seq.blank();

  seq.rect(boxes.success, () => {
    seq.noteOverSpan('Alice', 'Charlie', 'Group discussion');
    seq.message('Alice', 'Charlie', 'Hey Charlie!');
    seq.message('Charlie', 'Bob', 'Bob, join us!');
    seq.message('Bob', 'Charlie', 'On my way!', 'async');
  });

  return seq.toString();
}

function useArchitectureDiagram() {
  type Nodes = 'client' | 'nginx' | 'api1' | 'api2' | 'db' | 'cache' | 'queue';
  const flow = FlowDiagram<Nodes>({ direction: 'TB' });
  const presets = useStylePresets();

  flow.subgraph('Frontend', (sub) => {
    sub.direction('LR');
    sub.node('client').round('Browser');
  });

  flow.subgraph('Load Balancer', (sub) => {
    sub.node('nginx').hexagon('Nginx');
  });

  flow.subgraph('API Servers', (sub) => {
    sub.direction('LR');
    sub.node('api1').rect('API Server 1');
    sub.node('api2').rect('API Server 2');
  });

  flow.subgraph('Data Layer', (sub) => {
    sub.direction('LR');
    sub.node('db').cylinder('PostgreSQL');
    sub.node('cache').cylinder('Redis');
    sub.node('queue').cylinder('RabbitMQ');
  });

  flow.edge('client').to('nginx').solid();
  flow.edge('nginx').to('api1').solid();
  flow.edge('nginx').to('api2').solid();
  flow.edge('api1').to('db').solid();
  flow.edge('api2').to('db').solid();
  flow.edge('api1').to('cache').dotted();
  flow.edge('api2').to('cache').dotted();
  flow.edge('api1').to('queue').dotted();

  flow.style.define('frontend', presets.info);
  flow.style.define('backend', presets.success);
  flow.style.define('data', presets.warning);
  flow.style.apply('frontend', 'client', 'nginx');
  flow.style.apply('backend', 'api1', 'api2');
  flow.style.apply('data', 'db', 'cache', 'queue');

  return flow.toString();
}

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

export const Interactive = () => {
  const [diagramType] = useSelect('diagramType', {
    options: ['flow', 'sequence', 'sequenceDynamic', 'journey', 'architecture'] as const,
    defaultValue: 'flow',
    label: 'Diagram Type',
  });

  const [fullscreen] = useBoolean('fullscreen', {
    defaultValue: false,
    label: 'Enable Fullscreen',
  });

  const flowChart = useFlowDiagram();
  const sequenceChart = useSequenceDiagram();
  const sequenceDynamicChart = useDynamicSequenceDiagram();
  const journeyChart = useJourneyDiagram();
  const architectureChart = useArchitectureDiagram();

  const charts = {
    flow: flowChart,
    sequence: sequenceChart,
    sequenceDynamic: sequenceDynamicChart,
    journey: journeyChart,
    architecture: architectureChart,
  };

  const chart = charts[diagramType];

  return (
    <div className="space-y-4">
      <Mermaid chart={chart} fullscreen={fullscreen} />
      <details className="text-xs">
        <summary className="cursor-pointer text-muted-foreground">Generated Mermaid code</summary>
        <pre className="mt-2 p-3 bg-muted rounded overflow-auto">{chart}</pre>
      </details>
    </div>
  );
};

export const Flow = () => {
  const chart = useFlowDiagram();
  return <Mermaid chart={chart} />;
};

export const Sequence = () => {
  const chart = useSequenceDiagram();
  return <Mermaid chart={chart} />;
};

export const Journey = () => {
  const chart = useJourneyDiagram();
  return <Mermaid chart={chart} />;
};

export const Architecture = () => {
  const chart = useArchitectureDiagram();
  return <Mermaid chart={chart} />;
};

export const WithFullscreen = () => {
  const chart = useFlowDiagram();
  return (
    <div className="space-y-2">
      <p className="text-sm text-muted-foreground">
        Click the expand button to open fullscreen
      </p>
      <Mermaid chart={chart} fullscreen />
    </div>
  );
};
