/**
 * ui-polish/validate.ts — Args validation (Zod + projectPath sanity check).
 * No file I/O beyond verifying projectPath exists and looks like a web root.
 */
import { existsSync, statSync } from 'node:fs';
import path from 'node:path';
import { UiPolishArgsSchema, type UiPolishArgs } from './types.js';

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

export function validateArgs(raw: unknown): ArgsValidationResult {
  const parsed = UiPolishArgsSchema.safeParse(raw);
  if (!parsed.success) {
    return {
      valid: false,
      args: null,
      errors: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
    };
  }

  const args = parsed.data;
  const errors: string[] = [];

  // projectPath must exist and contain a `src` directory — refuse to scan arbitrary folders.
  const abs = path.resolve(args.projectPath);
  if (!existsSync(abs)) {
    errors.push(`projectPath does not exist: ${abs}`);
  } else if (!statSync(abs).isDirectory()) {
    errors.push(`projectPath is not a directory: ${abs}`);
  } else if (!existsSync(path.join(abs, 'src'))) {
    errors.push(`projectPath has no "src" folder — are you sure this is a React app root? ${abs}`);
  }

  // rules must look like Rxx tags (free-form allowed but we at least warn on obvious garbage).
  for (const ruleId of args.rules) {
    if (!/^R\d+(-[a-z0-9-]+)?$/.test(ruleId)) {
      errors.push(`rule id "${ruleId}" does not match /^R\\d+(-[a-z-]+)?$/ — expected e.g. "R1" or "R1-pagetemplate"`);
    }
  }

  // tokensFile, if provided, must exist.
  if (args.tokensFile) {
    const tokensAbs = path.resolve(args.tokensFile);
    if (!existsSync(tokensAbs)) {
      errors.push(`tokensFile does not exist: ${tokensAbs}`);
    }
  }

  // --url paths must look like URL paths (start with /).
  for (const u of args.urls) {
    if (!u.startsWith('/')) {
      errors.push(`--url path must start with /: ${u}`);
    }
  }

  // --page paths, if provided, must each exist, be a .tsx file, and live under projectPath.
  for (const p of args.paths) {
    const pageAbs = path.isAbsolute(p) ? p : path.join(abs, p);
    if (!existsSync(pageAbs)) {
      errors.push(`--page path does not exist: ${pageAbs}`);
    } else if (!statSync(pageAbs).isFile() || !pageAbs.endsWith('.tsx')) {
      errors.push(`--page path is not a .tsx file: ${pageAbs}`);
    } else if (!path.resolve(pageAbs).startsWith(path.resolve(abs))) {
      errors.push(`--page path is outside the project root: ${pageAbs}`);
    }
  }

  return { valid: errors.length === 0, args, errors };
}
