"""Bridge base class for platform-specific generators."""
from __future__ import annotations

from abc import ABC, abstractmethod
from pathlib import Path

import click

STATO_MARKER = "Generated by stato"

_PLATFORM_MAP = {
    "CLAUDE.md": "claude",
    ".cursorrules": "cursor",
    "AGENTS.md": "codex",
    "README.stato.md": "generic",
}


def check_existing_bridge(path: Path, force: bool = False) -> str:
    """Check if bridge file exists and determine action.

    Returns: 'create', 'overwrite', 'append', 'rename', 'cancel'
    """
    if not path.exists():
        return "create"

    content = path.read_text()
    if STATO_MARKER in content:
        return "overwrite"  # stato owns this file

    if force:
        return "overwrite"

    # Interactive prompt
    filename = path.name
    click.echo(f"\n{filename} already exists and was not generated by stato.\n")
    click.echo("Options:")
    click.echo("  [o] Overwrite (replaces existing file)")
    click.echo("  [a] Append stato section at the end")
    click.echo(f"  [s] Save as {filename}.stato instead")
    click.echo("  [c] Cancel")
    choice = click.prompt(
        "\nChoice", type=click.Choice(["o", "a", "s", "c"]), default="c"
    )

    return {"o": "overwrite", "a": "append", "s": "rename", "c": "cancel"}[choice]


class BridgeBase(ABC):
    """Base class for platform bridge generators."""

    def __init__(self, project_dir: Path):
        self.project_dir = project_dir
        self.stato_dir = project_dir / ".stato"

    @abstractmethod
    def generate(self) -> str:
        """Generate the bridge file content as a string."""
        ...

    @abstractmethod
    def output_filename(self) -> str:
        """The filename this bridge writes to (e.g., 'CLAUDE.md')."""
        ...

    def _platform_name(self) -> str:
        """Derive platform name from output filename."""
        return _PLATFORM_MAP.get(self.output_filename(), "auto")

    def _marker_comment(self) -> str:
        """Return the stato marker comment for this platform."""
        platform = self._platform_name()
        if self.output_filename().endswith(".md"):
            return f"<!-- {STATO_MARKER}. Do not edit manually. Regenerate with: stato bridge --platform {platform} -->"
        return f"# {STATO_MARKER}. Do not edit manually. Regenerate with: stato bridge --platform {platform}"

    def _append_separator(self) -> str:
        """Return the separator used when appending to an existing file."""
        platform = self._platform_name()
        if self.output_filename().endswith(".md"):
            return (
                "\n---\n"
                f"<!-- {STATO_MARKER}. Content below is managed by stato bridge. -->\n"
                f"<!-- Regenerate with: stato bridge --platform {platform} -->\n\n"
            )
        return (
            "\n# ---\n"
            f"# {STATO_MARKER}. Content below is managed by stato bridge.\n"
            f"# Regenerate with: stato bridge --platform {platform}\n\n"
        )

    def write(self, force: bool = False) -> tuple[Path, str]:
        """Generate and write the bridge file.

        Returns (path, action) where action is one of:
        'created', 'overwritten', 'appended', 'renamed', 'cancelled'
        """
        content = self.generate()
        output = self.project_dir / self.output_filename()

        action = check_existing_bridge(output, force)

        if action in ("create", "overwrite"):
            marker = self._marker_comment()
            output.write_text(marker + "\n\n" + content)
            return output, "created" if action == "create" else "overwritten"
        elif action == "append":
            existing = output.read_text()
            separator = self._append_separator()
            output.write_text(existing + "\n" + separator + content)
            return output, "appended"
        elif action == "rename":
            alt_name = self.output_filename() + ".stato"
            alt_path = self.project_dir / alt_name
            marker = self._marker_comment()
            alt_path.write_text(marker + "\n\n" + content)
            return alt_path, "renamed"
        else:  # cancel
            return output, "cancelled"
