"""Configuration file generator for odoorpc-toolbox.

Generates YAML configuration files with all available sections including
the extended transport, retry, timeout, and cache configuration.

Usage as library:
    from odoorpc_toolbox.config_generator import generate_config
    generate_config("my_config.yaml")

Usage as CLI:
    odoorpc-init-config                     # Creates odoo_config.yaml
    odoorpc-init-config -o custom.yaml      # Custom output path
    odoorpc-init-config --minimal           # Server section only
"""

from __future__ import annotations

import argparse
import sys
from pathlib import Path

# Default YAML template with all sections
_FULL_CONFIG_TEMPLATE = """\
# OdooRPC Toolbox Configuration
# Generated by odoorpc-init-config
# Documentation: https://github.com/equitania/odoorpc-toolbox

# Server connection (required)
Server:
  url: {url}
  port: {port}
  user: {user}
  password: {password}
  database: {database}
  protocol: {protocol}

# Transport backend (optional - defaults shown)
# Requires: pip install odoorpc-toolbox[httpx]
transport:
  backend: auto              # "auto" (tries httpx, falls back to urllib), "urllib", or "httpx"
  http2: true                # Enable HTTP/2 (httpx only)
  pool_connections: 10       # Max pooled connections (httpx only)

# Retry configuration (optional - defaults shown)
# Only active with httpx transport backend
retry:
  max_attempts: 3            # Maximum retry attempts (1 = no retry)
  backoff_factor: 0.5        # Exponential backoff base in seconds
  retry_on:                  # HTTP status codes that trigger retry
    - 502
    - 503
    - 504

# Timeout configuration (optional - defaults shown)
timeout:
  connect: 30                # Connection timeout in seconds
  read: 120                  # Read timeout in seconds

# Cache configuration (optional - defaults shown)
# Used by cached helper methods (get_state_id, get_country_id_by_code, etc.)
cache:
  maxsize: 256               # Maximum number of cached entries
  ttl: 3600                  # Time-to-live in seconds (0 = no expiry)
"""

_MINIMAL_CONFIG_TEMPLATE = """\
# OdooRPC Toolbox Configuration
# Generated by odoorpc-init-config
# Documentation: https://github.com/equitania/odoorpc-toolbox

# Server connection (required)
Server:
  url: {url}
  port: {port}
  user: {user}
  password: {password}
  database: {database}
  protocol: {protocol}
"""


def generate_config(
    output_path: str | Path = "odoo_config.yaml",
    *,
    url: str = "https://odoo.example.com",
    port: int = 443,
    user: str = "admin",
    password: str = "admin",
    database: str = "mydb",
    protocol: str = "jsonrpc",
    minimal: bool = False,
    overwrite: bool = False,
) -> Path:
    """Generate a YAML configuration file for odoorpc-toolbox.

    Args:
        output_path: Path for the generated config file.
        url: Odoo server URL.
        port: Odoo server port.
        user: Username for authentication.
        password: Password for authentication.
        database: Database name.
        protocol: RPC protocol (jsonrpc or jsonrpc+ssl).
        minimal: If True, generate only the Server section.
        overwrite: If True, overwrite existing files.

    Returns:
        Path to the generated configuration file.

    Raises:
        FileExistsError: If file exists and overwrite is False.
    """
    path = Path(output_path)

    if path.exists() and not overwrite:
        raise FileExistsError(f"Configuration file already exists: {path}. Use overwrite=True to replace.")

    template = _MINIMAL_CONFIG_TEMPLATE if minimal else _FULL_CONFIG_TEMPLATE
    content = template.format(
        url=url,
        port=port,
        user=user,
        password=password,
        database=database,
        protocol=protocol,
    )

    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")
    return path


def main(argv: list[str] | None = None) -> int:
    """CLI entry point for odoorpc-init-config.

    Args:
        argv: Command line arguments (defaults to sys.argv[1:]).

    Returns:
        Exit code (0 for success, 1 for error).
    """
    parser = argparse.ArgumentParser(
        prog="odoorpc-init-config",
        description="Generate a YAML configuration file for odoorpc-toolbox.",
    )
    parser.add_argument(
        "-o",
        "--output",
        default="odoo_config.yaml",
        help="Output file path (default: odoo_config.yaml)",
    )
    parser.add_argument(
        "--url",
        default="https://odoo.example.com",
        help="Odoo server URL (default: https://odoo.example.com)",
    )
    parser.add_argument(
        "--port",
        type=int,
        default=443,
        help="Odoo server port (default: 443)",
    )
    parser.add_argument(
        "--user",
        default="admin",
        help="Username (default: admin)",
    )
    parser.add_argument(
        "--database",
        default="mydb",
        help="Database name (default: mydb)",
    )
    parser.add_argument(
        "--protocol",
        default="jsonrpc",
        choices=["jsonrpc", "jsonrpc+ssl"],
        help="RPC protocol (default: jsonrpc)",
    )
    parser.add_argument(
        "--minimal",
        action="store_true",
        help="Generate minimal config (Server section only)",
    )
    parser.add_argument(
        "--force",
        action="store_true",
        help="Overwrite existing config file",
    )

    args = parser.parse_args(argv)

    try:
        path = generate_config(
            output_path=args.output,
            url=args.url,
            port=args.port,
            user=args.user,
            password="admin",
            database=args.database,
            protocol=args.protocol,
            minimal=args.minimal,
            overwrite=args.force,
        )
        print(f"Configuration file created: {path}")
        return 0
    except FileExistsError as e:
        print(f"Error: {e}", file=sys.stderr)
        print("Use --force to overwrite.", file=sys.stderr)
        return 1
    except OSError as e:
        print(f"Error writing config file: {e}", file=sys.stderr)
        return 1
