"""
This module handles the generation of configuration files for haniwers.
It creates starter configuration files based on templates.

:Usage:
```console
haniwers init [--force] [--no-env]
```
"""

import importlib.resources
import sys
from enum import Enum
from pathlib import Path
from datetime import datetime

import typer

from haniwers.v1.log.logger import logger as base_logger


class ConfigKind(str, Enum):
    """Types of configuration files that can be generated.

    This enum inherits from str to all:
    1. Direct string comparison (kind == "all")
    2. Automatic string conversion (str(kind))
    3. Easy conversion from string input (ConfigKind("all"))
    """

    ALL = "all"
    CONFIG = "config"
    ENV = "env"


def find_template(template_name: str) -> Path | None:
    """Find a template file in possible locations.

    Args:
        template_name (str): Name of the template file.

    Returns:
        Path | None: Path to the template if found, None otherwise.
    """
    # Try multiple possible paths to find the template
    possible_sources = [
        importlib.resources.files("haniwers.v1.assets").joinpath(
            template_name
        ),  # Installed package
        Path(__file__).parent.parent / "assets" / template_name,  # Relative to this file
        Path(f"src/haniwers/v1/assets/{template_name}"),  # Project root in dev
    ]

    return next((p for p in possible_sources if p.exists()), None)


def create_file_from_template(
    template_name: str,
    dest_path: Path,
    force: bool = False,
    replacements: dict[str, str] | None = None,
    header_comment: str | None = None,
) -> bool:
    """Create a file from a template.

    Args:
        template_name (str): Name of the template file.
        dest_path (Path): Destination path for the file.
        force (bool): If True, overwrite existing file without confirmation.
        replacements (dict[str, str] | None): Dictionary of text replacements to apply.
        header_comment (str | None): Header comment to add to the file.

    Returns:
        bool: True if successful, False otherwise.
    """
    if dest_path.exists() and not force:
        typer.echo(f"❌ {dest_path} already exists. Use --force to overwrite.")
        return False

    # Find the template
    src = find_template(template_name)
    if not src:
        typer.echo(
            f"❌ Template file {template_name} not found. Check if haniwers is installed correctly."
        )
        return False

    try:
        # Create parent directories if needed
        dest_path.parent.mkdir(parents=True, exist_ok=True)

        # Read the template
        with src.open("r") as source_file:
            content = source_file.read()

        # Add header comment if provided
        if header_comment and not content.startswith(header_comment):
            content = f"{header_comment}\n\n{content}"

        # Apply replacements if provided
        if replacements:
            for old, new in replacements.items():
                content = content.replace(old, new)

        # Write the modified content
        with dest_path.open("w") as dest_file:
            dest_file.write(content)

        typer.echo(f"✅ Created {dest_path} from template.")
        return True

    except Exception as e:
        typer.echo(f"❌ Error creating file: {e}")
        return False


class ConfigGenerator:
    def __init__(self, force: bool = False):
        self.force = force
        self.logger = base_logger.bind(context=self.__class__.__name__)

    def run(self, kind: ConfigKind = ConfigKind.ALL) -> None:
        try:
            config_kind = ConfigKind(kind.lower())
        except ValueError:
            typer.echo(f"❌ Invalid configuration kind: {kind}")
            typer.echo("Valid kinds: all, config, env")
            sys.exit(1)

        self.logger.info(f"Generating config kind: {kind}")
        success = True

        if config_kind in [ConfigKind.ALL, ConfigKind.CONFIG]:
            success = success and self.create_config_file()

        if config_kind in [ConfigKind.ALL, ConfigKind.ENV]:
            success = success and self.create_env_file()

        if not success:
            sys.exit(1)

    def create_config_file(self) -> bool:
        dest = Path("./hnw.toml")
        header_comment = (
            "# >>>>> Generated by haniwers init",
            f"# >>>>> At {datetime.now().isoformat()}",
        )
        replacements = {"enabled = true": "enabled = false  # Set to true once configured"}

        self.logger.debug(f"Creating {dest}")
        success = create_file_from_template(
            template_name="config.toml",
            dest_path=dest,
            force=self.force,
            replacements=replacements,
            header_comment=("\n").join(header_comment),
        )

        if success:
            self.logger.success(f"Generated config file: {dest}")
            typer.echo("Edit this file to configure your measurement.")

        return success

    def create_env_file(self) -> bool:
        dest = Path("./.env.haniwers")
        header_comment = (
            "# >>>>> Generated by haniwers init",
            f"# >>>>> At {datetime.now().isoformat()}",
        )

        self.logger.debug(f"Creating {dest}")
        success = create_file_from_template(
            template_name="env.haniwers",
            dest_path=dest,
            force=self.force,
            header_comment=("\n").join(header_comment),
        )

        if success:
            self.logger.success(f"Generated env file: {dest}")
            typer.echo("Edit this file to configure your environment settings.")

        return success


if __name__ == "__main__":
    """Self test.

    $ uv run src/haniwers/v1/config/generator.py
    """
    ConfigGenerator(force=True).run(kind=ConfigKind.CONFIG)
