"""Interactive initialization wizard for NextDNS Blocker."""

import os
from pathlib import Path
from typing import Optional
from zoneinfo import ZoneInfo

import click
import requests

from .common import SECURE_FILE_MODE, validate_url
from .config import get_config_dir

# NextDNS API base URL for validation
NEXTDNS_API_URL = "https://api.nextdns.io"


def validate_api_credentials(api_key: str, profile_id: str) -> tuple[bool, str]:
    """
    Validate API credentials against NextDNS API.

    Args:
        api_key: NextDNS API key
        profile_id: NextDNS profile ID

    Returns:
        Tuple of (success, message)
    """
    try:
        response = requests.get(
            f"{NEXTDNS_API_URL}/profiles/{profile_id}/denylist",
            headers={"X-Api-Key": api_key},
            timeout=10,
        )

        if response.status_code == 200:
            return True, "Credentials valid"
        elif response.status_code == 401:
            return False, "Invalid API key"
        elif response.status_code == 404:
            return False, "Profile ID not found"
        else:
            return False, f"API error: {response.status_code}"

    except requests.exceptions.Timeout:
        return False, "Connection timeout"
    except requests.exceptions.ConnectionError:
        return False, "Connection failed"
    except requests.exceptions.RequestException as e:
        return False, f"Request error: {e}"


def validate_timezone(tz_str: str) -> tuple[bool, str]:
    """
    Validate a timezone string.

    Args:
        tz_str: Timezone string (e.g., 'America/Mexico_City')

    Returns:
        Tuple of (success, message)
    """
    try:
        ZoneInfo(tz_str)
        return True, "Valid timezone"
    except KeyError:
        return False, f"Invalid timezone: {tz_str}"


def create_env_file(
    config_dir: Path,
    api_key: str,
    profile_id: str,
    timezone: str,
    domains_url: Optional[str] = None,
) -> Path:
    """
    Create .env file with configuration.

    Args:
        config_dir: Directory to create .env in
        api_key: NextDNS API key
        profile_id: NextDNS profile ID
        timezone: Timezone string
        domains_url: Optional URL for remote domains.json

    Returns:
        Path to created .env file
    """
    config_dir.mkdir(parents=True, exist_ok=True)

    env_file = config_dir / ".env"

    content = f"""# NextDNS Blocker Configuration
# Generated by 'nextdns-blocker init'

# NextDNS API credentials (required)
NEXTDNS_API_KEY={api_key}
NEXTDNS_PROFILE_ID={profile_id}

# Timezone for schedule evaluation
TIMEZONE={timezone}
"""

    if domains_url:
        content += f"""
# Remote domains.json URL (optional)
DOMAINS_URL={domains_url}
"""

    # Write with secure permissions
    fd = os.open(env_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, SECURE_FILE_MODE)
    try:
        with os.fdopen(fd, "w") as f:
            f.write(content)
    except OSError:
        os.close(fd)
        raise

    return env_file


def create_sample_domains(config_dir: Path) -> Path:
    """
    Create a sample domains.json file.

    Args:
        config_dir: Directory to create domains.json in

    Returns:
        Path to created domains.json file
    """
    config_dir.mkdir(parents=True, exist_ok=True)

    domains_file = config_dir / "domains.json"

    content = """{
  "domains": [
    {
      "domain": "example.com",
      "schedule": {
        "available_hours": [
          {
            "days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
            "time_ranges": [
              {"start": "18:00", "end": "21:00"}
            ]
          },
          {
            "days": ["saturday", "sunday"],
            "time_ranges": [
              {"start": "10:00", "end": "22:00"}
            ]
          }
        ]
      }
    }
  ],
  "allowlist": []
}
"""

    domains_file.write_text(content)
    return domains_file


def run_interactive_wizard(
    config_dir_override: Optional[Path] = None, domains_url: Optional[str] = None
) -> bool:
    """
    Run the interactive setup wizard.

    Args:
        config_dir_override: Optional config directory override
        domains_url: Optional URL for remote domains.json

    Returns:
        True if setup completed successfully
    """
    click.echo()
    click.echo(click.style("  NextDNS Blocker Setup", fg="cyan", bold=True))
    click.echo(click.style("  " + "=" * 21, fg="cyan"))
    click.echo()

    # Prompt for API key
    api_key = click.prompt("  API Key (from https://my.nextdns.io/account)", hide_input=True)

    if not api_key or not api_key.strip():
        click.echo(click.style("\n  Error: API key is required\n", fg="red"))
        return False

    api_key = api_key.strip()

    # Prompt for Profile ID
    profile_id = click.prompt("  Profile ID (from URL my.nextdns.io/<profile_id>)")

    if not profile_id or not profile_id.strip():
        click.echo(click.style("\n  Error: Profile ID is required\n", fg="red"))
        return False

    profile_id = profile_id.strip()

    # Prompt for timezone
    default_tz = "UTC"
    timezone = click.prompt("  Timezone", default=default_tz)
    timezone = timezone.strip()

    # Validate timezone
    tz_valid, tz_msg = validate_timezone(timezone)
    if not tz_valid:
        click.echo(click.style(f"\n  Error: {tz_msg}", fg="red"))
        click.echo("  See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n")
        return False

    # Prompt for optional DOMAINS_URL (only if not provided via --url)
    if not domains_url:
        click.echo()
        click.echo("  Domains URL (optional, press Enter to skip)")
        url_input = click.prompt("  URL", default="", show_default=False)
        url_input = url_input.strip()

        if url_input:
            if validate_url(url_input):
                domains_url = url_input
            else:
                click.echo(
                    click.style("\n  Error: Invalid URL format (must be http/https)", fg="red")
                )
                return False

    # Validate credentials
    click.echo()
    click.echo("  Validating credentials... ", nl=False)

    valid, msg = validate_api_credentials(api_key, profile_id)

    if valid:
        click.echo(click.style("OK", fg="green"))
    else:
        click.echo(click.style("FAILED", fg="red"))
        click.echo(click.style(f"\n  Error: {msg}\n", fg="red"))
        return False

    # Determine config directory
    config_dir = get_config_dir(config_dir_override)

    # Create .env file
    click.echo()
    env_file = create_env_file(config_dir, api_key, profile_id, timezone, domains_url)
    click.echo(f"  Configuration saved to: {env_file}")

    # Offer to create sample domains.json
    if not domains_url:
        click.echo()
        create_sample = click.confirm("  Create sample domains.json?", default=True)

        if create_sample:
            domains_file = create_sample_domains(config_dir)
            click.echo(f"  Created: {domains_file}")

    # Success message
    click.echo()
    click.echo(click.style("  Setup complete!", fg="green", bold=True))
    click.echo("  Run 'nextdns-blocker sync' to start blocking.")
    click.echo()

    return True


def run_non_interactive(
    config_dir_override: Optional[Path] = None, domains_url: Optional[str] = None
) -> bool:
    """
    Run non-interactive setup using environment variables.

    Expects:
        NEXTDNS_API_KEY: API key
        NEXTDNS_PROFILE_ID: Profile ID
        TIMEZONE: Timezone (optional, defaults to UTC)

    Args:
        config_dir_override: Optional config directory override
        domains_url: Optional URL for remote domains.json

    Returns:
        True if setup completed successfully
    """
    api_key = os.environ.get("NEXTDNS_API_KEY")
    profile_id = os.environ.get("NEXTDNS_PROFILE_ID")
    timezone = os.environ.get("TIMEZONE", "UTC")

    if not api_key:
        click.echo("Error: NEXTDNS_API_KEY environment variable not set", err=True)
        return False

    if not profile_id:
        click.echo("Error: NEXTDNS_PROFILE_ID environment variable not set", err=True)
        return False

    # Validate timezone
    tz_valid, tz_msg = validate_timezone(timezone)
    if not tz_valid:
        click.echo(f"Error: {tz_msg}", err=True)
        return False

    # Validate credentials
    valid, msg = validate_api_credentials(api_key, profile_id)
    if not valid:
        click.echo(f"Error: {msg}", err=True)
        return False

    # Determine config directory
    config_dir = get_config_dir(config_dir_override)

    # Create .env file
    env_file = create_env_file(config_dir, api_key, profile_id, timezone, domains_url)
    click.echo(f"Configuration saved to: {env_file}")

    return True
