/**
 * Base Documentation Template
 * Abstract class for all documentation templates
 */

import { DocumentationIntent } from '../../../types/workflow';
import { ComponentVersions } from '../../utils/version-discovery';

export interface TemplateContext {
  intent: DocumentationIntent;
  workflow: any;
  extendedWorkflow: any;
  versions: ComponentVersions;
  outputDirectory: string;
}

export abstract class DocumentationTemplate {
  /**
   * Generate documentation content from intent
   */
  abstract generate(context: TemplateContext): string;

  /**
   * Check if this template can handle the given intent
   */
  abstract canHandle(intent: DocumentationIntent): boolean;

  /**
   * Get output filename for this documentation
   */
  getOutputPath(intent: DocumentationIntent): string {
    if (intent.outputPath) {
      return intent.outputPath;
    }

    // Default path based on type and scope
    const filename = intent.scope
      ? `${intent.type}-${this.slugify(intent.scope)}.md`
      : `${intent.type}.md`;

    return filename;
  }

  /**
   * Helper: Convert string to slug
   */
  protected slugify(text: string): string {
    return text
      .toLowerCase()
      .replace(/[^\w\s-]/g, '')
      .replace(/\s+/g, '-')
      .replace(/-+/g, '-')
      .trim();
  }

  /**
   * Helper: Capitalize first letter
   */
  protected capitalize(text: string): string {
    return text.charAt(0).toUpperCase() + text.slice(1);
  }

  /**
   * Helper: Get technology display name
   */
  protected getTechnologyName(technology: string): string {
    const names: Record<string, string> = {
      react: 'React',
      express: 'Express',
      'typescript-express': 'Express.js',
      prisma: 'Prisma',
      clerk: 'Clerk',
      auth0: 'Auth0',
      postgresql: 'PostgreSQL',
      mysql: 'MySQL',
      mongodb: 'MongoDB',
      redis: 'Redis',
    };

    return names[technology] || this.capitalize(technology);
  }

  /**
   * Helper: Format version for display
   */
  protected formatVersion(version: string): string {
    return version.replace(/^[\^~>=<]+/, '');
  }

  /**
   * Helper: Generate footer with generation metadata
   */
  protected generateFooter(context: TemplateContext): string {
    const { workflow } = context;
    let footer = '\n---\n\n';

    // Add version information if available
    const techVersions = this.getRelevantVersions(context);
    if (techVersions.length > 0) {
      footer += `*Auto-generated based on: ${techVersions.join(', ')}*\n\n`;
    }

    footer += `*Generated from workflow: ${workflow.workflow.id} v${workflow.workflow.version}*\n`;

    return footer;
  }

  /**
   * Helper: Get relevant technology versions for footer
   */
  private getRelevantVersions(context: TemplateContext): string[] {
    const { versions, extendedWorkflow } = context;
    const techVersions: string[] = [];

    // Add frontend framework version
    if (extendedWorkflow?.technology?.frontend?.framework) {
      const framework = extendedWorkflow.technology.frontend.framework;
      const version = this.getVersionForFramework(framework, versions);
      if (version) {
        techVersions.push(`${this.getTechnologyName(framework)} ${this.formatVersion(version)}`);
      }
    }

    // Add backend framework version
    if (extendedWorkflow?.technology?.backend?.framework) {
      const framework = extendedWorkflow.technology.backend.framework;
      const version = this.getVersionForFramework(framework, versions);
      if (version) {
        techVersions.push(`${this.getTechnologyName(framework)} ${this.formatVersion(version)}`);
      }
    }

    // Add auth provider version
    if (extendedWorkflow?.auth?.provider) {
      const provider = extendedWorkflow.auth.provider;
      const version = this.getVersionForAuth(provider, versions);
      if (version) {
        techVersions.push(`${this.getTechnologyName(provider)} ${this.formatVersion(version)}`);
      }
    }

    return techVersions;
  }

  /**
   * Helper: Get version for a framework
   */
  private getVersionForFramework(framework: string, versions: ComponentVersions): string | undefined {
    const packageNames: Record<string, string> = {
      react: 'react',
      express: 'express',
      fastify: 'fastify',
      nestjs: '@nestjs/core',
    };

    const packageName = packageNames[framework];
    if (!packageName) return undefined;

    // Search all components
    for (const versionMap of Object.values(versions)) {
      if (!versionMap) continue;
      const version = versionMap.dependencies[packageName] || versionMap.devDependencies[packageName];
      if (version) return version;
    }

    return undefined;
  }

  /**
   * Helper: Get version for auth provider
   */
  private getVersionForAuth(provider: string, versions: ComponentVersions): string | undefined {
    const packageNames: Record<string, string> = {
      clerk: '@clerk/express',
      auth0: 'express-oauth2-jwt-bearer',
    };

    const packageName = packageNames[provider];
    if (!packageName) return undefined;

    // Search all components
    for (const versionMap of Object.values(versions)) {
      if (!versionMap) continue;
      const version = versionMap.dependencies[packageName] || versionMap.devDependencies[packageName];
      if (version) return version;
    }

    return undefined;
  }
}
