/**
 * cli:build-manifest — types.ts
 * Generates tests/ui-test/manifest.json consumed by Phase 5 run-ui-test.
 *
 * Input is a self-contained spec (one entity per CRUD pair). The CLI does NOT
 * read the filesystem registry/controllers — the orchestrator passes the same
 * data that drove scaffold-routes + scaffold-component + scaffold-controller.
 */
import { z } from 'zod';

export const ManifestEntitySchema = z.object({
  /** PascalCase singular, e.g. "Employee". */
  name: z.string().min(1),
  /** Section code matching the seeded section, e.g. "employees". */
  section: z.string().min(1).regex(/^[a-z][a-z0-9-]*$/, 'section must be kebab-case'),
  /** URL plural (kebab). Defaults to section. */
  plural: z.string().min(1).regex(/^[a-z][a-z0-9-]*$/, 'plural must be kebab-case').optional(),
  /** Roles allowed to read/list — produces positive list+detail tests. */
  rolesWithRead: z.array(z.string().min(1)).default([]),
  /** Roles allowed to create — produces form-submit tests. */
  rolesWithCreate: z.array(z.string().min(1)).default([]),
  /** Roles allowed to update — produces edit tests. */
  rolesWithUpdate: z.array(z.string().min(1)).default([]),
  /** Roles allowed to delete — produces delete tests. */
  rolesWithDelete: z.array(z.string().min(1)).default([]),
  /** Roles that should be DENIED — produces permission-negative tests. */
  rolesWithoutAccess: z.array(z.string().min(1)).default([]),
  /** Sample form data for create/edit scenarios. Fields must match the form. */
  fixture: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).default({}),
});

export const BuildManifestInputSchema = z.object({
  module: z.string().min(1),
  appCode: z.string().min(1).regex(/^[a-z][a-z0-9-]*$/, 'appCode must be kebab-case'),
  projectPath: z.string().min(1),
  entities: z.array(ManifestEntitySchema).min(1, 'At least one entity required'),
});

export type ManifestEntity = z.infer<typeof ManifestEntitySchema>;
export type BuildManifestInput = z.infer<typeof BuildManifestInputSchema>;

export interface ManifestTest {
  id: string;
  scenario: 'list' | 'detail' | 'form-submit' | 'edit' | 'delete' | 'permission-negative';
  page: string;
  role: string;
  fixture?: Record<string, unknown>;
  expectations: {
    httpStatus?: number[];
    noConsoleError?: boolean;
    rendersTestId?: string;
    redirectsTo?: string;
  };
}

export interface Manifest {
  generatedAt: string;
  module: string;
  appCode: string;
  tests: ManifestTest[];
}

export interface ValidationResult {
  valid: boolean;
  errors: string[];
  warnings: string[];
}

export interface GeneratedFile {
  path: string;
  content: string;
}
