"""Cloudflare tunnel configuration generation."""

import yaml
from pathlib import Path

from paracord.auth.config import ProjectInfo


def generate_tunnel_config(
    projects: dict[str, ProjectInfo],
    tunnel_name: str = "paracord",
    domain: str = "example.com",
) -> str:
    """Generate a cloudflared tunnel configuration YAML.

    Args:
        projects: Dict of path -> ProjectInfo
        tunnel_name: Name of the Cloudflare tunnel
        domain: Base domain for subdomains

    Returns:
        YAML configuration string
    """
    ingress_rules: list[dict] = []

    for path, project in projects.items():
        cloudflare = project.get("cloudflare", {})
        subdomain = cloudflare.get("subdomain")

        if subdomain:
            port = project.get("port", 8000)
            hostname = f"{subdomain}.{domain}"

            ingress_rules.append({
                "hostname": hostname,
                "service": f"http://localhost:{port}",
            })

    # Add catch-all rule (required by cloudflared)
    ingress_rules.append({
        "service": "http_status:404",
    })

    config = {
        "tunnel": tunnel_name,
        "credentials-file": f"~/.cloudflared/{tunnel_name}.json",
        "ingress": ingress_rules,
    }

    return yaml.safe_dump(config, default_flow_style=False, sort_keys=False)


def generate_project_tunnel_config(
    project: ProjectInfo,
    path: str,
    tunnel_name: str = "paracord",
    domain: str = "example.com",
) -> str:
    """Generate tunnel config for a single project.

    Args:
        project: ProjectInfo for the project
        path: Path to the project
        tunnel_name: Name of the Cloudflare tunnel
        domain: Base domain for subdomains

    Returns:
        YAML configuration string
    """
    return generate_tunnel_config({path: project}, tunnel_name, domain)


def get_tunnel_instructions(tunnel_name: str = "paracord") -> str:
    """Get instructions for setting up a Cloudflare tunnel.

    Args:
        tunnel_name: Name of the tunnel

    Returns:
        Formatted instructions string
    """
    return f"""Cloudflare Tunnel Setup Instructions:

1. Install cloudflared:
   brew install cloudflare/cloudflare/cloudflared   (macOS)
   # Or download from https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/

2. Authenticate cloudflared:
   cloudflared tunnel login

3. Create a tunnel:
   cloudflared tunnel create {tunnel_name}

4. Configure DNS (for each subdomain):
   cloudflared tunnel route dns {tunnel_name} <subdomain>.<your-domain>

5. Save the generated config to ~/.cloudflared/config.yml

6. Run the tunnel:
   cloudflared tunnel run {tunnel_name}

For more info: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/
"""


def validate_subdomain(subdomain: str) -> tuple[bool, str | None]:
    """Validate a subdomain string.

    Args:
        subdomain: Subdomain to validate

    Returns:
        Tuple of (is_valid, error_message)
    """
    if not subdomain:
        return False, "Subdomain cannot be empty"

    if len(subdomain) > 63:
        return False, "Subdomain must be 63 characters or less"

    if not subdomain[0].isalnum():
        return False, "Subdomain must start with a letter or number"

    if not subdomain[-1].isalnum():
        return False, "Subdomain must end with a letter or number"

    for char in subdomain:
        if not (char.isalnum() or char == "-"):
            return False, "Subdomain can only contain letters, numbers, and hyphens"

    return True, None
