/**
 * ui-polish/types.ts — CLI args + finding + report shape for the UI audit
 * of a generated SmartStack web application.
 *
 * Source of truth for the rule catalogue is the sibling tokens.json — this
 * file only mirrors its shape as TypeScript types so audit.ts and apply.ts
 * can type-check the rule data they load at runtime.
 */
import { z } from 'zod';

export const UiPolishModeSchema = z.enum(['audit', 'apply']);
export type UiPolishMode = z.infer<typeof UiPolishModeSchema>;

export const UiPolishArgsSchema = z.object({
  /** Absolute path to the generated SmartStack web root (holds src/pages). */
  projectPath: z.string().min(1),
  /** `audit` = report only ; `apply` = mechanical rewrite of fixable findings. */
  mode: UiPolishModeSchema,
  /** Subset of rule IDs to run (e.g. `['R1', 'R3']`). Empty = all. */
  rules: z.array(z.string()).default([]),
  /**
   * Restrict the scan to these page file paths (relative to projectPath, or
   * absolute). Empty = discover every page under src/pages + src/features.
   * Lets the caller verify a single page (`--page src/pages/x/FooListPage.tsx`).
   */
  paths: z.array(z.string()).default([]),
  /**
   * URL paths (e.g. /administration/tenants/{id}) to resolve to component files
   * via PageRegistry.register() data in src/extensions/*Registry.ts.
   */
  urls: z.array(z.string()).default([]),
  /** Override path for tokens.json (defaults to skill-local copy). */
  tokensFile: z.string().optional(),
  /**
   * Regeneration threshold — in `apply` mode, any *Page.tsx file with ≥ this
   * many ERROR findings remaining after mechanical fixes is REBUILT from the
   * scaffold-component template (OVERWRITES the existing content). Default 3.
   * Set to 0 to disable regeneration and fall back to pure mechanical fixes.
   * Set to 1 to regenerate aggressively on any remaining error.
   */
  regenerateThreshold: z.number().int().min(0).max(100).default(3),
});

export type UiPolishArgs = z.infer<typeof UiPolishArgsSchema>;

// ─── Tokens JSON mirrors ──────────────────────────────────────────────────

export type Severity = 'error' | 'warning' | 'info';

export interface HardRule {
  id: string;
  description: string;
  violation: string;
  autoFixable: boolean;
  severity: Severity;
}

export interface TokensFile {
  version: string;
  sourceFile: string;
  extractedAt: string;
  hardRules: HardRule[];
  cssVariables: Record<string, unknown>;
  componentClasses: Record<string, { class: string; description?: string }>;
  sharedComponents: Record<string, unknown>;
  extensionPattern: Record<string, unknown>;
  importMap: Record<string, string>;
}

// ─── Audit report ─────────────────────────────────────────────────────────

export interface Finding {
  ruleId: string;
  severity: Severity;
  file: string;
  line?: number;
  message: string;
  autoFixable: boolean;
  /** Raw source snippet around the violation (for apply.ts to locate). */
  snippet?: string;
}

export interface AuditReport {
  projectPath: string;
  filesInspected: number;
  findings: Finding[];
  counts: {
    errors: number;
    warnings: number;
    infos: number;
  };
  byRule: Record<string, number>;
}

export interface ApplyReport extends AuditReport {
  /** Findings actually rewritten by apply.ts. */
  fixesApplied: number;
  /** Paths of files rewritten. */
  filesModified: string[];
  /** Findings that were auto-fixable but couldn't be rewritten (e.g. file parse error). */
  fixesSkipped: Finding[];
  /** Per-file regeneration verdicts emitted by the Phase 3 regen pass. */
  regenerations?: Array<{ file: string; regenerated: boolean; reason: string }>;
}

// ─── Output envelope ──────────────────────────────────────────────────────

export interface UiPolishOutput {
  success: boolean;
  command: 'ui-polish';
  data: {
    mode: UiPolishMode;
    rulesRun: string[];
    valid: boolean;
  };
  report: AuditReport | ApplyReport | null;
  filesModified: string[];
  errors: string[];
  warnings: string[];
  nextSteps: string[];
}
