"""
Generators for creating documentation files from analyzed project data.
"""

import json
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, Optional

if TYPE_CHECKING:
    from .analyzer import ProjectAnalyzer

from .utils import extract_intent_context, format_project_name
from .templates.template_loader import TemplateLoader
from .diagram_generator import DiagramGenerator as MermaidDiagramGenerator, DiagramConfig


class BaseGenerator:
    """Base class for all generators."""
    
    def __init__(self, analyzer: 'ProjectAnalyzer'):
        """
        Initialize the generator.
        
        Args:
            analyzer: ProjectAnalyzer instance with discovered components
        """
        self.analyzer = analyzer
        self.date = datetime.now().strftime("%Y-%m-%d")
        self.datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    def generate(self, *args, **kwargs) -> str:
        """
        Generate the document.
        
        Returns:
            Generated document as string
        """
        raise NotImplementedError("Subclasses must implement generate()")


class SpecGenerator(BaseGenerator):
    """Generator for spec.md files."""
    
    def __init__(self, analyzer: 'ProjectAnalyzer', format_type: str = 'markdown'):
        """
        Initialize the spec generator.
        
        Args:
            analyzer: ProjectAnalyzer instance
            format_type: Output format ('markdown' or 'json')
        """
        super().__init__(analyzer)
        self.format_type = format_type
    
    def generate(self, description: str) -> str:
        """
        Generate specification document.
        
        Args:
            description: Project description for context
            
        Returns:
            Generated spec content
        """
        if self.format_type == 'json':
            return self._generate_json()
        else:
            return self._generate_markdown(description)
    
    def _generate_json(self) -> str:
        """Generate JSON format specification."""
        data = {
            "metadata": {
                "generated": self.date,
                "feature_branch": "main",
                "status": "Active Development"
            },
            "statistics": {
                "endpoints": self.analyzer.endpoint_count,
                "models": self.analyzer.model_count,
                "views": self.analyzer.view_count,
                "services": self.analyzer.service_count,
                "features": self.analyzer.feature_count
            },
            "endpoints": [
                {
                    "method": ep.method,
                    "path": ep.path,
                    "controller": ep.controller,
                    "authenticated": ep.authenticated
                }
                for ep in self.analyzer.endpoints
            ],
            "models": [
                {"name": m.name, "fields": m.fields}
                for m in self.analyzer.models
            ],
            "views": [
                {"name": v.name, "file": v.file_name}
                for v in self.analyzer.views
            ],
            "services": [s.name for s in self.analyzer.services]
        }
        return json.dumps(data, indent=2)
    
    def _generate_markdown(self, description: str) -> str:
        """Generate Markdown format specification."""
        project_info = self.analyzer.get_project_info()
        display_name = format_project_name(project_info["name"])
        
        # Extract intent context from description
        intent_context = extract_intent_context(description)
        
        output = [
            f"# Feature Specification: {display_name}",
            "",
            f"**Feature Branch**: `main`",
            f"**Created**: {self.date}",
            f"**Status**: Active Development",
            f"**Input**: Reverse-engineered from existing codebase",
            "",
            "## Project Overview",
            "",
            project_info["description"],
            "",
            "This specification was automatically generated by reverse-engineering the existing codebase.",
            "It documents the current implementation's capabilities, requirements, and architecture.",
            "",
            "**Note**: This is a living document generated from code analysis. User stories and requirements",
            "below represent the implemented functionality as detected from controllers, models, and services.",
            "",
            "## User Scenarios & Testing *(mandatory)*",
            "",
            f"**Application Purpose**: {description}",
            "",
        ]
        
        # Generate user stories
        story_num = 1
        controllers_seen = set()
        
        for endpoint in self.analyzer.endpoints[:6]:  # Limit to first 6 controllers
            if endpoint.controller in controllers_seen:
                continue
            controllers_seen.add(endpoint.controller)
            
            # Generate story for this controller
            actor, goal, benefit = self._infer_business_outcome(
                endpoint.controller, 
                intent_context
            )
            
            feature_name = endpoint.controller.replace('Controller', '').replace('Api', '')
            priority = "P1" if story_num <= 3 else "P2"
            
            output.extend([
                "",
                f"### User Story {story_num} - {feature_name} (Priority: {priority})",
                "",
                f"As a **{actor}**, I want to **{goal}**",
                f"so that **I can {benefit}**.",
                "",
                "**Why this priority**: Core business value - this capability directly supports the application's primary purpose.",
                "",
                f"**Independent Test**: Can be tested by exercising the available endpoints and verifying that users can achieve the stated goal.",
                "",
                "**Acceptance Scenarios**:",
                "",
                "1. **Given** I have valid data, **When** I make requests, **Then** I receive accurate results",
                "2. **Given** I provide invalid data, **When** I attempt operations, **Then** I receive clear error messages",
                "",
                "---",
            ])
            story_num += 1
        
        # Add UI story if views exist
        if self.analyzer.view_count > 0:
            output.extend([
                "",
                f"### User Story {story_num} - User Interface Interactions (Priority: P1)",
                "",
                "As a **system user**, I want to **interact with a web-based interface**",
                "so that **I can perform operations without needing to use API calls directly**.",
                "",
                f"**Why this priority**: The UI provides the primary user experience with {self.analyzer.view_count} views available.",
                "",
                "**Independent Test**: Can be fully tested by navigating through available views and verifying all interactive elements function correctly.",
                "",
                "**Acceptance Scenarios**:",
                "",
                "1. **Given** I access the application, **When** I navigate between views, **Then** the interface responds smoothly",
                "2. **Given** I interact with forms, **When** I submit data, **Then** it is processed correctly",
                "3. **Given** I view data displays, **When** information is loaded, **Then** it is presented clearly and accurately",
                "4. **Given** errors occur, **When** I receive feedback, **Then** messages are helpful and actionable",
                "",
                "---",
            ])
        
        # Add edge cases and requirements
        output.extend([
            "",
            "### Edge Cases",
            "",
            "- What happens when **invalid data is submitted** to API endpoints?",
            "- How does the system handle **concurrent modifications** to the same entity?",
            "- What occurs when **required authentication** is missing or expired?",
            "- How does the system respond to **malformed JSON** in requests?",
            "- What happens when **database connections fail** during operations?",
            "",
            "## Requirements *(mandatory)*",
            "",
            "### Functional Requirements",
            "",
        ])
        
        # Generate functional requirements
        req_counter = 1
        
        # Check for authentication
        if any(ep.authenticated for ep in self.analyzer.endpoints):
            output.append(f"- **FR-{req_counter:03d}**: System MUST provide authentication and authorization for protected endpoints")
            req_counter += 1
        
        # Check for HTTP methods
        methods = set(ep.method for ep in self.analyzer.endpoints)
        if "GET" in methods:
            output.append(f"- **FR-{req_counter:03d}**: System MUST support retrieval of data via GET endpoints")
            req_counter += 1
        if "POST" in methods:
            output.append(f"- **FR-{req_counter:03d}**: System MUST support creation of new entities via POST endpoints")
            req_counter += 1
        if "PUT" in methods or "PATCH" in methods:
            output.append(f"- **FR-{req_counter:03d}**: System MUST support updates to existing entities via PUT/PATCH endpoints")
            req_counter += 1
        if "DELETE" in methods:
            output.append(f"- **FR-{req_counter:03d}**: System MUST support deletion of entities via DELETE endpoints")
            req_counter += 1
        
        output.extend([
            f"- **FR-{req_counter:03d}**: System MUST validate all input data for correctness and completeness",
        ])
        req_counter += 1
        output.extend([
            f"- **FR-{req_counter:03d}**: System MUST return appropriate HTTP status codes for all operations",
        ])
        req_counter += 1
        output.extend([
            f"- **FR-{req_counter:03d}**: System MUST handle errors gracefully with meaningful error messages",
        ])
        req_counter += 1
        
        if self.analyzer.model_count > 0:
            output.append(f"- **FR-{req_counter:03d}**: System MUST persist data using {self.analyzer.model_count} defined data models")
        
        # Key entities
        output.extend([
            "",
            "### Key Entities",
            "",
            f"**Discovered Models** ({self.analyzer.model_count} total):",
            "",
        ])
        
        for model in self.analyzer.models:
            output.append(f"- **{model.name}**: {model.fields} fields")
        
        # Success criteria
        output.extend([
            "",
            "## Success Criteria *(mandatory)*",
            "",
            "### Measurable Outcomes",
            "",
            "- **SC-001**: API endpoints respond within acceptable time limits (< 2 seconds for 95% of requests)",
            "- **SC-002**: System successfully handles concurrent requests without data corruption",
            "- **SC-003**: All CRUD operations complete successfully with proper validation",
            "- **SC-004**: Error responses include meaningful messages and appropriate HTTP status codes",
            "- **SC-005**: Data persistence maintains integrity across all operations",
            "- **SC-006**: Authentication and authorization function correctly for protected resources",
            f"- **SC-007**: System scales to handle expected user load ({self.analyzer.endpoint_count} endpoints, {self.analyzer.model_count} models)",
            "- **SC-008**: All functional requirements are testable and verified",
            "",
            "## Technical Implementation Details",
            "",
            "### API Endpoints Discovered",
            "",
            f"Total endpoints: {self.analyzer.endpoint_count}",
            "",
        ])
        
        # Group endpoints by controller
        current_controller = ""
        for endpoint in self.analyzer.endpoints:
            if endpoint.controller != current_controller:
                if current_controller:
                    output.append("")
                output.append(f"**{endpoint.controller} Controller**:")
                output.append("")
                current_controller = endpoint.controller
            
            output.append(f"- `{endpoint.method} {endpoint.path}` {endpoint}")
        
        # UI Views
        output.extend([
            "",
            "### UI Views Discovered",
            "",
            f"Total views: {self.analyzer.view_count}",
            "",
        ])
        
        for view in self.analyzer.views:
            output.append(f"- **{view.name}**: `{view.file_name}`")
        
        # Backend services
        output.extend([
            "",
            "### Backend Services Discovered",
            "",
            f"Total services: {self.analyzer.service_count}",
            "",
        ])
        
        for service in self.analyzer.services:
            output.append(f"- {service.name}")
        
        # Technology stack
        output.extend([
            "",
            "### Technology Stack",
            "",
        ])
        
        if project_info["language"] != "NEEDS CLARIFICATION":
            output.append(f"- **Language/Runtime**: {project_info['language']}")
        
        if project_info["dependencies"] != "NEEDS CLARIFICATION":
            formatted_deps = project_info["dependencies"].replace(", ", " + ")
            output.append(f"- **Frameworks**: {formatted_deps}")
        
        if project_info["storage"] != "N/A":
            formatted_storage = project_info["storage"].replace(", ", " + ")
            output.append(f"- **Data Storage**: {formatted_storage}")
        
        if project_info["testing"] != "NEEDS CLARIFICATION":
            formatted_testing = project_info["testing"].replace(", ", " + ")
            output.append(f"- **Testing**: {formatted_testing}")
        
        # Check for build tools
        if list(self.analyzer.repo_root.rglob("pom.xml")):
            output.append("- **Build Tool**: Maven")
        elif list(self.analyzer.repo_root.rglob("build.gradle")):
            output.append("- **Build Tool**: Gradle")
        elif list(self.analyzer.repo_root.rglob("package.json")):
            output.append("- **Build Tool**: npm/yarn/pnpm")
        
        # Footer
        output.extend([
            "",
            "---",
            "",
            f"**Generated**: {self.date} by reverse-engineer",
            f"**Analysis**: {self.analyzer.endpoint_count} endpoints, {self.analyzer.model_count} models, {self.analyzer.view_count} views, {self.analyzer.service_count} services",
        ])
        
        return "\n".join(output)
    
    def _infer_business_outcome(self, controller: str, intent_context: dict) -> tuple:
        """Infer actor, goal, and benefit for a controller."""
        # Simple inference based on controller name
        controller_lower = controller.lower()
        
        # Infer actor
        if "auth" in controller_lower or "login" in controller_lower:
            actor = "system user"
        elif "admin" in controller_lower:
            actor = "administrator"
        else:
            actor = "user"
        
        # Infer goal and benefit
        entity = controller.replace("Controller", "").replace("Api", "")
        
        # Use intent verbs if available
        if intent_context.get("verbs"):
            verb = intent_context["verbs"][0]
            goal = f"{verb} {entity} data"
            benefit = f"support {verb} operations effectively"
        else:
            goal = f"manage {entity} data"
            benefit = f"maintain accurate {entity} information"
        
        return actor, goal, benefit


class PlanGenerator(BaseGenerator):
    """Generator for plan.md files."""
    
    def generate(self) -> str:
        """Generate implementation plan document."""
        project_info = self.analyzer.get_project_info()
        display_name = format_project_name(project_info["name"])
        project_type = project_info["type"]
        project_name = self.analyzer.repo_root.name
        
        output = [
            f"# Implementation Plan: {display_name}",
            "",
            f"**Branch**: `{project_name}` | **Date**: {self.date} | **Spec**: [spec.md](./spec.md)",
            "**Input**: Reverse-engineered specification from existing codebase",
            "",
            f"**Note**: This plan documents the current implementation state of the {display_name}",
            "application, generated through reverse-engineering analysis. Unlike typical plans that",
            "guide future development, this serves as architectural documentation of what exists.",
            "",
            "---",
            "",
            "## Summary",
            "",
            project_info["description"],
            "",
            "**Primary Capabilities**:",
            f"- RESTful API with {self.analyzer.endpoint_count} endpoints",
            f"- Data management with {self.analyzer.model_count} models",
        ]
        
        if self.analyzer.view_count > 0:
            output.append(f"- User interface with {self.analyzer.view_count} views")
        
        if self.analyzer.service_count > 0:
            output.append(f"- Business logic layer with {self.analyzer.service_count} services")
        
        output.extend([
            "",
            "**Technical Approach**:",
        ])
        
        if project_info["language"] != "NEEDS CLARIFICATION":
            output.append(f"- {project_info['language']} runtime")
        
        if project_info["dependencies"] != "NEEDS CLARIFICATION":
            for dep in project_info["dependencies"].split(", "):
                output.append(f"- {dep} framework")
        
        if project_info["storage"] != "N/A":
            output.append(f"- {project_info['storage']} for data persistence")
        
        # Add more sections
        output.extend([
            "",
            "---",
            "",
            "## Technical Context",
            "",
            f"**Language/Version**: {project_info['language']}",
            f"**Primary Dependencies**: {project_info['dependencies']}",
            f"**Storage**: {project_info['storage']}",
            f"**Testing**: {project_info['testing']}",
            "**Target Platform**: Docker containers (Linux), Web browsers (ES2015+)",
            f"**Project Type**: {project_type}",
            "**Performance Goals**: <500ms API response time, efficient data processing, optimal resource utilization",
            "**Constraints**: Scalable architecture, maintainable codebase, robust error handling",
            f"**Scale/Scope**: {self.analyzer.endpoint_count} API endpoints, {self.analyzer.model_count} data models, {self.analyzer.view_count} UI views",
            "",
            "---",
            "",
            "## Project Structure",
            "",
            "### Documentation (this feature)",
            "",
            "```",
            "specs/001-reverse/",
            "├── spec.md              # Reverse-engineered specification",
            "└── plan.md              # This file (implementation plan)",
            "```",
            "",
            "---",
            "",
            "## Phase 1: Design & Contracts",
            "",
            "**Status**: ✅ COMPLETE (Existing Implementation)",
            "",
            "The following design artifacts exist in the current codebase:",
            "",
            "### API Endpoints",
            "",
            f"**API Endpoints** ({self.analyzer.endpoint_count} endpoints):",
            "",
        ])
        
        # Group endpoints by controller
        current_controller = ""
        for endpoint in self.analyzer.endpoints:
            if endpoint.controller != current_controller:
                output.append("")
                output.append(f"**{endpoint.controller}Controller**:")
                current_controller = endpoint.controller
            output.append(f"- {endpoint}")
        
        output.extend([
            "",
            "### Data Models",
            "",
            f"**Entities** ({self.analyzer.model_count} models):",
            "",
        ])
        
        for model in self.analyzer.models:
            output.append(f"- **{model.name}** - {model.fields} fields")
        
        if self.analyzer.view_count > 0:
            output.extend([
                "",
                "### Views & Components",
                "",
                f"**UI Views** ({self.analyzer.view_count} views):",
                "",
            ])
            
            for view in self.analyzer.views:
                output.append(f"- **{view.name}** - `{view.file_name}`")
        
        output.extend([
            "",
            "---",
            "",
            "## Key Decisions & Rationale",
            "",
            "### Technology Choices",
            "",
        ])
        
        # Add technology rationale based on detected stack
        if "Spring Boot" in project_info["dependencies"]:
            output.extend([
                "**Backend: Spring Boot**",
                "- Rationale: Industry-standard framework with excellent security, testing, and documentation",
                "- Alternatives considered: Quarkus (less mature), Node.js (team expertise with Java)",
                "",
            ])
        
        if "Vue.js" in project_info["dependencies"]:
            output.extend([
                "**Frontend: Vue.js 3**",
                "- Rationale: Progressive framework with excellent developer experience and Composition API",
                "- Alternatives considered: React (more complex state management), Angular (heavier)",
                "",
            ])
        
        if "MongoDB" in project_info["storage"]:
            output.extend([
                "**Database: MongoDB**",
                "- Rationale: Flexible schema for evolving data requirements, excellent JSON integration",
                "- Alternatives considered: PostgreSQL (less flexible schema), MySQL (dated)",
                "",
            ])
        
        output.extend([
            "---",
            "",
            "## Next Steps",
            "",
            "Since this is a reverse-engineered plan, next steps depend on your goal:",
            "",
            "### For Documentation",
            "- ✅ spec.md and plan.md are now generated",
            "- Consider adding architecture diagrams",
            "- Document deployment procedures",
            "- Create API documentation (Swagger/OpenAPI)",
            "",
            "### For New Features",
            "1. Create new feature specification",
            "2. Generate implementation plan",
            "3. Break down into tasks",
            "4. Implement and test",
            "",
            "---",
            "",
            "## Maintenance Notes",
            "",
            f"**Last Analysis**: {self.datetime}",
            "**Script**: reverse-engineer",
            f"**Analysis Stats**: {self.analyzer.endpoint_count} endpoints, {self.analyzer.model_count} models, {self.analyzer.view_count} views, {self.analyzer.service_count} services",
            "",
            "To regenerate this plan:",
            "```bash",
            "reverse-engineer --plan",
            "```",
        ])
        
        return "\n".join(output)


class DataModelGenerator(BaseGenerator):
    """Generator for data-model.md files."""
    
    def generate(self) -> str:
        """Generate data model documentation."""
        project_info = self.analyzer.get_project_info()
        display_name = format_project_name(project_info["name"])
        
        output = [
            f"# Data Models: {display_name}",
            "",
            f"**Generated**: {self.date}",
            "**Source**: Reverse-engineered from project models",
            f"**Total Models**: {self.analyzer.model_count}",
            "",
            f"This document provides comprehensive documentation for all data models in the {display_name} application.",
            "",
            "---",
            "",
            "## Overview",
            "",
            f"The {display_name} uses {self.analyzer.model_count} data models to represent the domain:",
            "",
        ]
        
        for model in self.analyzer.models:
            output.append(f"- **{model.name}** - {model.fields} fields")
        
        output.extend([
            "",
            "---",
            "",
            "## Model Descriptions",
            "",
        ])
        
        # Generate detailed sections for each model
        for model in self.analyzer.models:
            output.extend([
                "",
                f"### {model.name}",
                "",
                f"**Location**: `{model.file_path.relative_to(self.analyzer.repo_root) if model.file_path else 'Unknown'}`",
                f"**Fields**: {model.fields}",
                "",
            ])
            
            if model.file_path and model.file_path.exists():
                try:
                    content = model.file_path.read_text()
                    
                    # Extract class-level JavaDoc
                    import re
                    javadoc_match = re.search(r'/\*\*(.*?)\*/', content, re.DOTALL)
                    if javadoc_match:
                        javadoc = javadoc_match.group(1)
                        # Clean up JavaDoc
                        javadoc_lines = [
                            line.strip().lstrip('*').strip()
                            for line in javadoc.split('\n')
                            if line.strip() and not line.strip().startswith('@')
                        ]
                        if javadoc_lines:
                            output.append("**Description**:")
                            output.extend(javadoc_lines[:5])  # Limit to 5 lines
                            output.append("")
                    
                    # Extract field information
                    output.append("**Fields**:")
                    output.append("")
                    
                    field_pattern = r'private\s+(\S+)\s+(\S+);'
                    for match in re.finditer(field_pattern, content):
                        field_type = match.group(1)
                        field_name = match.group(2)
                        output.append(f"- `{field_name}` (`{field_type}`)")
                    
                    output.append("")
                    
                    # Check for MongoDB document annotation
                    if '@Document' in content:
                        collection_match = re.search(r'collection\s*=\s*"([^"]*)"', content)
                        if collection_match:
                            output.append(f"**MongoDB Collection**: `{collection_match.group(1)}`")
                            output.append("")
                    
                    # Check for relationships
                    if '@DBRef' in content:
                        output.append("**Relationships**: Contains database references to other documents")
                        output.append("")
                
                except Exception:
                    output.append("*Model file not accessible for detailed analysis*")
                    output.append("")
            else:
                output.append("*Model file not found or not accessible for detailed analysis*")
                output.append("")
            
            output.append("---")
        
        output.extend([
            "",
            "## Model Relationships",
            "",
            "The model relationships are determined by examining `@DBRef`, `@OneToMany`, `@ManyToOne`,",
            "and other relationship annotations in the source code. Refer to the individual model",
            "documentation above for specific relationship details.",
            "",
            "## Usage Patterns",
            "",
            "The usage patterns for these models are determined by the service layer and controller",
            "implementations. Common patterns include:",
            "",
            "1. **CRUD Operations**: Create, Read, Update, Delete operations for entity management",
            "2. **Data Validation**: JSR-303 validation annotations ensure data integrity",
            "3. **Persistence**: JPA/MongoDB annotations handle database mapping",
            "4. **Business Logic**: Service classes orchestrate model interactions",
            "",
            "---",
            "",
            "**Note**: This documentation was auto-generated by analyzing the Java model files. For the most up-to-date field information, refer to the source code.",
        ])
        
        return "\n".join(output)


class ApiContractGenerator(BaseGenerator):
    """Generator for OpenAPI 3.0 specification (api-spec.json)."""
    
    def generate(self) -> str:
        """Generate OpenAPI specification."""
        project_info = self.analyzer.get_project_info()
        project_name = project_info["name"]
        display_name = format_project_name(project_name)
        
        api_title = f"{display_name} API"
        api_description = project_info["description"]
        api_version = "1.0.0"
        
        # Try to detect version from pom.xml
        for pom_file in self.analyzer.repo_root.rglob("pom.xml"):
            try:
                import re
                content = pom_file.read_text()
                version_match = re.search(r'<version>([^<]+)</version>', content)
                if version_match:
                    api_version = version_match.group(1)
                    break
            except Exception:
                pass
        
        # Build OpenAPI spec
        spec = {
            "openapi": "3.0.3",
            "info": {
                "title": api_title,
                "description": api_description,
                "version": api_version,
                "contact": {
                    "name": "API Support"
                },
                "license": {
                    "name": "MIT"
                }
            },
            "servers": [
                {
                    "url": "http://localhost:8080",
                    "description": "Development server"
                }
            ],
            "security": [
                {
                    "bearerAuth": []
                }
            ],
            "components": {
                "securitySchemes": {
                    "bearerAuth": {
                        "type": "http",
                        "scheme": "bearer",
                        "bearerFormat": "JWT",
                        "description": "JWT token obtained from authentication endpoint"
                    }
                },
                "schemas": self._generate_schemas()
            },
            "paths": self._generate_paths(),
            "tags": self._generate_tags()
        }
        
        return json.dumps(spec, indent=2)
    
    def _generate_schemas(self) -> dict:
        """Generate component schemas for models."""
        schemas = {}
        
        # Add model schemas
        for model in self.analyzer.models:
            schemas[model.name] = {
                "type": "object",
                "description": f"Data model for {model.name}",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Unique identifier"
                    }
                }
            }
            
            # Try to extract actual fields if file exists
            if model.file_path and model.file_path.exists():
                try:
                    import re
                    content = model.file_path.read_text()
                    field_pattern = r'private\s+(\S+)\s+(\S+);'
                    
                    properties = {}
                    for match in re.finditer(field_pattern, content):
                        field_type = match.group(1)
                        field_name = match.group(2)
                        
                        # Map Java types to OpenAPI types
                        openapi_type = self._map_type(field_type)
                        properties[field_name] = {"type": openapi_type}
                    
                    if properties:
                        schemas[model.name]["properties"] = properties
                
                except Exception:
                    pass
        
        # Add common schemas
        schemas["Error"] = {
            "type": "object",
            "properties": {
                "error": {
                    "type": "string",
                    "description": "Error message"
                },
                "status": {
                    "type": "integer",
                    "description": "HTTP status code"
                }
            }
        }
        
        schemas["AuthResponse"] = {
            "type": "object",
            "properties": {
                "token": {
                    "type": "string",
                    "description": "JWT authentication token"
                },
                "expiresIn": {
                    "type": "integer",
                    "description": "Token expiration time in seconds"
                }
            }
        }
        
        return schemas
    
    def _map_type(self, java_type: str) -> str:
        """Map Java type to OpenAPI type."""
        type_map = {
            "String": "string",
            "Integer": "integer",
            "int": "integer",
            "Long": "integer",
            "long": "integer",
            "Double": "number",
            "double": "number",
            "Float": "number",
            "float": "number",
            "Boolean": "boolean",
            "boolean": "boolean",
            "Date": "string",
            "LocalDate": "string",
            "LocalDateTime": "string",
            "Instant": "string",
        }
        
        if java_type.startswith("List") or java_type.startswith("ArrayList"):
            return "array"
        
        return type_map.get(java_type, "object")
    
    def _generate_paths(self) -> dict:
        """Generate API paths from endpoints."""
        paths = {}
        
        for endpoint in self.analyzer.endpoints:
            path = endpoint.path or "/"
            method = endpoint.method.lower()
            
            if path not in paths:
                paths[path] = {}
            
            operation_id = f"{endpoint.controller}{endpoint.method.capitalize()}"
            summary = f"{endpoint.method} {endpoint.controller}"
            
            operation = {
                "operationId": operation_id,
                "summary": summary,
                "description": f"Endpoint for {endpoint.controller}",
                "tags": [endpoint.controller]
            }
            
            if endpoint.authenticated:
                operation["security"] = [{"bearerAuth": []}]
            
            # Add responses
            operation["responses"] = self._generate_responses(endpoint.method)
            
            # Add request body for POST/PUT/PATCH
            if endpoint.method in ["POST", "PUT", "PATCH"]:
                operation["requestBody"] = {
                    "required": True,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/object"
                            }
                        }
                    }
                }
            
            paths[path][method] = operation
        
        return paths
    
    def _generate_responses(self, method: str) -> dict:
        """Generate response definitions based on HTTP method."""
        if method == "GET":
            return {
                "200": {
                    "description": "Successful response",
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object"
                            }
                        }
                    }
                },
                "404": {
                    "description": "Resource not found",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Error"
                            }
                        }
                    }
                }
            }
        elif method == "POST":
            return {
                "201": {
                    "description": "Resource created successfully",
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object"
                            }
                        }
                    }
                },
                "400": {
                    "description": "Invalid request data",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Error"
                            }
                        }
                    }
                }
            }
        elif method in ["PUT", "PATCH"]:
            return {
                "200": {
                    "description": "Resource updated successfully",
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object"
                            }
                        }
                    }
                },
                "404": {
                    "description": "Resource not found",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Error"
                            }
                        }
                    }
                }
            }
        elif method == "DELETE":
            return {
                "204": {
                    "description": "Resource deleted successfully"
                },
                "404": {
                    "description": "Resource not found",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Error"
                            }
                        }
                    }
                }
            }
        else:
            return {
                "200": {
                    "description": "Successful response"
                }
            }
    
    def _generate_tags(self) -> list:
        """Generate tags for controllers."""
        controllers = set(ep.controller for ep in self.analyzer.endpoints)
        
        return [
            {
                "name": controller,
                "description": f"Operations for {controller} management"
            }
            for controller in sorted(controllers)
        ]


class UseCaseMarkdownGenerator(BaseGenerator):
    """Generator for use-cases.md files."""
    
    def __init__(self, analyzer, framework_id: Optional[str] = None):
        """Initialize generator with optional framework ID."""
        super().__init__(analyzer)
        self.template_loader = TemplateLoader(framework_id)
    
    def _load_template(self, template_name: str) -> str:
        """Load a template file with framework-specific fallback."""
        return self.template_loader.load(template_name)
    
    def _build_actors_summary(self) -> str:
        """Build the actors summary section."""
        if not self.analyzer.actors:
            return "*No actors identified in the current analysis.*"
        
        lines = []
        for actor in self.analyzer.actors:
            lines.append(f"- **{actor.name}** ({actor.type}) - Access: {actor.access_level}")
        
        return "\n".join(lines)
    
    def _build_boundaries_summary(self) -> str:
        """Build the system boundaries summary section."""
        if not self.analyzer.system_boundaries:
            return "*No system boundaries identified in the current analysis.*"
        
        lines = []
        for boundary in self.analyzer.system_boundaries:
            lines.append(f"- **{boundary.name}** ({boundary.type}) - {len(boundary.components)} components")
        
        return "\n".join(lines)
    
    def _build_use_cases_summary(self) -> str:
        """Build the use cases summary section."""
        if not self.analyzer.use_cases:
            return "*No use cases identified in the current analysis.*"
        
        lines = []
        for use_case in self.analyzer.use_cases:
            lines.append(f"- {use_case.name}")
        
        return "\n".join(lines)
    
    def _build_business_context(self) -> str:
        """Build the business context table."""
        if not hasattr(self.analyzer, 'business_context'):
            return "*No business context information available.*"
        
        context = self.analyzer.business_context
        lines = []
        
        # Transaction boundaries
        if context.get('transactions'):
            readonly_count = sum(1 for t in context['transactions'] if t.get('readonly', False))
            write_count = len(context['transactions']) - readonly_count
            lines.append(f"| Transaction Boundaries | {len(context['transactions'])} total | Write: {write_count}, Read-Only: {readonly_count} |")
        
        # Validation rules
        if context.get('validations'):
            validation_types = {}
            for v in context['validations']:
                vtype = v.get('type', 'unknown')
                validation_types[vtype] = validation_types.get(vtype, 0) + 1
            
            types_summary = ", ".join([f"{vtype.replace('_', ' ').title()}: {count}" 
                                       for vtype, count in sorted(validation_types.items(), key=lambda x: x[1], reverse=True)])
            lines.append(f"| Validation Rules | {len(context['validations'])} constraints | {types_summary} |")
        
        # Business workflows
        if context.get('workflows'):
            workflow_types = {}
            for w in context['workflows']:
                wtype = w.get('type', 'unknown')
                workflow_types[wtype] = workflow_types.get(wtype, 0) + 1
            
            types_summary = ", ".join([f"{wtype.replace('_', ' ').title()}: {count}" 
                                       for wtype, count in sorted(workflow_types.items(), key=lambda x: x[1], reverse=True)])
            lines.append(f"| Business Workflows | {len(context['workflows'])} patterns | {types_summary} |")
        
        # Business rules
        if context.get('business_rules'):
            rule_types = {}
            for r in context['business_rules']:
                rtype = r.get('rule_type', 'unknown')
                rule_types[rtype] = rule_types.get(rtype, 0) + 1
            
            types_summary = ", ".join([f"{rtype.replace('_', ' ').title()}: {count}" 
                                       for rtype, count in sorted(rule_types.items(), key=lambda x: x[1], reverse=True)])
            lines.append(f"| Business Rules | {len(context['business_rules'])} derived | {types_summary} |")
        
        return "\n".join(lines) if lines else "*No business context information available.*"
    
    def _build_use_cases_detailed(self) -> str:
        """Build the detailed use cases section."""
        if not self.analyzer.use_cases:
            return "*No use cases identified in the current analysis.*"
        
        lines = []
        
        # Group use cases by actor
        use_cases_by_actor = {}
        for use_case in self.analyzer.use_cases:
            actor = use_case.primary_actor or "System"
            if actor not in use_cases_by_actor:
                use_cases_by_actor[actor] = []
            use_cases_by_actor[actor].append(use_case)
        
        for actor, use_cases in use_cases_by_actor.items():
            lines.append(f"### {actor} Use Cases")
            lines.append("")
            lines.append(f"Total: {len(use_cases)} use cases")
            lines.append("")
            
            # Show all use cases with full detail
            for i, use_case in enumerate(use_cases, 1):
                lines.append(f"#### UC{i:02d}: {use_case.name}")
                lines.append("")
                lines.append(f"**Primary Actor**: {use_case.primary_actor}")
                
                if use_case.secondary_actors:
                    lines.append(f"**Secondary Actors**: {', '.join(use_case.secondary_actors)}")
                
                if use_case.preconditions:
                    lines.append("")
                    lines.append("**Preconditions**:")
                    for precondition in use_case.preconditions:
                        lines.append(f"- {precondition}")
                
                if use_case.postconditions:
                    lines.append("")
                    lines.append("**Postconditions**:")
                    for postcondition in use_case.postconditions:
                        lines.append(f"- {postcondition}")
                
                if use_case.main_scenario:
                    lines.append("")
                    lines.append("**Main Scenario**:")
                    for j, step in enumerate(use_case.main_scenario, 1):
                        lines.append(f"{j}. {step}")
                
                if use_case.extensions:
                    lines.append("")
                    lines.append("**Extensions**:")
                    for extension in use_case.extensions:
                        lines.append(f"- {extension}")
                
                lines.append("")
                lines.append("---")
                lines.append("")
        
        return "\n".join(lines)
    
    def generate(self) -> str:
        """Generate use case documentation using template."""
        project_info = self.analyzer.get_project_info()
        display_name = format_project_name(project_info["name"])
        
        # Load template
        template = self._load_template("phase4-use-cases.md")
        
        # Build content sections
        business_context = self._build_business_context()
        use_cases_detailed = self._build_use_cases_detailed()
        use_cases_detailed = self._build_use_cases_detailed()
        
        # Additional sections - keeping placeholders for now
        use_case_relationships = "*Not yet implemented in current analysis.*"
        actor_boundary_matrix = "*Not yet implemented in current analysis.*"
        business_rules = "*Included in Business Context section above.*"
        workflows = "*Included in Business Context section above.*"
        extension_points = "*Not yet implemented in current analysis.*"
        validation_rules = "*Included in Business Context section above.*"
        transaction_boundaries = "*Included in Business Context section above.*"
        
        # Populate template variables
        output = template.replace("{{PROJECT_NAME}}", project_info["name"])
        output = output.replace("{{DATE}}", self.datetime)
        output = output.replace("{{PROJECT_NAME_DISPLAY}}", display_name)
        output = output.replace("{{ACTOR_COUNT}}", str(self.analyzer.actor_count))
        output = output.replace("{{USE_CASE_COUNT}}", str(self.analyzer.use_case_count))
        output = output.replace("{{BOUNDARY_COUNT}}", str(self.analyzer.system_boundary_count))
        output = output.replace("{{BUSINESS_CONTEXT}}", business_context)
        output = output.replace("{{USE_CASES_DETAILED}}", use_cases_detailed)
        output = output.replace("{{USE_CASE_RELATIONSHIPS}}", use_case_relationships)
        output = output.replace("{{ACTOR_BOUNDARY_MATRIX}}", actor_boundary_matrix)
        output = output.replace("{{BUSINESS_RULES}}", business_rules)
        output = output.replace("{{WORKFLOWS}}", workflows)
        output = output.replace("{{EXTENSION_POINTS}}", extension_points)
        output = output.replace("{{VALIDATION_RULES}}", validation_rules)
        output = output.replace("{{TRANSACTION_BOUNDARIES}}", transaction_boundaries)
        
        return output


class StructureDocGenerator(BaseGenerator):
    """Generator for Phase 1: Project Structure documentation."""
    
    def __init__(self, analyzer: 'ProjectAnalyzer', framework_id: Optional[str] = None):
        """Initialize generator with optional framework ID."""
        super().__init__(analyzer)
        self.template_loader = TemplateLoader(framework_id)
    
    def _load_template(self, template_name: str) -> str:
        """Load a template file with framework-specific fallback."""
        return self.template_loader.load(template_name)
    
    def _build_endpoints_table(self) -> str:
        """Build the API endpoints table."""
        if not self.analyzer.endpoints:
            return "*No endpoints discovered*"
        
        lines = []
        for endpoint in self.analyzer.endpoints:
            auth = "🔒" if endpoint.authenticated else ""
            lines.append(f"| {endpoint.method} | {endpoint.path} | {endpoint.controller} {auth} |")
        
        return "\n".join(lines)
    
    def _build_models_table(self) -> str:
        """Build the data models table."""
        if not self.analyzer.models:
            return "*No models discovered*"
        
        lines = []
        for model in self.analyzer.models:
            location = str(model.file_path.relative_to(self.analyzer.repo_root)) if model.file_path else "N/A"
            lines.append(f"| {model.name} | {model.fields} | `{location}` |")
        
        return "\n".join(lines)
    
    def _build_views_table(self) -> str:
        """Build the UI views table."""
        if not self.analyzer.views:
            return "*No views discovered*"
        
        lines = []
        for view in self.analyzer.views:
            lines.append(f"| {view.name} | `{view.file_name}` |")
        
        return "\n".join(lines)
    
    def _build_services_list(self) -> str:
        """Build the backend services list."""
        if not self.analyzer.services:
            return "*No services discovered*"
        
        lines = []
        for service in self.analyzer.services:
            lines.append(f"- `{service.name}`")
        
        return "\n".join(lines)
    
    def _build_features_table(self) -> str:
        """Build the features table."""
        if not self.analyzer.features:
            return "*No features were identified during analysis. Features may be documented in README files or project documentation.*"
        
        lines = []
        current_category = "General"
        
        for i, feature in enumerate(self.analyzer.features, 1):
            # Split feature at first colon to separate name from description
            if ': ' in feature:
                name, description = feature.split(': ', 1)
                current_category = name  # Update category for subsequent items
                lines.append(f"| {i} | {name} | {description} |")
            else:
                # No colon found - use as description with current category
                lines.append(f"| {i} | {current_category} | {feature} |")
        
        return "\n".join(lines)
    
    def generate(self) -> str:
        """Generate Phase 1 structure documentation using template."""
        project_name = format_project_name(self.analyzer.repo_root.name)
        
        # Load template
        template = self._load_template("phase1-structure.md")
        
        # Build content sections
        endpoints_table = self._build_endpoints_table()
        models_table = self._build_models_table()
        views_table = self._build_views_table()
        services_list = self._build_services_list()
        features_table = self._build_features_table()
        
        # Populate template variables
        output = template.replace("{{PROJECT_NAME}}", self.analyzer.repo_root.name)
        output = output.replace("{{DATE}}", self.datetime)
        output = output.replace("{{ENDPOINT_COUNT}}", str(self.analyzer.endpoint_count))
        output = output.replace("{{MODEL_COUNT}}", str(self.analyzer.model_count))
        output = output.replace("{{VIEW_COUNT}}", str(self.analyzer.view_count))
        output = output.replace("{{SERVICE_COUNT}}", str(self.analyzer.service_count))
        output = output.replace("{{FEATURE_COUNT}}", str(self.analyzer.feature_count))
        output = output.replace("{{PROJECT_PATH}}", str(self.analyzer.repo_root))
        
        # Replace table placeholders with actual content
        # For endpoints table, replace the template row with actual rows
        template_row = "| {{HTTP_METHOD}} | {{HTTP_ENDPOINT}} | {{API_CONTROLLER}} |"
        output = output.replace(template_row, endpoints_table)
        
        # For models table
        template_row = "| {{MODEL}} | {{FIELDS}} | {{DATA_MODEL_LOCATION}} |"
        output = output.replace(template_row, models_table)
        
        # For views table
        template_row = "| {{UI_VIEW_NAME}} | {{UI_COMPONENT_FILE}} |"
        output = output.replace(template_row, views_table)
        
        # For services list
        output = output.replace("{{SERVICES_LIST}}", services_list)
        
        # For features table - handle both cases (with/without table header)
        if self.analyzer.features:
            # Features exist, just replace the table content
            output = output.replace("{{FEATURES_TABLE}}", features_table)
        else:
            # No features, replace table section with message
            features_section = """| # | Name | Description |
|---|------|-------------|
{{FEATURES_TABLE}}"""
            output = output.replace(features_section, features_table)
        
        return output


class ActorDocGenerator(BaseGenerator):
    """Generator for Phase 2: Actor Discovery documentation."""
    
    def __init__(self, analyzer: 'ProjectAnalyzer', framework_id: Optional[str] = None):
        """Initialize generator with optional framework ID."""
        super().__init__(analyzer)
        self.template_loader = TemplateLoader(framework_id)
    
    def _load_template(self, template_name: str) -> str:
        """Load a template file with framework-specific fallback."""
        return self.template_loader.load(template_name)
    
    def _build_actors_table(self) -> str:
        """Build the actors table."""
        if not self.analyzer.actors:
            return "*No actors discovered*"
        
        lines = []
        for actor in self.analyzer.actors:
            actor_type = actor.type.replace('_', ' ').title()
            evidence = ", ".join(actor.identified_from) if actor.identified_from else "N/A"
            lines.append(f"| {actor.name} | {actor_type} | {actor.access_level} | {evidence} |")
        
        return "\n".join(lines)
    
    def _count_actor_types(self) -> tuple:
        """Count actors by type."""
        internal_users = sum(1 for a in self.analyzer.actors if a.type in ['user', 'admin', 'role'])
        end_users = sum(1 for a in self.analyzer.actors if a.type == 'end_user')
        external_systems = sum(1 for a in self.analyzer.actors if a.type == 'external_system')
        return internal_users, end_users, external_systems
    
    def _build_access_levels_summary(self) -> str:
        """Build access levels summary."""
        if not self.analyzer.actors:
            return "*No access levels defined*"
        
        access_levels = {}
        for actor in self.analyzer.actors:
            level = actor.access_level
            access_levels[level] = access_levels.get(level, 0) + 1
        
        lines = []
        for level, count in sorted(access_levels.items(), key=lambda x: x[1], reverse=True):
            lines.append(f"- **{level}**: {count} actor(s)")
        
        return "\n".join(lines)
    
    def generate(self) -> str:
        """Generate Phase 2 actor documentation using template."""
        project_name = format_project_name(self.analyzer.repo_root.name)
        
        # Load template
        template = self._load_template("phase2-actors.md")
        
        # Build content sections
        actors_table = self._build_actors_table()
        internal_users, end_users, external_systems = self._count_actor_types()
        access_levels_summary = self._build_access_levels_summary()
        
        # Populate template variables
        output = template.replace("{{PROJECT_NAME}}", self.analyzer.repo_root.name)
        output = output.replace("{{DATE}}", self.datetime)
        output = output.replace("{{ACTOR_COUNT}}", str(self.analyzer.actor_count))
        output = output.replace("{{INTERNAL_USER_COUNT}}", str(internal_users))
        output = output.replace("{{END_USER_COUNT}}", str(end_users))
        output = output.replace("{{EXTERNAL_SYSTEM_COUNT}}", str(external_systems))
        output = output.replace("{{PROJECT_PATH}}", str(self.analyzer.repo_root))
        output = output.replace("{{ACCESS_LEVELS_SUMMARY}}", access_levels_summary)
        
        # Replace table template row with actual data
        template_row = "| {{ACTOR}} | {{ACTOR_TYPE}} | {{ACTOR_ACCESS_LEVEL}} | {{ACTOR_EVIDENCE}} |"
        output = output.replace(template_row, actors_table)
        
        # Placeholders for future features
        output = output.replace("{{SECURITY_ANNOTATIONS_SUMMARY}}", "*Not yet implemented*")
        output = output.replace("{{ACTOR_RELATIONSHIPS}}", "*Not yet implemented*")
        
        return output


class BoundaryDocGenerator(BaseGenerator):
    """Generator for Phase 3: System Boundary documentation."""
    
    def __init__(self, analyzer: 'ProjectAnalyzer', framework_id: Optional[str] = None):
        """Initialize generator with optional framework ID."""
        super().__init__(analyzer)
        self.template_loader = TemplateLoader(framework_id)
    
    def _load_template(self, template_name: str) -> str:
        """Load a template file with framework-specific fallback."""
        return self.template_loader.load(template_name)
    
    def _build_boundaries_table(self) -> str:
        """Build the system boundaries table."""
        if not self.analyzer.system_boundaries:
            return "*No system boundaries discovered*"
        
        lines = []
        for boundary in self.analyzer.system_boundaries:
            boundary_type = boundary.type.replace('_', ' ').title()
            component_count = len(boundary.components)
            key_components = ", ".join(boundary.components) if boundary.components else "N/A"
            lines.append(f"| {boundary.name} | {boundary_type} | {component_count} | {key_components} |")
        
        return "\n".join(lines)
    
    def _count_boundary_metrics(self) -> tuple:
        """Count boundary-related metrics."""
        total_boundaries = self.analyzer.system_boundary_count
        subsystems = sum(1 for b in self.analyzer.system_boundaries if b.type in ['subsystem', 'module'])
        layers = sum(1 for b in self.analyzer.system_boundaries if b.type in ['layer', 'tier'])
        total_components = sum(len(b.components) for b in self.analyzer.system_boundaries)
        return total_boundaries, subsystems, layers, total_components
    
    def _build_subsystem_architecture(self) -> str:
        """Build subsystem architecture table."""
        subsystems = [b for b in self.analyzer.system_boundaries if b.type in ['subsystem', 'module']]
        if not subsystems:
            return "*No subsystems identified*"
        
        lines = []
        for subsystem in subsystems:
            component_count = len(subsystem.components)
            components_list = ", ".join(subsystem.components) if subsystem.components else "N/A"
            interface_count = len(subsystem.interfaces) if subsystem.interfaces else 0
            lines.append(f"| {subsystem.name} | {component_count} | {interface_count} | {components_list} |")
        
        return "\n".join(lines)
    
    def _build_layer_organization(self) -> str:
        """Build layer organization summary."""
        layers = [b for b in self.analyzer.system_boundaries if b.type in ['layer', 'tier']]
        if not layers:
            return "*No layers identified*"
        
        lines = []
        for layer in layers:
            lines.append(f"- **{layer.name}**: {len(layer.components)} component(s)")
        
        return "\n".join(lines)
    
    def generate(self) -> str:
        """Generate Phase 3 boundary documentation using template."""
        project_name = format_project_name(self.analyzer.repo_root.name)
        
        # Load template
        template = self._load_template("phase3-boundaries.md")
        
        # Build content sections
        boundaries_table = self._build_boundaries_table()
        boundary_count, subsystem_count, layer_count, component_count = self._count_boundary_metrics()
        subsystem_architecture = self._build_subsystem_architecture()
        layer_organization = self._build_layer_organization()
        
        # Populate template variables
        output = template.replace("{{PROJECT_NAME}}", self.analyzer.repo_root.name)
        output = output.replace("{{DATE}}", self.datetime)
        output = output.replace("{{BOUNDARY_COUNT}}", str(boundary_count))
        output = output.replace("{{SUBSYSTEM_COUNT}}", str(subsystem_count))
        output = output.replace("{{LAYER_COUNT}}", str(layer_count))
        output = output.replace("{{COMPONENT_COUNT}}", str(component_count))
        output = output.replace("{{PROJECT_PATH}}", str(self.analyzer.repo_root))
        output = output.replace("{{SUBSYSTEM_ARCHITECTURE}}", subsystem_architecture)
        output = output.replace("{{LAYER_ORGANIZATION}}", layer_organization)
        output = output.replace("{{BOUNDARIES_TABLE}}", boundaries_table)
        
        # Placeholders for future features
        output = output.replace("{{COMPONENT_MAPPING}}", "*Not yet implemented*")
        output = output.replace("{{BOUNDARY_INTERACTIONS}}", "*Not yet implemented*")
        output = output.replace("{{TECH_STACK_BY_BOUNDARY}}", "*Not yet implemented*")
        
        return output


class FourPlusOneDocGenerator(BaseGenerator):
    """Generator for 4+1 Architecture View document.
    
    Combines data from all four phases to create a comprehensive
    4+1 architectural view model document.
    """
    
    def __init__(self, analyzer: 'ProjectAnalyzer', framework_id: Optional[str] = None):
        """Initialize generator with optional framework ID."""
        super().__init__(analyzer)
        self.template_loader = TemplateLoader(framework_id)
    
    def _load_template(self, template_name: str) -> str:
        """Load a template file with framework-specific fallback."""
        return self.template_loader.load(template_name)
    
    def generate(self) -> str:
        """Generate 4+1 architecture documentation using template."""
        project_name = format_project_name(self.analyzer.repo_root.name)
        
        # Load template
        template = self._load_template("4+1-architecture-template.md")
        
        # Prepare variables for template
        variables = {
            'PROJECT_NAME': self.analyzer.repo_root.name,
            'GENERATION_DATE': self.date,
            'VERSION_NUMBER': '1.0.0',
            'AUTHOR_NAMES': 'RE-cue Analysis Tool',
            
            # Overview metrics
            'DOMAIN_MODEL_DESCRIPTION': f"The system contains {len(self.analyzer.models)} core domain models organized by functional areas.",
            
            # Logical View - Domain Models
            'CATEGORY_1': 'Core Business',
            'CATEGORY_2': 'Supporting',
            
            # Subsystem Architecture
            'SUBSYSTEM_DESCRIPTION': f"The application is organized into {len(self.analyzer.system_boundaries)} major subsystems.",
            'SUBSYSTEM_NAME': 'Primary Subsystem',
            'SUBSYSTEM_PURPOSE': 'Core business logic',
            'COMPONENT_COUNT': str(len(self.analyzer.services)),
            'KEY_COMPONENTS': ', '.join([s.name for s in self.analyzer.services[:3]]) if self.analyzer.services else 'N/A',
            
            # Service Layer
            'SERVICE_COUNT': str(len(self.analyzer.services)),
            'ADDITIONAL_COMPONENT_CATEGORY': 'Utilities and Helpers',
            'SPECIALIZED_COMPONENTS_DESCRIPTION': 'Supporting components for cross-cutting concerns.',
            
            # Component Relationships
            'TOP_LAYER': 'Presentation Layer',
            'LAYER_DESCRIPTION': 'UI Views and Components',
            'COMMUNICATION_PROTOCOL': 'HTTP/REST',
            'MIDDLE_LAYER': 'Application Layer',
            'COMPONENT': 'Service',
            'COMPONENT_GROUP': 'Business Logic',
            'DATA_LAYER': 'Data Access Layer',
            'LAYER_DETAILS': 'Repositories and Models',
            
            # Process View
            'PROCESS_NAME_1': 'Request Processing',
            'PROCESS_NAME_2': 'Data Persistence',
            'PROCESS_NAME_3': 'Authentication Flow',
            'BACKGROUND_PROCESS': 'Background Jobs',
            'PROCESS_DESCRIPTION': 'Standard workflow',
            'STEP_1': 'Initialize request',
            'STEP_2': 'Validate input',
            'STEP_3': 'Process business logic',
            'STEP_4': 'Update state',
            'STEP_5': 'Return response',
            'SUBSTEP': 'Sub-operation',
            'DETAIL_1': 'Operation detail',
            'DETAIL_2': 'Operation detail',
            'DETAIL_3': 'Operation detail',
            
            # Concurrency
            'TRANSACTION_COUNT': str(len([e for e in self.analyzer.endpoints if e.method in ['POST', 'PUT', 'DELETE']])),
            'WRITE_OPERATION_COUNT': str(len([e for e in self.analyzer.endpoints if e.method in ['POST', 'PUT', 'DELETE']])),
            'READ_OPERATION_COUNT': str(len([e for e in self.analyzer.endpoints if e.method == 'GET'])),
            'WORKFLOW_PATTERN_COUNT': '2',
            'PATTERN_TYPE': 'Standard',
            'PATTERN_COUNT': '1',
            
            # Synchronization
            'SYNCHRONIZATION_TYPE_1': 'Database Transactions',
            'SYNCHRONIZATION_TYPE_2': 'Session Management',
            'SYNCHRONIZATION_TYPE_3': 'Resource Locking',
            'SYNC_DESCRIPTION': 'Managed by framework',
            
            # Development View
            'PROJECT_ROOT': self.analyzer.repo_root.name,
            'MODULE_1': 'backend',
            'MODULE_2': 'frontend',
            'MODULE_3': 'shared',
            'MODULE_DESCRIPTION': 'Application module',
            'LANGUAGE': 'java' if any('java' in str(f) for f in self.analyzer.repo_root.rglob('*.java')) else 'python',
            'PACKAGE': 'com.example.app',
            'FOLDER': 'components',
            'FOLDER_DESCRIPTION': 'Component files',
            'TEST_DESCRIPTION': 'Unit and integration tests',
            'BUILD_FILE': 'pom.xml',
            'FILE_DESCRIPTION': 'Build configuration',
            'MAIN_FILE': 'main.py',
            'CONFIG_FILE': 'config.json',
            'SUBFOLDER': 'utils',
            
            # Package Organization
            'PACKAGE_ROOT': 'src.main',
            'SUBPACKAGE': 'controllers',
            'PACKAGE_DESCRIPTION': 'REST controllers',
            'ITEM_COUNT': str(len(self.analyzer.endpoints)),
            'ITEM_1': 'Controller1',
            'ITEM_2': 'Controller2',
            'ITEM_3': 'Controller3',
            'ITEM_TYPE': 'Controllers',
            'SUBITEM': 'Helper',
            
            # Technology Stack
            'LAYER_1': 'Backend',
            'LAYER_2': 'Frontend',
            'TECHNOLOGY_1': 'Framework',
            'TECHNOLOGY_2': 'Library',
            'TECHNOLOGY_3': 'Tool',
            'TECHNOLOGY_4': 'Database',
            'TECHNOLOGY_5': 'Cache',
            'INFRASTRUCTURE': 'Infrastructure',
            
            # Build & Deployment
            'COMPONENT_1': 'Backend',
            'COMPONENT_2': 'Frontend',
            'COMPONENT_3': 'Database',
            'BUILD_PROCESS_DESCRIPTION': 'Standard build process',
            'DEPLOYMENT_DESCRIPTION': 'Container-based deployment',
            'ORCHESTRATION': 'docker-compose.yml',
            'ORCHESTRATION_TOOL': 'Docker Compose',
            
            # Physical View
            'CLIENT_USER_LAYER': 'Client/User Layer',
            'CLIENT_APPLICATION': 'Web Application',
            'FEATURE_1': 'User Interface',
            'FEATURE_2': 'Data Visualization',
            'FEATURE_3': 'Reporting',
            'PROTOCOL_PORT': 'HTTPS/443',
            'SECURITY': 'TLS 1.3',
            'APPLICATION_SERVER_LAYER': 'Application Server Layer',
            'APPLICATION_SERVER': 'Application Server',
            'PORT_NUMBER': '8080',
            'PROTOCOL': 'HTTP',
            'CONNECTION_DETAILS': 'Connection pool',
            'DATABASE': 'Database Server',
            'DATABASE_DETAILS': 'Configuration',
            'ITEM_1': 'Connection pool: 20',
            'ITEM_2': 'Timeout: 30s',
            'ITEM_3': 'Max connections: 100',
            
            # Network Communication
            'LAYER_1': 'Client',
            'LAYER_2': 'Application',
            'LAYER_3': 'Database',
            'AUTH_METHOD': 'JWT',
            'DATA_FORMAT': 'JSON',
            'ADDITIONAL_DETAIL': 'Compression',
            'DETAIL_VALUE': 'gzip',
            'CONNECTION_TYPE': 'Persistent',
            
            # Container Deployment
            'CONTAINER_TECHNOLOGY': 'Docker',
            'DEPLOYMENT_FILE': 'docker-compose.yml',
            'SERVICE_1': 'web',
            'SERVICE_2': 'api',
            'SERVICE_3': 'db',
            'SERVICE_DESCRIPTION': 'Service container',
            'VOLUME_DETAILS': './data:/data',
            'DEPENDENCIES': 'db',
            'CONFIG_DETAILS': 'Environment variables',
            'ADDITIONAL_PROPERTY': 'Networks',
            'PROPERTY_DETAILS': 'internal',
            
            # Security Layers
            'SECURITY_LAYER_1': 'Authentication',
            'SECURITY_LAYER_2': 'Authorization',
            'SECURITY_LAYER_3': 'Data Protection',
            'FEATURE_4': 'Audit Logging',
            
            # Scalability
            'CONSIDERATION_1': 'Horizontal Scaling',
            'CONSIDERATION_2': 'Load Balancing',
            'CONSIDERATION_3': 'Caching Strategy',
            'CONSIDERATION_4': 'Database Optimization',
            'CONSIDERATION_DESCRIPTION': 'Planned for future implementation',
            
            # Use Case View
            'ACTOR_COUNT': str(len(self.analyzer.actors)),
            'ACTOR_1': self.analyzer.actors[0].name if self.analyzer.actors else 'User',
            'ACTOR_2': self.analyzer.actors[1].name if len(self.analyzer.actors) > 1 else 'Administrator',
            'ACTOR_3': self.analyzer.actors[2].name if len(self.analyzer.actors) > 2 else 'System',
            'ACTOR_TYPE': 'Internal User',
            'ACCESS_LEVEL': 'Standard',
            'ACTOR_DESCRIPTION': 'Primary system user',
            
            # Use Cases
            'USE_CASE_NAME': 'Primary Use Case',
            'ACTORS': 'User',
            'STEP_6': 'Additional step',
            'STEP_7': 'Additional step',
            'STEP_8': 'Additional step',
            'STEP_9': 'Additional step',
            'STEP_10': 'Additional step',
            'STEP_11': 'Additional step',
            'METHOD_ACTION': 'processRequest',
            'ACTION': 'action',
            'RESULT': 'success',
            'STEP_5_DESCRIPTION': 'Complex step with details',
            'STEP_6_DESCRIPTION': 'Another complex step',
            'DETAIL_A': 'Detail A',
            'DETAIL_B': 'Detail B',
            'DETAIL_C': 'Detail C',
            'DETAIL_D': 'Detail D',
            'DETAIL_E': 'Detail E',
            'DETAIL_F': 'Detail F',
            'DETAIL_G': 'Detail G',
            'DETAIL_H': 'Detail H',
            'STEP_3_DESCRIPTION': 'Step with details',
            'STEP_2_DESCRIPTION': 'Step with details',
            'SUBCOMPONENT': 'SubComponent',
            
            # Statistics
            'TOTAL_USE_CASES': str(len(self.analyzer.use_cases)),
            'CATEGORY': 'Primary',
            'CATEGORY_COUNT': str(len(self.analyzer.use_cases)),
            'OPERATION_TYPE': 'CRUD',
            'OPERATION_COUNT': str(len(self.analyzer.endpoints)),
            'DETAIL_LABEL': 'Metric',
            'DETAIL_COUNT': '0',
            
            # Scenarios
            'SCENARIO_1': 'User Registration',
            'SCENARIO_2': 'Data Processing',
            'SCENARIO_3': 'Report Generation',
            'SCENARIO_4': 'User Management',
            'SCENARIO_5': 'System Configuration',
            'SCENARIO_6': 'Data Export',
            'ACTORS': 'User, Admin',
            'SYSTEMS': 'Web, API, Database',
            'COMPLEXITY': 'Medium',
            
            # Architecture Principles
            'PRINCIPLE_1': 'Separation of Concerns',
            'PRINCIPLE_2': 'DRY (Don\'t Repeat Yourself)',
            'PRINCIPLE_3': 'SOLID Principles',
            'PRINCIPLE_4': 'Dependency Injection',
            'PRINCIPLE_5': 'RESTful API Design',
            'PRINCIPLE_6': 'Security by Design',
            'PRINCIPLE_7': 'Testability',
            'PRINCIPLE_8': 'Maintainability',
            'PRINCIPLE_DESCRIPTION': 'Core architectural principle',
            
            # Patterns
            'PATTERN_1': 'MVC (Model-View-Controller)',
            'PATTERN_2': 'Repository Pattern',
            'PATTERN_3': 'Service Layer',
            'PATTERN_4': 'Dependency Injection',
            'PATTERN_5': 'Factory Pattern',
            'PATTERN_6': 'Observer Pattern',
            'PATTERN_7': 'Strategy Pattern',
            'PATTERN_DESCRIPTION': 'Design pattern implementation',
            
            # Quality Attributes
            'IMPLEMENTATION_DETAILS': 'Implementation details',
            'STATUS': 'In Progress',
            
            # Technology Decisions
            'LAYER_COMPONENT': 'Application Layer',
            'DECISION_1': 'Framework Choice',
            'DECISION_2': 'Database Selection',
            'DECISION_3': 'API Design',
            'DECISION_4': 'Authentication',
            'DECISION_5': 'Deployment',
            'DECISION_6': 'Monitoring',
            'DECISION_7': 'Testing',
            'TECHNOLOGY': 'Technology',
            'RATIONALE': 'Rationale for choice',
            
            # Constraints
            'CONSTRAINT_1': 'Performance Requirements',
            'CONSTRAINT_2': 'Security Requirements',
            'CONSTRAINT_3': 'Scalability Requirements',
            'CONSTRAINT_4': 'Budget Constraints',
            'CONSTRAINT_5': 'Timeline Constraints',
            'CONSTRAINT_6': 'Technology Stack',
            'CONSTRAINT_DESCRIPTION': 'Constraint description',
            
            # Future Considerations
            'ENHANCEMENT_1': 'Performance Optimization',
            'ENHANCEMENT_2': 'Additional Features',
            'ENHANCEMENT_3': 'Integration Points',
            'ENHANCEMENT_4': 'Mobile Support',
            'ENHANCEMENT_5': 'Analytics',
            'ENHANCEMENT_DESCRIPTION': 'Future enhancement',
            'EXTENSION_1': 'Feature Extension',
            'EXTENSION_2': 'API Extension',
            'EXTENSION_3': 'Integration Extension',
            'EXTENSION_4': 'Platform Extension',
            'EXTENSION_5': 'Data Extension',
            'EXTENSION_6': 'UI Extension',
            'EXTENSION_DESCRIPTION': 'Extension description',
            
            # Conclusion
            'ARCHITECTURE_SUMMARY': 'This document provides a comprehensive overview of the system architecture using the 4+1 view model.',
            'ARCHITECTURAL_QUALITIES': 'modularity, scalability, and maintainability',
            'TECHNOLOGIES_AND_PRACTICES': 'modern frameworks and best practices',
            'LOGICAL_VIEW_SUMMARY': f'{len(self.analyzer.models)} models, {len(self.analyzer.services)} services',
            'PROCESS_VIEW_SUMMARY': f'{len(self.analyzer.endpoints)} endpoints with standard workflows',
            'DEVELOPMENT_VIEW_SUMMARY': f'Organized module structure with {len(self.analyzer.system_boundaries)} boundaries',
            'PHYSICAL_VIEW_SUMMARY': 'Container-based deployment with standard infrastructure',
            'USE_CASE_VIEW_SUMMARY': f'{len(self.analyzer.use_cases)} use cases across {len(self.analyzer.actors)} actors',
            'MISSION_STATEMENT': 'delivering robust and scalable solutions',
            'KEY_QUALITIES': 'security, performance, and reliability',
            
            # Metadata
            'DOCUMENT_METADATA': 'Generated by RE-cue',
            'LAST_UPDATED_DATE': self.date,
        }
        
        # Use Jinja2 template rendering
        output = self.template_loader.apply_variables(template, **variables)
        
        return output


class VisualizationGenerator(BaseGenerator):
    """Generator for visualization diagrams."""
    
    def __init__(self, analyzer: 'ProjectAnalyzer', config: Optional[DiagramConfig] = None):
        """
        Initialize the visualization generator.
        
        Args:
            analyzer: ProjectAnalyzer instance
            config: Optional diagram configuration
        """
        super().__init__(analyzer)
        self.config = config or DiagramConfig()
        self.diagram_gen = MermaidDiagramGenerator(analyzer, self.config)
    
    def generate(self, diagram_type: Optional[str] = None) -> str:
        """
        Generate visualization diagrams.
        
        Args:
            diagram_type: Optional specific diagram type to generate.
                         If None, generates all diagrams.
                         Options: 'flowchart', 'sequence', 'component', 'er', 'architecture', 'all'
        
        Returns:
            Generated diagrams document
        """
        if diagram_type and diagram_type != 'all':
            # Generate specific diagram type
            return self._generate_with_header(diagram_type)
        else:
            # Generate all diagrams
            return self.diagram_gen.generate_all_diagrams()
    
    def _generate_with_header(self, diagram_type: str) -> str:
        """Generate a specific diagram with header."""
        diagram_content = self.diagram_gen.generate_specific_diagram(diagram_type)
        
        header = f"# {diagram_type.capitalize()} Diagrams\n\n"
        header += f"**Generated**: {self.datetime}\n\n"
        header += "---\n\n"
        
        footer = "\n\n---\n\n*Generated by RE-cue - Business Process Visualization*\n"
        
        return header + diagram_content + footer


