import { describe, expect, it } from 'vitest';
import {
  AI_GUIDE,
  CHEAT_SECTIONS,
  FORGE_VS_CALIBRATE,
  FUSION_GUIDE,
  NETWORK_GUIDE,
  PIPELINE_STEPS,
  ROADMAP_FEATURES,
  TROUBLESHOOTING,
} from './cheatSheetContent';

function assertSteps(steps: { id: string; title: string; subtitle: string; icon: string; body: string }[]) {
  const ids = steps.map((s) => s.id);
  expect(new Set(ids).size).toBe(ids.length);
  for (const step of steps) {
    expect(step.title.trim().length).toBeGreaterThan(0);
    expect(step.subtitle.trim().length).toBeGreaterThan(0);
    expect(step.icon.trim().length).toBeGreaterThan(0);
    expect(step.body.trim().length).toBeGreaterThan(20);
  }
}

describe('PIPELINE_STEPS', () => {
  it('defines six pipeline stages in workflow order', () => {
    expect(PIPELINE_STEPS).toHaveLength(6);
    expect(PIPELINE_STEPS.map((s) => s.id)).toEqual([
      'calibrate',
      'forge',
      'buildmgr',
      'drop',
      'connect',
      'mine',
    ]);
    expect(PIPELINE_STEPS.map((s) => s.title)).toEqual([
      'Calibrate',
      'Forge',
      'Build Manager',
      'Drop',
      'Connect',
      'Mine',
    ]);
  });

  it('each step has required content fields', () => {
    assertSteps(PIPELINE_STEPS);
  });

  it('routed steps link to primary app pages', () => {
    const routed = PIPELINE_STEPS.filter((s) => s.route);
    expect(routed.map((s) => s.route)).toEqual([
      '/settings',
      '/forge',
      '/builds',
      '/agents',
      '/dashboard',
    ]);
    for (const step of routed) {
      expect(step.routeLabel?.trim().length).toBeGreaterThan(0);
    }
  });

  it('drop step includes install one-liner example', () => {
    const drop = PIPELINE_STEPS.find((s) => s.id === 'drop')!;
    expect(drop.code).toContain('install.ps1');
    expect(drop.tips?.some((t) => t.includes('install.sh'))).toBe(true);
  });
});

describe('FORGE_VS_CALIBRATE', () => {
  it('has forge and calibrate sections with titles and item lists', () => {
    expect(FORGE_VS_CALIBRATE.forge.title).toMatch(/Forge/i);
    expect(FORGE_VS_CALIBRATE.calibrate.title).toMatch(/Calibrate/i);
    expect(FORGE_VS_CALIBRATE.forge.items.length).toBeGreaterThan(10);
    expect(FORGE_VS_CALIBRATE.calibrate.items.length).toBeGreaterThan(5);
  });

  it('forge items cover baked-in agent settings', () => {
    const joined = FORGE_VS_CALIBRATE.forge.items.join(' ');
    expect(joined).toMatch(/C2|server URL/i);
    expect(joined).toMatch(/wallet/i);
    expect(joined).toMatch(/Fusion/i);
  });

  it('calibrate items cover server-only settings', () => {
    const joined = FORGE_VS_CALIBRATE.calibrate.items.join(' ');
    expect(joined).toMatch(/Listen port/i);
    expect(joined).toMatch(/retention/i);
  });
});

describe('NETWORK_GUIDE', () => {
  it('has four LAN network steps with unique ids', () => {
    expect(NETWORK_GUIDE).toHaveLength(4);
    expect(NETWORK_GUIDE.map((s) => s.id)).toEqual(['n1', 'n2', 'n3', 'n4']);
    assertSteps(NETWORK_GUIDE);
  });
});

describe('FUSION_GUIDE', () => {
  it('has four fusion workflow steps', () => {
    expect(FUSION_GUIDE).toHaveLength(4);
    expect(FUSION_GUIDE.map((s) => s.id)).toEqual(['f1', 'f2', 'f3', 'f4']);
    assertSteps(FUSION_GUIDE);
  });
});

describe('AI_GUIDE', () => {
  it('has three AI autonomy steps', () => {
    expect(AI_GUIDE).toHaveLength(3);
    expect(AI_GUIDE.map((s) => s.id)).toEqual(['a1', 'a2', 'a3']);
    assertSteps(AI_GUIDE);
  });

  it('mentions Ollama and decide loop', () => {
    const bodies = AI_GUIDE.map((s) => s.body).join(' ');
    expect(bodies).toMatch(/Ollama/i);
    expect(bodies).toMatch(/decide/i);
  });
});

describe('TROUBLESHOOTING', () => {
  it('lists common problems with non-empty fixes', () => {
    expect(TROUBLESHOOTING.length).toBeGreaterThanOrEqual(10);
    for (const entry of TROUBLESHOOTING) {
      expect(entry.problem.trim().length).toBeGreaterThan(10);
      expect(entry.fix.trim().length).toBeGreaterThan(20);
    }
  });

  it('covers forge, pool, and dropper failure modes', () => {
    const problems = TROUBLESHOOTING.map((t) => t.problem).join(' ');
    expect(problems).toMatch(/Forge/i);
    expect(problems).toMatch(/hashrate|shares/i);
    expect(problems).toMatch(/dropper|PS1/i);
  });

  it('shares-rejected fix matches wallet validator range', () => {
    const entry = TROUBLESHOOTING.find((t) => t.problem.includes('Shares all rejected'))!;
    expect(entry.fix).toMatch(/90.*106/);
    expect(entry.fix).toMatch(/4 or 8/);
  });
});

describe('ROADMAP_FEATURES', () => {
  it('entries have priority, title, and description', () => {
    expect(ROADMAP_FEATURES.length).toBeGreaterThan(10);
    for (const feat of ROADMAP_FEATURES) {
      expect(['high', 'medium', 'low']).toContain(feat.priority);
      expect(feat.title.trim().length).toBeGreaterThan(3);
      expect(feat.desc.trim().length).toBeGreaterThan(10);
    }
  });

  it('includes shipped core features', () => {
    const titles = ROADMAP_FEATURES.map((f) => f.title);
    expect(titles).toContain('Build Manager full page');
    expect(titles).toContain('AI Autonomy (Ollama)');
    expect(titles).toContain('Dropper endpoints');
  });
});

describe('CHEAT_SECTIONS', () => {
  const expectedSections = [
    { id: 'pipeline', title: 'End-to-end pipeline' },
    { id: 'network', title: 'Network topology — LAN + USB' },
    { id: 'fusion', title: 'Fusion workflow' },
    { id: 'ai', title: 'AI Autonomy workflow' },
    { id: 'troubleshoot', title: 'Troubleshooting' },
  ];

  it('registers five guide sections with stable ids and titles', () => {
    expect(CHEAT_SECTIONS).toHaveLength(5);
    expect(CHEAT_SECTIONS.map((s) => ({ id: s.id, title: s.title }))).toEqual(expectedSections);
  });

  it('each section has a non-empty description', () => {
    for (const section of CHEAT_SECTIONS) {
      expect(section.description.trim().length).toBeGreaterThan(20);
    }
  });

  it('step sections reference the exported step arrays', () => {
    const byId = Object.fromEntries(CHEAT_SECTIONS.map((s) => [s.id, s]));
    expect(byId.pipeline.steps).toBe(PIPELINE_STEPS);
    expect(byId.network.steps).toBe(NETWORK_GUIDE);
    expect(byId.fusion.steps).toBe(FUSION_GUIDE);
    expect(byId.ai.steps).toBe(AI_GUIDE);
  });

  it('troubleshoot section maps cards from TROUBLESHOOTING', () => {
    const troubleshoot = CHEAT_SECTIONS.find((s) => s.id === 'troubleshoot')!;
    expect(troubleshoot.cards).toHaveLength(TROUBLESHOOTING.length);
    expect(troubleshoot.cards![0]).toEqual({
      title: TROUBLESHOOTING[0].problem,
      body: TROUBLESHOOTING[0].fix,
      accent: 'amber',
    });
  });
});
