/**
 * cli:scaffold-routes — types.ts
 *
 * componentKey segment rule: each segment must be lowercase alphanumeric,
 * may contain internal hyphens but must start with a letter. Dots are the
 * separator between hierarchy levels and cannot appear inside a segment.
 */
import { z } from 'zod'

const SEGMENT_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/

export const RouteEntitySchema = z.object({
  name: z.string().min(1).regex(/^[A-Z][A-Za-z0-9]*$/, 'Entity name must be PascalCase'),
  /**
   * Optional explicit plural (`Categories` for `Category`, `Rues` for `Rue`).
   * When omitted, the CLI falls back to `${name}s` — fine for regular plurals
   * but wrong for entities whose plural ends in `ies`/`-es`/`ues`. Callers
   * passing this through the BA pipeline use the BA-declared plural verbatim.
   */
  pluralName: z
    .string()
    .min(1)
    .regex(/^[A-Z][A-Za-z0-9]*$/, 'pluralName must be PascalCase')
    .optional(),
  section: z.string().min(1).regex(SEGMENT_REGEX, 'Section must be kebab-case and start with a letter'),
  /**
   * Optional kebab parent for sub-resources. When set the entity is nested
   * one extra level deep:
   *   - componentKey   →  `{app}.{module}.{parentSection}.{section}[.{view}]`
   *   - default page   →  `@/pages/{app}/{module}/{parentSection}/{section}`
   *   - URL helper     →  `/{app}/{module}/{parentSection}/{section}`
   *
   * Mirrors how the SmartStack navigation DB stores 4-segment keys for nested
   * resources (e.g. `gaf.referentiels.types-affaire.types-audit`). Without
   * this field, the CLI emitted a flat 3-segment key that DynamicRouter could
   * not resolve, leaving the page on a perpetual spinner.
   */
  parentSection: z
    .string()
    .min(1)
    .regex(SEGMENT_REGEX, 'parentSection must be kebab-case and start with a letter')
    .optional(),
  views: z.array(z.enum([
    'list', 'detail', 'create', 'edit',
    'dashboard', 'kanban',
    // Bug 7 fix — reconduction is the bulk-renewal pattern (AFFAIRES/Demande
    // and other workflow-driven entities). Page lives at
    // `${section}/reconduction`; componentKey `app.module[.parent].section.reconduction`.
    'reconduction',
    'app-home', 'module-home', 'section-home',
  ])).default(['list', 'detail', 'create']),
  /**
   * Optional per-view file path overrides. When provided, scaffold-routes
   * uses these for the lazy import paths instead of deriving from
   * `@/pages/{appCode}/{module}/{section}/`. Source: `pageSpec.filePath` from the PRD.
   * Lets the registry stay aligned with whatever directory the project
   * actually uses (e.g. legacy `pages/budgeting/` vs canonical
   * `pages/budgets/`) without forcing a folder rename.
   *
   * Keys: 'list', 'detail', 'create', 'edit'.
   * Values: relative path from project root to the .tsx file
   * (e.g. 'src/pages/budgeting/budgets/BudgetsListPage.tsx').
   */
  pageFilePaths: z.record(z.string()).optional(),
})

export const ScaffoldRoutesInputSchema = z.object({
  module: z.string().min(1).regex(SEGMENT_REGEX, 'Module must be kebab-case and start with a letter'),
  appCode: z.string().min(1).regex(SEGMENT_REGEX, 'appCode must be kebab-case and start with a letter'),
  entities: z.array(RouteEntitySchema).min(1),
  projectPath: z.string().min(1),
})

export type RouteEntity = z.infer<typeof RouteEntitySchema>
export type ScaffoldRoutesInput = z.infer<typeof ScaffoldRoutesInputSchema>
export interface GeneratedFile { path: string; content: string }
export interface ValidationResult { valid: boolean; errors: string[]; warnings: string[] }

/**
 * Validate a fully-assembled componentKey against SmartStack's DynamicRouter
 * resolution contract. Returns null if valid, or an explanation string.
 *
 * Rules:
 *  - 2 to 5 dot-separated segments:
 *      `app.module`                                       (module-home hub)
 *      `app.module.section`                               (section root / list view)
 *      `app.module.section.view`                          (detail/edit/create)
 *      `app.module.parentSection.section`                 (sub-resource list)
 *      `app.module.parentSection.section.view`            (sub-resource detail/edit/create)
 *  - each segment matches SEGMENT_REGEX
 *  - final segment may be one of the IMPLICIT_SUFFIXES for view-specific
 *    registrations (detail, edit, create, new, duplicate, settings, configure,
 *    permissions, members, history, logs, analytics, preview, versions,
 *    comments, attachments, audit, export, notifications, schedule, workflow,
 *    summary, test, runs, import) — the emitted key itself is fine in any
 *    form, but the suffix is how DynamicRouter auto-generates `/:id/edit`
 *    etc. Mismatches produce silent spinners at runtime.
 *
 * The 5-segment form was added in 2026-05-27 to support nested resources
 * whose navigation DB key carries a parent section (e.g.
 * `gaf.referentiels.types-affaire.types-audit.detail`).
 */
export function validateComponentKey(key: string): string | null {
  const parts = key.split('.')
  if (parts.length < 2 || parts.length > 5) {
    return `componentKey '${key}' has ${parts.length} segments — must be between 2 and 5 (app.module[.parentSection].section[.view])`
  }
  for (const [i, part] of parts.entries()) {
    if (!SEGMENT_REGEX.test(part)) {
      return `componentKey '${key}' segment ${i} ('${part}') is invalid — must be kebab-case and start with a letter`
    }
  }
  return null
}
