import { describe, it, expect } from 'vitest';
import { BriefViewDto } from '@shared/infrastructure/api-client';
import { parseBrief, parseBriefView, parseNode, parseStatus } from './brief.adapter';

const view: BriefViewDto = {
  brief: {
    briefId: 'b1',
    beroep: 'arts',
    templateId: 't1',
    drafterId: 'demo-drafter',
    status: { tag: 'submitted', submittedBy: 'demo-drafter', submittedAt: '2026-07-01' },
    placeholders: [
      { key: 'naam', label: 'Naam', autoResolvable: true },
      { key: 'code', label: 'Code', autoResolvable: true, fillable: false },
    ],
    sections: [
      {
        sectionKey: 'aanhef',
        title: 'Aanhef',
        required: true,
        blocks: [
          { type: 'passage', blockId: 'local-1', content: { paragraphs: [{ nodes: [{ type: 'placeholder', key: 'naam' }] }] }, sourcePassageId: 'p1', sourceVersion: 2, edited: true },
          { type: 'freeText', blockId: 'local-2', content: { paragraphs: [{ nodes: [{ type: 'text', text: 'hoi', marks: ['bold'] }] }] } },
        ],
      },
    ],
  },
  availablePassages: [
    { passageId: 'p1', scope: 'global', sectionKey: 'aanhef', label: 'Aanhef', content: { paragraphs: [{ nodes: [] }] }, version: 1 },
  ],
};

describe('brief.adapter parse boundary', () => {
  it('parses a well-formed view into the domain unions', () => {
    const r = parseBriefView(view);
    expect(r.ok).toBe(true);
    if (!r.ok) return;
    expect(r.value.brief.status).toEqual({ tag: 'submitted', submittedBy: 'demo-drafter', submittedAt: '2026-07-01' });
    const [passage, free] = r.value.brief.sections[0].blocks;
    expect(passage.type === 'passage' && passage.edited).toBe(true);
    expect(free.type).toBe('freeText');
    expect(r.value.brief.placeholders[1]).toEqual({ key: 'code', label: 'Code', autoResolvable: true, fillable: false });
  });

  it('narrows node variants and rejects unknown ones', () => {
    expect(parseNode({ type: 'text', text: 'x' })).toEqual({ ok: true, value: { type: 'text', text: 'x' } });
    expect(parseNode({ type: 'placeholder', key: 'k' })).toEqual({ ok: true, value: { type: 'placeholder', key: 'k' } });
    expect(parseNode({ type: 'lineBreak' })).toEqual({ ok: true, value: { type: 'lineBreak' } });
    expect(parseNode({ type: 'text' }).ok).toBe(false); // missing text
    expect(parseNode({ type: 'bogus' } as never).ok).toBe(false);
  });

  it('rejects a status DTO missing its required fields', () => {
    expect(parseStatus({ tag: 'submitted' }).ok).toBe(false); // no submittedBy/At
    expect(parseStatus({ tag: 'rejected', rejectedBy: 'x', rejectedAt: 't' }).ok).toBe(false); // no comments
    expect(parseStatus({ tag: 'draft' }).ok).toBe(true);
  });

  it('reads section.locked (default false) and paragraph.list', () => {
    const r = parseBrief({
      ...view.brief,
      sections: [
        {
          sectionKey: 'aanhef',
          title: 'Aanhef',
          required: true,
          locked: true,
          blocks: [
            {
              type: 'freeText',
              blockId: 'b1',
              content: {
                paragraphs: [
                  { nodes: [{ type: 'text', text: 'een' }], list: 'bullet' },
                  { nodes: [{ type: 'text', text: 'twee' }], list: 'number' },
                  { nodes: [{ type: 'text', text: 'plat' }] },
                ],
              },
            },
          ],
        },
        { sectionKey: 'kern', title: 'Kern', required: true, blocks: [] }, // no `locked` → false
      ],
    });
    expect(r.ok).toBe(true);
    if (!r.ok) return;
    const [aanhef, kern] = r.value.sections;
    expect(aanhef.locked).toBe(true);
    expect(kern.locked).toBe(false);
    expect(aanhef.blocks[0].content.paragraphs.map((p) => p.list)).toEqual(['bullet', 'number', undefined]);
  });

  it('rejects a passage block missing provenance', () => {
    const r = parseBrief({
      ...view.brief,
      sections: [{ sectionKey: 's', title: 'S', required: false, blocks: [{ type: 'passage', blockId: 'b', content: { paragraphs: [] } }] }],
    });
    expect(r.ok).toBe(false);
  });
});
