"""Egress proxy generator — produces Squid config for domain-based egress control.

The app container sets HTTP_PROXY/HTTPS_PROXY to point at the Squid sidecar,
and Squid enforces the domain allowlist at the network layer. This approach:
- Works with HTTPS (CONNECT method for TLS tunnels)
- Cannot be bypassed by the app process
- Matches on hostnames, not IP addresses
- Is auditable (Squid access logs)
"""

from typing import List, Set

from ..analyzer.models import AppAnalysis
from ..analyzer.ai_usage import AI_PACKAGES


# Infrastructure domains that should always be reachable (pip installs, etc.)
_INFRA_DOMAINS = {
    "pypi.org",
    "files.pythonhosted.org",
}


def collect_egress_domains(analysis: AppAnalysis) -> List[str]:
    """Collect all domains the app needs to reach from analysis results.

    Merges domains from:
    - External service detection (SDK-based, e.g. boto3 → *.amazonaws.com)
    - AI usage detection (e.g. openai → api.openai.com)
    - Infrastructure domains (pypi, etc.)
    """
    domains: Set[str] = set()

    for svc in analysis.external_services:
        for d in svc.domains:
            if d and d != "N/A":
                domains.add(d)

    # AI packages store domains in AI_PACKAGES, not in the model
    for ai in analysis.ai_usage:
        pkg_info = AI_PACKAGES.get(ai.sdk)
        if pkg_info:
            for d in pkg_info[2]:  # index 2 = egress_domains list
                if d:
                    domains.add(d)

    domains |= _INFRA_DOMAINS

    return sorted(domains)


def generate_squid_config(domains: List[str]) -> str:
    """Generate a Squid proxy configuration with a domain allowlist.

    Args:
        domains: List of allowed destination domains (e.g. ["api.openai.com", "*.amazonaws.com"])

    Returns:
        squid.conf content as a string
    """
    acl_lines = []
    for domain in sorted(set(domains)):
        if domain.startswith("*."):
            # Wildcard: Squid uses .domain.com syntax for suffix matching
            acl_lines.append(f"acl allowed_domains dstdomain {domain[1:]}")
        else:
            acl_lines.append(f"acl allowed_domains dstdomain {domain}")

    acl_block = "\n".join(acl_lines) if acl_lines else "# No domains configured — all egress blocked"

    return f'''# Squid egress proxy configuration
# Generated by harden CLI (OSS)
#
# This proxy enforces a domain-based allowlist for outbound traffic.
# The app container sets HTTP_PROXY/HTTPS_PROXY to route through here.
# Only domains listed below are reachable from the app.
#
# Architecture:
#   [app container] --HTTP_PROXY--> [squid:3128] --> [internet]
#                                       |
#                                  domain allowlist
#                                  enforced here

# Listen on port 3128 (internal only)
http_port 3128

# ============================================================================
# Domain Allowlist
# ============================================================================
# Derived from static analysis of the project's imports and URLs.
# Edit this list to add or remove allowed destinations.
{acl_block}

# ============================================================================
# Access Control
# ============================================================================
acl SSL_ports port 443
acl Safe_ports port 80
acl Safe_ports port 443
acl CONNECT method CONNECT

# Block non-standard ports
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

# Allow traffic to listed domains only
http_access allow allowed_domains
http_access deny all

# ============================================================================
# Logging
# ============================================================================
access_log stdio:/var/log/squid/access.log combined
cache_log stdio:/var/log/squid/cache.log

# ============================================================================
# Performance
# ============================================================================
cache deny all
connect_timeout 30 seconds
read_timeout 300 seconds
request_timeout 300 seconds
maximum_object_size 0

# ============================================================================
# Security
# ============================================================================
via off
forwarded_for off
httpd_suppress_version_string on
pid_filename /var/run/squid/squid.pid

# ============================================================================
# Breakglass
# ============================================================================
# To temporarily allow all egress, replace the ACL section above with:
#   http_access allow all
'''
