"""Frontend authentication generator for Prism.

This generator creates React authentication components including:
- AuthContext with useAuth() hook
- Login and Signup forms
- Protected route wrapper
- Login and Signup pages
- Token management and API integration
"""

from __future__ import annotations

from pathlib import Path

from prism.generators.base import GeneratedFile, GeneratorBase
from prism.spec.stack import FileStrategy
from prism.utils.template_engine import TemplateRenderer


class FrontendAuthGenerator(GeneratorBase):
    """Generates React authentication components for frontend."""

    REQUIRED_TEMPLATES = [
        "frontend/auth/AuthContext.tsx.jinja2",
        "frontend/auth/LoginForm.tsx.jinja2",
        "frontend/auth/SignupForm.tsx.jinja2",
        "frontend/auth/ProtectedRoute.tsx.jinja2",
        "frontend/auth/Login.tsx.jinja2",
        "frontend/auth/Signup.tsx.jinja2",
        "frontend/auth/index.ts.jinja2",
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Skip generation if auth is not enabled
        if not self.spec.auth.enabled:
            self.skip_generation = True
            return

        # Initialize template renderer
        self.renderer = TemplateRenderer()
        self.renderer.validate_templates_exist(self.REQUIRED_TEMPLATES)

        # Setup paths for generated auth files
        frontend_base = Path(self.spec.generator.frontend_output)
        self.contexts_path = frontend_base / "contexts"
        self.components_path = frontend_base / "components" / "auth"
        self.pages_path = frontend_base / "pages"

    def generate_files(self) -> list[GeneratedFile]:
        """Generate all frontend authentication files.

        Returns:
            List of generated files with content and strategies
        """
        if getattr(self, "skip_generation", False):
            return []

        files = []

        # Auth context and hook
        files.append(self._generate_auth_context())

        # Auth components
        files.append(self._generate_login_form())
        files.append(self._generate_signup_form())
        files.append(self._generate_protected_route())

        # Auth pages
        files.append(self._generate_login_page())
        files.append(self._generate_signup_page())

        # Index files
        files.append(self._generate_components_index())

        return files

    def _generate_auth_context(self) -> GeneratedFile:
        """Generate AuthContext with useAuth() hook.

        Returns:
            GeneratedFile for AuthContext.tsx
        """
        user_model = self.spec.auth.user_model
        username_field = self.spec.auth.username_field

        content = self.renderer.render_file(
            "frontend/auth/AuthContext.tsx.jinja2",
            context={
                "user_model": user_model,
                "username_field": username_field,
            },
        )

        return GeneratedFile(
            path=self.contexts_path / "AuthContext.tsx",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Auth context with useAuth hook",
        )

    def _generate_login_form(self) -> GeneratedFile:
        """Generate LoginForm component.

        Returns:
            GeneratedFile for LoginForm.tsx
        """
        username_field = self.spec.auth.username_field
        input_type = "email" if username_field == "email" else "text"

        content = self.renderer.render_file(
            "frontend/auth/LoginForm.tsx.jinja2",
            context={
                "username_field": username_field,
                "username_field_title": username_field.title(),
                "input_type": input_type,
            },
        )

        return GeneratedFile(
            path=self.components_path / "LoginForm.tsx",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Login form component",
        )

    def _generate_signup_form(self) -> GeneratedFile:
        """Generate SignupForm component.

        Returns:
            GeneratedFile for SignupForm.tsx
        """
        username_field = self.spec.auth.username_field
        password_config = self.spec.auth
        input_type = "email" if username_field == "email" else "text"

        content = self.renderer.render_file(
            "frontend/auth/SignupForm.tsx.jinja2",
            context={
                "username_field": username_field,
                "username_field_title": username_field.title(),
                "input_type": input_type,
                "password_min_length": password_config.password_min_length,
                "password_require_uppercase": password_config.password_require_uppercase,
                "password_require_lowercase": password_config.password_require_lowercase,
                "password_require_number": password_config.password_require_number,
                "password_require_special": password_config.password_require_special,
            },
        )

        return GeneratedFile(
            path=self.components_path / "SignupForm.tsx",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Signup form component",
        )

    def _generate_protected_route(self) -> GeneratedFile:
        """Generate ProtectedRoute wrapper component.

        Returns:
            GeneratedFile for ProtectedRoute.tsx
        """
        content = self.renderer.render_file(
            "frontend/auth/ProtectedRoute.tsx.jinja2",
            context={},
        )

        return GeneratedFile(
            path=self.components_path / "ProtectedRoute.tsx",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Protected route wrapper",
        )

    def _generate_login_page(self) -> GeneratedFile:
        """Generate Login page component.

        Returns:
            GeneratedFile for Login.tsx
        """
        content = self.renderer.render_file(
            "frontend/auth/Login.tsx.jinja2",
            context={},
        )

        return GeneratedFile(
            path=self.pages_path / "Login.tsx",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Login page",
        )

    def _generate_signup_page(self) -> GeneratedFile:
        """Generate Signup page component.

        Returns:
            GeneratedFile for Signup.tsx
        """
        content = self.renderer.render_file(
            "frontend/auth/Signup.tsx.jinja2",
            context={},
        )

        return GeneratedFile(
            path=self.pages_path / "Signup.tsx",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Signup page",
        )

    def _generate_components_index(self) -> GeneratedFile:
        """Generate index file for auth components.

        Returns:
            GeneratedFile for components/auth/index.ts
        """
        content = self.renderer.render_file(
            "frontend/auth/index.ts.jinja2",
            context={},
        )

        return GeneratedFile(
            path=self.components_path / "index.ts",
            content=content,
            strategy=FileStrategy.ALWAYS_OVERWRITE,
            description="Auth components index",
        )
