"""
Purpose: Load and merge host configuration from YAML file with code parameters
LLM-Note:
  Dependencies: imports from [pathlib, yaml] | imported by [network/host/server.py] | no tests (simple utility)
  Data flow: load_host_config(co_dir, **code_params) → reads .co/host.yaml if exists → yaml.safe_load() → merges with code_params (code overrides YAML) → returns dict | load_list_file(path) → reads line-by-line → strips comments (#) → returns list of addresses
  State/Effects: reads .co/host.yaml from filesystem | reads whitelist/blacklist files | no writes | no persistent state
  Integration: exposes load_host_config(co_dir, **code_params), load_list_file(file_path) | used by host() function to merge configuration sources | code parameters take precedence over YAML
  Performance: simple file I/O | YAML parsing via safe_load | no caching (loads on each call)
  Errors: returns empty dict/list if file doesn't exist | YAML parsing errors bubble up

Load host.yaml configuration file.

host.yaml is optional — generated by 'co init' or 'co create'.
Code parameters override YAML values.
"""

from pathlib import Path
import yaml
import logging

logger = logging.getLogger(__name__)


# Default file upload limits
DEFAULT_FILE_LIMITS = {
    "max_file_size": 10,                       # MB per file (both WebSocket and HTTP)
    "max_files_per_request": 10                # Max number of files in one request
}


def load_host_config(co_dir: Path = None, **code_params) -> dict:
    """
    Load host configuration from .co/host.yaml.

    Priority (highest to lowest):
    1. Code parameters (passed to host())
    2. Config file (.co/host.yaml) — optional
    3. Default values (hardcoded)

    File size limits are specified in MB and converted to bytes internally.
    Permissions are loaded as-is from YAML (unified permission structure).

    Args:
        co_dir: Path to .co directory (defaults to ./.co/)
        **code_params: Code parameters from host() function

    Returns:
        Config dict from YAML with code param overrides and defaults
        Includes 'permissions' field if defined in host.yaml
    """
    if co_dir is None:
        co_dir = Path.cwd() / '.co'

    # Start with defaults
    config = DEFAULT_FILE_LIMITS.copy()

    # Load YAML config (overrides defaults)
    config_path = co_dir / 'host.yaml'
    if config_path.exists():
        with open(config_path, 'r', encoding='utf-8') as f:
            yaml_config = yaml.safe_load(f) or {}
            config.update(yaml_config)

    # Code params override YAML (only if not None)
    for key, value in code_params.items():
        if value is not None:
            config[key] = value

    return config


def load_list_file(file_path: str | Path | None) -> list:
    """
    Load addresses from whitelist/blacklist file.

    File format: one address per line, comments with #

    Args:
        file_path: Path to list file

    Returns:
        List of addresses (empty list if file doesn't exist)
    """
    if file_path is None:
        return []

    path = Path(file_path)
    if not path.exists():
        return []

    addresses = []
    with open(path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if '#' in line:
                line = line[:line.index('#')].strip()
            if line:
                addresses.append(line)

    return addresses


def validate_files(files: list, config: dict) -> None:
    """Validate uploaded files against configured limits.

    Args:
        files: List of file dicts with 'name' and 'data' (bytes)
        config: Host config with limits (max_file_size in MB)

    Raises:
        ValueError: If files exceed limits with clear error message
    """
    if not files:
        return

    # Get limits from config (already has defaults from load_host_config)
    max_count = config.get("max_files_per_request", DEFAULT_FILE_LIMITS["max_files_per_request"])
    max_size_mb = config.get("max_file_size", DEFAULT_FILE_LIMITS["max_file_size"])
    max_size_bytes = max_size_mb * 1024 * 1024  # Convert MB to bytes

    # Log upload attempt
    total_size = sum(len(f["data"]) for f in files)
    total_mb = total_size / 1024 / 1024
    file_names = [f["name"] for f in files]
    logger.info(
        f"File upload: {len(files)} file(s), {total_mb:.2f}MB total - {', '.join(file_names)}"
    )

    # Validate count
    if len(files) > max_count:
        logger.warning(
            f"File upload rejected: too many files ({len(files)} > {max_count})"
        )
        raise ValueError(
            f"Too many files: {len(files)} (max: {max_count}). "
            f"Increase max_files_per_request in host.yaml"
        )

    # Validate individual file sizes
    for f in files:
        size = len(f["data"])

        if size > max_size_bytes:
            mb = size / 1024 / 1024
            logger.warning(
                f"File upload rejected: {f['name']} too large ({mb:.1f}MB > {max_size_mb}MB)"
            )
            raise ValueError(
                f"File too large: {f['name']} ({mb:.1f}MB, max: {max_size_mb}MB). "
                f"Increase max_file_size in host.yaml"
            )

    logger.info(f"File upload validated: {len(files)} file(s) accepted")
