/**
 * Best Practices Documentation Template
 * Generates coding standards, conventions, and best practices specific to the technology stack
 */

import { DocumentationIntent } from '../../../types/workflow';
import { DocumentationTemplate, TemplateContext } from './base-template';

export class BestPracticesTemplate extends DocumentationTemplate {
  canHandle(intent: DocumentationIntent): boolean {
    return intent.type === 'best_practices';
  }

  generate(context: TemplateContext): string {
    const { workflow, extendedWorkflow } = context;

    let content = `# Best Practices\n\n`;

    if (workflow.workflow.description) {
      content += `Best practices and coding standards for ${workflow.workflow.name}.\n\n`;
    }

    // General principles
    content += this.generateGeneralPrinciples(context);

    // Technology-specific practices
    if (extendedWorkflow?.technology?.backend) {
      content += this.generateBackendPractices(context);
    }

    if (extendedWorkflow?.technology?.frontend) {
      content += this.generateFrontendPractices(context);
    }

    if (extendedWorkflow?.technology?.database) {
      content += this.generateDatabasePractices(context);
    }

    // API practices
    if (extendedWorkflow?.api) {
      content += this.generateApiPractices(context);
    }

    // Security practices
    if (extendedWorkflow?.auth?.enabled) {
      content += this.generateSecurityPractices(context);
    }

    // Testing practices
    if (extendedWorkflow?.technology?.testing) {
      content += this.generateTestingPractices(context);
    }

    // Git workflow
    content += this.generateGitPractices(context);

    content += this.generateFooter(context);

    return content;
  }

  private generateGeneralPrinciples(_context: TemplateContext): string {
    let content = `## General Principles\n\n`;

    content += `### Code Quality\n\n`;
    content += `- Write clean, readable, and maintainable code\n`;
    content += `- Follow DRY (Don't Repeat Yourself) principle\n`;
    content += `- Keep functions small and focused on a single responsibility\n`;
    content += `- Use meaningful variable and function names\n`;
    content += `- Add comments for complex logic, but prefer self-documenting code\n\n`;

    content += `### Project Structure\n\n`;
    content += `- Organize code by feature or domain, not by file type\n`;
    content += `- Keep related files close together\n`;
    content += `- Separate business logic from infrastructure code\n`;
    content += `- Use clear directory naming conventions\n\n`;

    content += `### Error Handling\n\n`;
    content += `- Always handle errors explicitly\n`;
    content += `- Use try-catch blocks for asynchronous operations\n`;
    content += `- Provide meaningful error messages\n`;
    content += `- Log errors with appropriate context\n`;
    content += `- Don't silently fail or swallow errors\n\n`;

    return content;
  }

  private generateBackendPractices(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const backend = extendedWorkflow?.technology?.backend;

    if (!backend) return '';

    let content = `## Backend Best Practices\n\n`;

    // TypeScript/Express specific
    if (backend.language === 'typescript' && backend.framework === 'express') {
      content += `### TypeScript/Express\n\n`;
      content += `**Type Safety:**\n`;
      content += `- Always define explicit types for function parameters and return values\n`;
      content += `- Avoid using \`any\` type; use \`unknown\` if type is truly unknown\n`;
      content += `- Use interfaces for object shapes\n`;
      content += `- Enable strict mode in \`tsconfig.json\`\n\n`;

      content += `**Middleware:**\n`;
      content += `- Keep middleware functions focused and composable\n`;
      content += `- Use middleware for cross-cutting concerns (auth, logging, validation)\n`;
      content += `- Always call \`next()\` or send a response\n`;
      content += `- Use error-handling middleware for centralized error handling\n\n`;

      content += `**Route Handlers:**\n`;
      content += `- Keep route handlers thin; delegate to service layer\n`;
      content += `- Use async/await for asynchronous operations\n`;
      content += `- Validate request data before processing\n`;
      content += `- Return consistent response formats\n\n`;
    }

    // Python/Flask specific
    if (backend.language === 'python' && backend.framework === 'flask') {
      content += `### Python/Flask\n\n`;
      content += `**Code Style:**\n`;
      content += `- Follow PEP 8 style guide\n`;
      content += `- Use type hints for function signatures\n`;
      content += `- Write docstrings for all public functions and classes\n`;
      content += `- Use list comprehensions where appropriate\n\n`;

      content += `**Blueprints:**\n`;
      content += `- Organize routes using Flask Blueprints\n`;
      content += `- Keep blueprints focused on a single domain\n`;
      content += `- Register blueprints with URL prefixes\n\n`;

      content += `**Decorators:**\n`;
      content += `- Use decorators for authentication and authorization\n`;
      content += `- Create custom decorators for repeated patterns\n`;
      content += `- Keep decorators simple and composable\n\n`;
    }

    // ORM practices
    if (backend.orm) {
      content += `### ${this.capitalize(backend.orm)} Best Practices\n\n`;

      if (backend.orm === 'prisma') {
        content += `- Use Prisma migrations for schema changes\n`;
        content += `- Always use transactions for multiple related operations\n`;
        content += `- Use \`select\` to fetch only needed fields\n`;
        content += `- Leverage relation loading to avoid N+1 queries\n`;
        content += `- Use database indexes for frequently queried fields\n\n`;
      } else {
        content += `- Use migrations for all schema changes\n`;
        content += `- Implement proper connection pooling\n`;
        content += `- Use query optimization techniques\n`;
        content += `- Avoid N+1 query problems\n\n`;
      }
    }

    return content;
  }

  private generateFrontendPractices(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const frontend = extendedWorkflow?.technology?.frontend;

    if (!frontend) return '';

    let content = `## Frontend Best Practices\n\n`;

    // React specific
    if (frontend.framework === 'react') {
      content += `### React Best Practices\n\n`;
      content += `**Component Design:**\n`;
      content += `- Keep components small and focused\n`;
      content += `- Use functional components with hooks\n`;
      content += `- Extract reusable logic into custom hooks\n`;
      content += `- Prefer composition over inheritance\n`;
      content += `- Use prop-types or TypeScript for prop validation\n\n`;

      content += `**State Management:**\n`;
      content += `- Keep state as close to where it's used as possible\n`;
      content += `- Lift state up only when necessary\n`;
      content += `- Use Context API for global state\n`;
      content += `- Consider useReducer for complex state logic\n`;
      content += `- Avoid unnecessary re-renders with React.memo and useCallback\n\n`;

      content += `**Hooks:**\n`;
      content += `- Follow the Rules of Hooks\n`;
      content += `- Keep hooks at the top level of components\n`;
      content += `- Specify dependencies correctly in useEffect\n`;
      content += `- Clean up side effects in useEffect return functions\n\n`;

      content += `**Performance:**\n`;
      content += `- Code-split routes and large components\n`;
      content += `- Lazy load images and heavy components\n`;
      content += `- Memoize expensive calculations with useMemo\n`;
      content += `- Use virtualization for long lists\n\n`;
    }

    // Styling practices
    if (frontend.styling) {
      content += `### Styling with ${this.capitalize(frontend.styling)}\n\n`;

      if (frontend.styling === 'tailwind') {
        content += `- Use utility classes for styling\n`;
        content += `- Extract common patterns into components\n`;
        content += `- Use @apply sparingly; prefer utilities\n`;
        content += `- Configure theme in tailwind.config.js\n`;
        content += `- Use responsive modifiers consistently\n\n`;
      } else {
        content += `- Keep styles modular and scoped to components\n`;
        content += `- Use CSS variables for theming\n`;
        content += `- Follow a consistent naming convention\n`;
        content += `- Avoid deeply nested selectors\n\n`;
      }
    }

    return content;
  }

  private generateDatabasePractices(_context: TemplateContext): string {
    let content = `## Database Best Practices\n\n`;

    content += `### Schema Design\n\n`;
    content += `- Normalize data to reduce redundancy\n`;
    content += `- Use appropriate data types for each field\n`;
    content += `- Add indexes to frequently queried columns\n`;
    content += `- Use foreign keys to maintain referential integrity\n`;
    content += `- Consider soft deletes for important records\n\n`;

    content += `### Queries\n\n`;
    content += `- Write efficient queries that fetch only needed data\n`;
    content += `- Use prepared statements to prevent SQL injection\n`;
    content += `- Batch operations when possible\n`;
    content += `- Use transactions for related operations\n`;
    content += `- Monitor slow queries and optimize\n\n`;

    content += `### Migrations\n\n`;
    content += `- Always use migrations for schema changes\n`;
    content += `- Never modify existing migrations after deployment\n`;
    content += `- Test migrations on staging before production\n`;
    content += `- Write reversible migrations when possible\n`;
    content += `- Include data migrations when schema changes affect data\n\n`;

    return content;
  }

  private generateApiPractices(_context: TemplateContext): string {
    let content = `## API Best Practices\n\n`;

    content += `### RESTful Design\n\n`;
    content += `- Use appropriate HTTP methods (GET, POST, PUT, PATCH, DELETE)\n`;
    content += `- Use plural nouns for resource endpoints (/users, not /user)\n`;
    content += `- Use nested routes for related resources (/users/:id/posts)\n`;
    content += `- Return appropriate HTTP status codes\n`;
    content += `- Version your API (/api/v1/...)\n\n`;

    content += `### Request/Response\n\n`;
    content += `- Validate all input data\n`;
    content += `- Return consistent JSON response formats\n`;
    content += `- Include error details in error responses\n`;
    content += `- Use pagination for list endpoints\n`;
    content += `- Support filtering and sorting where appropriate\n\n`;

    content += `### Status Codes\n\n`;
    content += `- **200 OK:** Successful GET, PUT, PATCH, DELETE\n`;
    content += `- **201 Created:** Successful POST\n`;
    content += `- **204 No Content:** Successful request with no response body\n`;
    content += `- **400 Bad Request:** Invalid request data\n`;
    content += `- **401 Unauthorized:** Authentication required\n`;
    content += `- **403 Forbidden:** Insufficient permissions\n`;
    content += `- **404 Not Found:** Resource doesn't exist\n`;
    content += `- **500 Internal Server Error:** Server error\n\n`;

    return content;
  }

  private generateSecurityPractices(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const auth = extendedWorkflow?.auth;

    let content = `## Security Best Practices\n\n`;

    content += `### Authentication\n\n`;
    content += `- Never store passwords in plain text\n`;
    content += `- Use strong hashing algorithms (bcrypt, Argon2)\n`;
    content += `- Implement password strength requirements\n`;
    content += `- Use secure session management\n`;
    content += `- Implement rate limiting on auth endpoints\n\n`;

    content += `### Authorization\n\n`;
    content += `- Always verify user permissions before actions\n`;
    content += `- Implement role-based access control (RBAC)\n`;
    content += `- Use ownership checks for user-specific resources\n`;
    content += `- Deny by default; explicitly grant permissions\n\n`;

    content += `### API Security\n\n`;
    content += `- Use HTTPS in production\n`;
    content += `- Validate and sanitize all input\n`;
    content += `- Implement CORS correctly\n`;
    content += `- Use security headers (HSTS, CSP, X-Frame-Options)\n`;
    content += `- Keep dependencies up to date\n\n`;

    if (auth?.provider === 'clerk') {
      content += `### Clerk-Specific\n\n`;
      content += `- Store Clerk API keys in environment variables\n`;
      content += `- Use middleware for route protection\n`;
      content += `- Verify tokens on the backend\n`;
      content += `- Handle authentication errors gracefully\n\n`;
    }

    content += `### Environment Variables\n\n`;
    content += `- Never commit secrets to version control\n`;
    content += `- Use \`.env\` files for local development\n`;
    content += `- Use environment-specific configurations\n`;
    content += `- Rotate secrets regularly\n\n`;

    return content;
  }

  private generateTestingPractices(_context: TemplateContext): string {
    let content = `## Testing Best Practices\n\n`;

    content += `### Unit Tests\n\n`;
    content += `- Test individual functions in isolation\n`;
    content += `- Mock external dependencies\n`;
    content += `- Write tests before fixing bugs (TDD)\n`;
    content += `- Aim for high code coverage\n`;
    content += `- Keep tests fast and focused\n\n`;

    content += `### Integration Tests\n\n`;
    content += `- Test component interactions\n`;
    content += `- Use test databases for data operations\n`;
    content += `- Clean up test data after each test\n`;
    content += `- Test error scenarios\n\n`;

    content += `### E2E Tests\n\n`;
    content += `- Test critical user flows\n`;
    content += `- Use stable selectors\n`;
    content += `- Keep E2E tests independent\n`;
    content += `- Run in CI/CD pipeline\n\n`;

    content += `### Test Organization\n\n`;
    content += `- Place tests near the code they test\n`;
    content += `- Use descriptive test names\n`;
    content += `- Follow AAA pattern (Arrange, Act, Assert)\n`;
    content += `- Group related tests with describe blocks\n\n`;

    return content;
  }

  private generateGitPractices(_context: TemplateContext): string {
    let content = `## Git Workflow\n\n`;

    content += `### Branches\n\n`;
    content += `- Use feature branches for new development\n`;
    content += `- Branch naming: \`feature/description\`, \`fix/description\`\n`;
    content += `- Keep main/master branch deployable\n`;
    content += `- Delete branches after merging\n\n`;

    content += `### Commits\n\n`;
    content += `- Write clear, descriptive commit messages\n`;
    content += `- Use present tense ("Add feature" not "Added feature")\n`;
    content += `- Make atomic commits (one logical change per commit)\n`;
    content += `- Reference issue numbers in commits\n\n`;

    content += `### Pull Requests\n\n`;
    content += `- Write descriptive PR titles and descriptions\n`;
    content += `- Keep PRs focused and reasonably sized\n`;
    content += `- Request reviews from team members\n`;
    content += `- Address review comments promptly\n`;
    content += `- Ensure CI passes before merging\n\n`;

    return content;
  }
}
