/**
 * nexus-agents scaffold templates
 *
 * Template generators for each scaffold type. Each generator returns
 * an array of files with their paths and content.
 *
 * @module cli/scaffold-templates
 * (Source: Issue #653 - Scaffold command)
 */

import { toPascalCase, toCamelCase, toScreamingSnake } from './scaffold.js';

/** A file to be generated by scaffolding. */
export interface GeneratedFile {
  readonly path: string;
  readonly content: string;
}

/** Generates the imports and schema section of a tool file. */
function toolImportsAndSchema(name: string, pascal: string): string {
  return `/**
 * nexus-agents/mcp - ${pascal} Tool
 *
 * MCP tool for ${name} operations.
 *
 * @module mcp/tools/${name}
 * (Source: Issue #653 - Scaffolded)
 */

import { z } from 'zod';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import type { ILogger } from '../../core/index.js';
import { createLogger, formatZodError } from '../../core/index.js';
import type { RateLimiter } from '../middleware/rate-limiter.js';
import type { SecurityConfig } from '../../config/schemas.js';
import { wrapToolWithTimeout, toSdkCallback } from '../middleware/tool-wrapper.js';
import { createSecureHandler, type HandlerContext } from '../middleware/secure-handler.js';

/**
 * Input schema for ${name} tool.
 */
export const ${pascal}InputSchema = z.object({
  input: z.string().min(1).describe('Primary input for ${name} operation'),
  options: z.record(z.string(), z.unknown()).optional().describe('Additional options'),
});

export type ${pascal}Input = z.infer<typeof ${pascal}InputSchema>;

/**
 * Dependencies for ${name} tool.
 */
export interface ${pascal}Deps {
  logger?: ILogger;
  rateLimiter: RateLimiter;
  security?: SecurityConfig | undefined;
}
`;
}

/** Generates the handler and registration section of a tool file. */
function toolHandlerAndRegistration(name: string, pascal: string): string {
  return `
/**
 * Handles the ${name} tool execution.
 */
function create${pascal}Handler(deps: ${pascal}Deps) {
  return async (args: unknown, ctx: HandlerContext) => {
    const validated = ${pascal}InputSchema.safeParse(args);
    if (!validated.success) {
      return {
        isError: true,
        content: [{ type: 'text' as const, text: \`Validation error: \${formatZodError(validated.error)}\` }],
      };
    }

    ctx.logger.debug('Executing ${name}', { input: validated.data.input });

    const output = { status: 'ok', input: validated.data.input };
    return {
      content: [{ type: 'text' as const, text: JSON.stringify(output, null, 2) }],
    };
  };
}

/**
 * Registers the ${name} tool with the MCP server.
 */
export function register${pascal}Tool(server: McpServer, deps: ${pascal}Deps): void {
  const logger = deps.logger ?? createLogger({ tool: '${name}' });
  const toolSchema = {
    input: z.string().min(1).describe('Input for ${name}'),
  };

  const description = '${pascal} tool for ${name} operations.';

  const secureHandler = createSecureHandler(create${pascal}Handler(deps), {
    toolName: '${name}',
    rateLimiter: deps.rateLimiter,
    logger,
  });

  const timeoutMs = deps.security?.timeout?.defaultTimeoutMs;
  const wrappedHandler = wrapToolWithTimeout(
    '${name}',
    secureHandler,
    timeoutMs !== undefined ? { timeoutMs, logger } : { logger }
  );

  server.registerTool(
    '${name}',
    { description, inputSchema: toolSchema },
    toSdkCallback(wrappedHandler)
  );
  logger.info('Registered ${name} tool');
}
`;
}

/** Generates MCP tool source file content. */
function toolSourceContent(name: string, pascal: string): string {
  return toolImportsAndSchema(name, pascal) + toolHandlerAndRegistration(name, pascal);
}

/** Generates MCP tool test file content. */
function toolTestContent(name: string, pascal: string): string {
  return `/**
 * Tests for ${name} tool.
 * (Source: Issue #653 - Scaffolded)
 */

import { describe, it, expect } from 'vitest';
import { ${pascal}InputSchema } from './${name}.js';

describe('${pascal} Tool', () => {
  describe('${pascal}InputSchema', () => {
    it('should validate valid input', () => {
      const result = ${pascal}InputSchema.safeParse({ input: 'test' });
      expect(result.success).toBe(true);
    });

    it('should reject empty input', () => {
      const result = ${pascal}InputSchema.safeParse({ input: '' });
      expect(result.success).toBe(false);
    });
  });
});
`;
}

/** Generates MCP tool files (source + test). */
export function generateToolFiles(name: string): GeneratedFile[] {
  const pascal = toPascalCase(name);
  return [
    { path: `src/mcp/tools/${name}.ts`, content: toolSourceContent(name, pascal) },
    { path: `src/mcp/tools/${name}.test.ts`, content: toolTestContent(name, pascal) },
  ];
}

/** Generates expert knowledge module files. */
export function generateExpertFiles(name: string): GeneratedFile[] {
  const pascal = toPascalCase(name);
  const screaming = toScreamingSnake(name);
  return [
    {
      path: `src/agents/experts/knowledge/${name}/index.ts`,
      content: `/**
 * ${pascal} Expert Knowledge Module
 *
 * Domain-specific knowledge for the ${name} expert.
 *
 * @module agents/experts/knowledge/${name}
 * (Source: Issue #653 - Scaffolded)
 */

/**
 * ${pascal} domain knowledge patterns.
 */
export const ${screaming}_PATTERNS = [
  'Analyze ${name} requirements before implementation',
  'Validate ${name} outputs against acceptance criteria',
  'Document ${name} decisions and trade-offs',
] as const;

/**
 * ${pascal} best practices.
 */
export const ${screaming}_BEST_PRACTICES = [
  'Follow single-responsibility principle for ${name} components',
  'Write tests before implementing ${name} logic',
  'Use structured error handling with Result types',
] as const;
`,
    },
  ];
}

/** Generates workflow template files. */
export function generateWorkflowFiles(name: string): GeneratedFile[] {
  return [
    {
      path: `src/workflows/templates/${name}.yaml`,
      content: `# ${name} Workflow Template
# (Source: Issue #653 - Scaffolded)
#
# Executes a ${name} analysis and generates a report.
#
name: "${name}"
version: "1.0.0"
description: "Analyze and report on ${name} targets."

inputs:
  target:
    type: string
    description: "Target for the workflow"
    default: "."

steps:
  - id: "analyze"
    name: "Analyze"
    agent: "code_expert"
    prompt: |
      Analyze the target: {{target}}
      Identify key findings, potential issues, and recommendations.
    timeout: 120

  - id: "report"
    name: "Generate Report"
    agent: "documentation_expert"
    dependsOn: ["analyze"]
    prompt: |
      Generate a report based on the analysis.
      Analysis: {{steps.analyze.output}}
    timeout: 60

timeout: 300
`,
    },
  ];
}

/** Generates CLI command source file content. */
function commandSourceContent(name: string, pascal: string, camel: string): string {
  return `/**
 * nexus-agents ${name} command
 *
 * CLI command for ${name} operations.
 *
 * @module cli/${name}
 * (Source: Issue #653 - Scaffolded)
 */

export interface ${pascal}Options {
  readonly verbose?: boolean;
}

export interface ${pascal}Result {
  readonly success: boolean;
  readonly message: string;
}

/**
 * Runs the ${name} command logic.
 */
export function run${pascal}(options: ${pascal}Options): ${pascal}Result {
  if (options.verbose === true) {
    process.stdout.write('Running ${name} in verbose mode...\\n');
  }
  return { success: true, message: '${pascal} completed successfully.' };
}

/**
 * Prints the ${name} result to stdout.
 */
export function print${pascal}Result(result: ${pascal}Result): void {
  process.stdout.write(result.message + '\\n');
}

/**
 * Main command entry point. Returns exit code.
 */
export function ${camel}Command(options: ${pascal}Options): number {
  const result = run${pascal}(options);
  print${pascal}Result(result);
  return result.success ? 0 : 1;
}
`;
}

/** Generates CLI command test file content. */
function commandTestContent(name: string, pascal: string, camel: string): string {
  return `/**
 * Tests for ${name} command.
 * (Source: Issue #653 - Scaffolded)
 */

import { describe, it, expect, vi } from 'vitest';
import { run${pascal}, ${camel}Command } from './${name}.js';

describe('${pascal} Command', () => {
  describe('run${pascal}()', () => {
    it('should return success', () => {
      const result = run${pascal}({});
      expect(result.success).toBe(true);
    });
  });

  describe('${camel}Command()', () => {
    it('should return 0 for success', () => {
      vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
      const exitCode = ${camel}Command({});
      expect(exitCode).toBe(0);
    });
  });
});
`;
}

/** Generates CLI command files (source + test). */
export function generateCommandFiles(name: string): GeneratedFile[] {
  const pascal = toPascalCase(name);
  const camel = toCamelCase(name);
  return [
    { path: `src/cli/${name}.ts`, content: commandSourceContent(name, pascal, camel) },
    { path: `src/cli/${name}.test.ts`, content: commandTestContent(name, pascal, camel) },
  ];
}
