/**
 * audit-dev-api / types.ts — CLI args + finding + report shapes.
 *
 * MVP scope: this CLI implements the pagespec ↔ controller cross-check rules
 * (DEV-API-010 / DEV-API-011) only — those that need deterministic execution
 * because they serve as the Phase 2 gate of `/ba-develop`. The other rules
 * (DEV-API-001..009) remain conversational (Claude reads / greps via the
 * skill SKILL.md verbatim).
 *
 * Output envelope shape mirrors `audit-dev-frontend/cli/audit-dev-frontend/types.ts`
 * so the Studio audit-reports UI can render both audits with the same renderer.
 */
import { z } from 'zod'

export const AuditDevApiModeSchema = z.enum(['audit', 'apply'])
export type AuditDevApiMode = z.infer<typeof AuditDevApiModeSchema>

export const AuditDevApiArgsSchema = z.object({
  /** Absolute path to the .NET backend root (holds src/<Ns>.Api/Controllers/**). */
  backendPath: z.string().min(1),
  /**
   * Absolute path to the module folder inside `.smartstack/ba/<APP>/<MODULE>`.
   * The CLI loads every `pagespecs/*.md` directly under this folder.
   */
  modulePath: z.string().min(1),
  /** `audit` = report only ; `apply` is a stub for parity with frontend (no-op in MVP). */
  mode: AuditDevApiModeSchema.default('audit'),
  /** Active module code (PRD scope). */
  moduleCode: z.string().min(1),
  /** Active application code (PRD scope). */
  appCode: z.string().min(1),
  /** Subset of rule codes to run (e.g. ['DEV-API-010']). Empty = all implemented rules. */
  rules: z.array(z.string()).default([]),
})

export type AuditDevApiArgs = z.infer<typeof AuditDevApiArgsSchema>

// ─── Finding (mirrors audit-dev-frontend shape) ──────────────────────────

export type Severity = 'err' | 'warn' | 'ok'

export interface Finding {
  /** Always 'devApi' for this skill. */
  dimension: 'devApi'
  /** Rule code, e.g. 'DEV-API-010'. */
  code: string
  severity: Severity
  /** Display label, e.g. 'DEV_API_010_err'. */
  label: string
  /** Rule-specific data (rendered into the solution / UI). */
  params: Record<string, unknown>
  /** Mandatory on err/warn — user-facing remediation. */
  solution: string
  /** Optional skill name to delegate the fix to. */
  fixSkill?: string
  /** Optional phase key to re-run. */
  fixPhaseKey?: string
  /** Optional file path (relative to backendPath) for orchestrator UI navigation. */
  file?: string
}

// ─── Internal inventory shapes ───────────────────────────────────────────

/** One pagespec action of `kind:"api"` after normalisation. */
export interface PageActionEntry {
  file: string
  entity: string
  module: string
  section: string
  code: string
  /** kebab-case URL segment — the source of truth. */
  endpoint: string
  httpMethod: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
  scope: 'row' | 'bulk' | 'header'
  ucReference?: string
}

/** A `[HttpVerb("...")]` declaration on a `*Controller.cs`. */
export interface ControllerEndpointEntry {
  /** Lowercase verb: `get` / `post` / `put` / `patch` / `delete`. */
  verb: string
  /** Route path relative to the controller mount, normalised. */
  routePath: string
  /** Controller file path relative to backendPath. */
  file: string
  /** Inferred entity (from `I<Entity>Service` field, fallback singularize(filename)). */
  entity: string
  /** Strata: 'integration' (under Controllers/{Module}/) or 'screens' (under Controllers/{Module}/Screens/). */
  stratum: 'integration' | 'screens'
  /** Class-level mount route (from [Route(...)] on the class). Used to disambiguate
   *  shared verb+path pairs across strata that share an entity. */
  classRoute: string
  /** Injected service interface name (e.g. "IOpportunityService"). Used by DEV-API-014
   *  to detect cross-strata service mismatch. */
  injectedService: string | null
}

/** One pagespec read by the screen-driven matcher (DEV-API-012). Records the
 *  view + the entity so the rule can verify a matching endpoint exists on
 *  the corresponding `{EntityPlural}ScreenController.cs`. */
export interface PageScreenEntry {
  file: string
  entity: string
  module: string
  section: string
  view: 'list' | 'detail' | 'form' | 'dashboard' | 'kanban' | 'card' | 'app-home' | 'module-home' | 'section-home'
  screenCode: string
}

/** A `// TODO[SCREEN-<screenCode>]:` marker found in a screen controller (DEV-API-013). */
export interface ScreenTodoEntry {
  file: string
  line: number
  marker: string
}

// ─── Reports ─────────────────────────────────────────────────────────────

export interface AuditReport {
  scope: 'devApi'
  applicationCode: string
  moduleCode: string
  modulePath: string
  backendPath: string
  filesInspected: number
  findings: Finding[]
  counts: { errors: number; warnings: number; oks: number }
  byRule: Record<string, number>
  /** Markdown rendering, written to disk and embedded in stdout when requested. */
  markdown: string
}

export interface AuditDevApiOutput {
  success: boolean
  command: 'audit-dev-api'
  data: {
    mode: AuditDevApiMode
    rulesRun: string[]
    valid: boolean
  }
  report: AuditReport | null
  auditReport: {
    scope: 'devApi'
    applicationCode: string
    moduleCode: string
    findings: Array<Pick<Finding, 'dimension' | 'code' | 'severity' | 'label' | 'params' | 'solution' | 'fixSkill' | 'fixPhaseKey'>>
  } | null
  filesModified: string[]
  errors: string[]
  warnings: string[]
  nextSteps: string[]
}

export interface ArgsValidationResult {
  valid: boolean
  args: AuditDevApiArgs | null
  errors: string[]
}
