/* ---------------------------------------------------------------------------
 * Verifier for the Backstage admin resource registry.
 *
 * Walks every registered resource and asserts the invariants that keep the
 * shared components renderable. Compile-time TypeScript already catches most
 * shape issues via the strict Resource<T> generic — this suite covers what
 * TS can't see at the value level (function-ness of handlers, kind strings
 * actually being in the registered set, sentinel resource keys not colliding).
 *
 * Note on "every column.key is a valid field on the entity":
 * That's a structural assertion best enforced at compile time. Resource<T>
 * narrows the render/value callbacks to the entity's keys; this suite skips
 * trying to re-check it at runtime.
 * ------------------------------------------------------------------------- */

import { describe, it, expect } from 'vitest';
import { groups } from '../src/admin/resources';
import type {
  Field,
  Resource,
  ResourceGroup,
  Column,
  FormEmbed,
} from '../src/admin/resource-types';

const KNOWN_FIELD_KINDS: ReadonlySet<Field['kind']> = new Set([
  'text',
  'textarea',
  'markdown',
  'select',
  'select-async',
  'multi-select-async',
  'multi-text',
  'date',
  'datetime',
  'number',
  'readonly',
]);

const KNOWN_COLUMN_KINDS: ReadonlySet<string> = new Set([
  'text', 'pill', 'relative-date', 'number', 'tag-list',
]);

const KNOWN_EMBED_COMPONENTS: ReadonlySet<FormEmbed['component']> = new Set([
  'pulse-sub-form',
]);

function allResources(): Resource[] {
  return groups.flatMap((g: ResourceGroup) => g.resources as Resource[]);
}

describe('admin resource registry', () => {
  it('has at least one group with resources registered', () => {
    expect(groups.length).toBeGreaterThan(0);
    expect(allResources().length).toBeGreaterThan(0);
  });

  it('every resource key is unique across the registry', () => {
    const keys = allResources().map((r) => r.key);
    const dups = keys.filter((k, i) => keys.indexOf(k) !== i);
    expect(dups).toEqual([]);
  });

  it('every resource.groupKey points at a real group', () => {
    const groupKeys = new Set(groups.map((g) => g.key));
    for (const r of allResources()) {
      expect(groupKeys.has(r.groupKey), `${r.key} → unknown groupKey ${r.groupKey}`).toBe(true);
    }
  });

  describe.each(allResources())('resource: $key', (resource: Resource) => {
    it('has required identity fields', () => {
      expect(resource.key).toBeTruthy();
      expect(resource.label).toBeTruthy();
      expect(resource.pluralLabel).toBeTruthy();
      expect(resource.singularLabel).toBeTruthy();
      expect(resource.groupKey).toBeTruthy();
    });

    it('list.queryFn is a function', () => {
      expect(typeof resource.list.queryFn).toBe('function');
    });

    it('every column has a registered kind (or none = text)', () => {
      for (const col of resource.list.columns as Column<unknown>[]) {
        const kind = col.kind ?? 'text';
        expect(KNOWN_COLUMN_KINDS.has(kind), `${resource.key}: column ${col.key} → unknown kind ${kind}`).toBe(true);
      }
      if (resource.list.columnsByFilter) {
        for (const [filterKey, cols] of Object.entries(resource.list.columnsByFilter)) {
          for (const col of cols as Column<unknown>[]) {
            const kind = col.kind ?? 'text';
            expect(KNOWN_COLUMN_KINDS.has(kind), `${resource.key}: columnsByFilter.${filterKey}.${col.key} → unknown kind ${kind}`).toBe(true);
          }
        }
      }
    });

    it('exactly one or zero filters is isDefault', () => {
      const filters = resource.list.filters ?? [];
      const defaults = filters.filter((f) => f.isDefault);
      expect(defaults.length).toBeLessThanOrEqual(1);
    });

    it('every filter.predicate is a function', () => {
      for (const f of resource.list.filters ?? []) {
        expect(typeof f.predicate, `${resource.key}: filter ${f.key} predicate`).toBe('function');
      }
    });

    it('every form field has a registered kind', () => {
      for (const field of resource.form?.fields ?? []) {
        expect(
          KNOWN_FIELD_KINDS.has(field.kind),
          `${resource.key}: field ${field.key} → unknown kind ${field.kind}`,
        ).toBe(true);
      }
    });

    it('every embed.component is in the registered set', () => {
      for (const embed of resource.form?.embeds ?? []) {
        expect(
          KNOWN_EMBED_COMPONENTS.has(embed.component),
          `${resource.key}: embed ${embed.key} → unknown component ${embed.component}`,
        ).toBe(true);
      }
    });

    it('every ops member is a function (when defined)', () => {
      const ops = resource.ops;
      if (ops.create) expect(typeof ops.create).toBe('function');
      if (ops.update) expect(typeof ops.update).toBe('function');
      if (ops.delete) expect(typeof ops.delete).toBe('function');
      if (ops.getById) expect(typeof ops.getById).toBe('function');
    });

    it('every action.handler is a function', () => {
      for (const action of resource.actions ?? []) {
        expect(typeof action.handler, `${resource.key}: action ${action.key}`).toBe('function');
      }
    });

    it('action keys are unique', () => {
      const keys = (resource.actions ?? []).map((a) => a.key);
      const dups = keys.filter((k, i) => keys.indexOf(k) !== i);
      expect(dups).toEqual([]);
    });

    it('renders SOMETHING when an item is clicked (form OR summary, or no clicks)', () => {
      // If form is null and there's no summary, the resource is non-clickable.
      // If form is null but a summary is defined → review panel renders.
      // If form is defined → edit panel renders.
      // The only invalid shape is form=null + summary defined + no actions,
      // which would render an empty review panel. Flag it.
      if (resource.form === null && resource.summary !== undefined) {
        const actions = resource.actions ?? [];
        expect(actions.length, `${resource.key}: review-mode resource with no actions`).toBeGreaterThan(0);
      }
    });

    it('when ops.create is defined, the form is defined too', () => {
      // Can't render the create panel without a form.
      if (resource.ops.create) {
        expect(resource.form, `${resource.key}: ops.create is defined but form is null`).not.toBeNull();
      }
    });
  });
});
