"""Configuration commands for AITBC CLI"""

import click
import os
import shlex
import subprocess
import yaml
import json
from pathlib import Path
from typing import Optional, Dict, Any
from ..config import get_config, Config
from ..utils import output, error, success


@click.group()
def config():
    """Manage CLI configuration"""
    pass


@config.command()
@click.pass_context
def show(ctx):
    """Show current configuration"""
    config = ctx.obj['config']
    
    config_dict = {
        "coordinator_url": config.coordinator_url,
        "api_key": "***REDACTED***" if config.api_key else None,
        "timeout": getattr(config, 'timeout', 30),
        "config_file": getattr(config, 'config_file', None)
    }
    
    output(config_dict, ctx.obj['output_format'])


@config.command()
@click.argument("key")
@click.argument("value")
@click.option("--global", "global_config", is_flag=True, help="Set global config")
@click.pass_context
def set(ctx, key: str, value: str, global_config: bool):
    """Set configuration value"""
    config = ctx.obj['config']
    
    # Determine config file path
    if global_config:
        config_dir = Path.home() / ".config" / "aitbc"
        config_dir.mkdir(parents=True, exist_ok=True)
        config_file = config_dir / "config.yaml"
    else:
        config_file = Path.cwd() / ".aitbc.yaml"
    
    # Load existing config
    if config_file.exists():
        with open(config_file) as f:
            config_data = yaml.safe_load(f) or {}
    else:
        config_data = {}
    
    # Set the value
    if key == "api_key":
        config_data["api_key"] = value
        if ctx.obj['output_format'] == 'table':
            success("API key set (use --global to set permanently)")
    elif key == "coordinator_url":
        config_data["coordinator_url"] = value
        if ctx.obj['output_format'] == 'table':
            success(f"Coordinator URL set to: {value}")
    elif key == "timeout":
        try:
            config_data["timeout"] = int(value)
            if ctx.obj['output_format'] == 'table':
                success(f"Timeout set to: {value}s")
        except ValueError:
            error("Timeout must be an integer")
            ctx.exit(1)
    else:
        error(f"Unknown configuration key: {key}")
        ctx.exit(1)
    
    # Save config
    with open(config_file, 'w') as f:
        yaml.dump(config_data, f, default_flow_style=False)
    
    output({
        "config_file": str(config_file),
        "key": key,
        "value": value
    }, ctx.obj['output_format'])


@config.command()
@click.option("--global", "global_config", is_flag=True, help="Show global config")
def path(global_config: bool):
    """Show configuration file path"""
    if global_config:
        config_dir = Path.home() / ".config" / "aitbc"
        config_file = config_dir / "config.yaml"
    else:
        config_file = Path.cwd() / ".aitbc.yaml"
    
    output({
        "config_file": str(config_file),
        "exists": config_file.exists()
    })


@config.command()
@click.option("--global", "global_config", is_flag=True, help="Edit global config")
@click.pass_context
def edit(ctx, global_config: bool):
    """Open configuration file in editor"""
    # Determine config file path
    if global_config:
        config_dir = Path.home() / ".config" / "aitbc"
        config_dir.mkdir(parents=True, exist_ok=True)
        config_file = config_dir / "config.yaml"
    else:
        config_file = Path.cwd() / ".aitbc.yaml"
    
    # Create if doesn't exist
    if not config_file.exists():
        config = ctx.obj['config']
        config_data = {
            "coordinator_url": config.coordinator_url,
            "timeout": getattr(config, 'timeout', 30)
        }
        with open(config_file, 'w') as f:
            yaml.dump(config_data, f, default_flow_style=False)
    
    # Open in editor
    editor = os.getenv('EDITOR', 'nano').strip() or 'nano'
    editor_cmd = shlex.split(editor)
    subprocess.run([*editor_cmd, str(config_file)], check=False)


@config.command()
@click.option("--global", "global_config", is_flag=True, help="Reset global config")
@click.pass_context
def reset(ctx, global_config: bool):
    """Reset configuration to defaults"""
    # Determine config file path
    if global_config:
        config_dir = Path.home() / ".config" / "aitbc"
        config_file = config_dir / "config.yaml"
    else:
        config_file = Path.cwd() / ".aitbc.yaml"
    
    if not config_file.exists():
        output({"message": "No configuration file found"})
        return
    
    if not click.confirm(f"Reset configuration at {config_file}?"):
        return
    
    # Remove config file
    config_file.unlink()
    success("Configuration reset to defaults")


@config.command()
@click.option("--format", "output_format", type=click.Choice(['yaml', 'json']), default='yaml', help="Output format")
@click.option("--global", "global_config", is_flag=True, help="Export global config")
@click.pass_context
def export(ctx, output_format: str, global_config: bool):
    """Export configuration"""
    # Determine config file path
    if global_config:
        config_dir = Path.home() / ".config" / "aitbc"
        config_file = config_dir / "config.yaml"
    else:
        config_file = Path.cwd() / ".aitbc.yaml"
    
    if not config_file.exists():
        error("No configuration file found")
        ctx.exit(1)
    
    with open(config_file) as f:
        config_data = yaml.safe_load(f) or {}
    
    # Redact sensitive data
    if 'api_key' in config_data:
        config_data['api_key'] = "***REDACTED***"
    
    if output_format == 'json':
        click.echo(json.dumps(config_data, indent=2))
    else:
        click.echo(yaml.dump(config_data, default_flow_style=False))


@config.command()
@click.argument("file_path")
@click.option("--merge", is_flag=True, help="Merge with existing config")
@click.option("--global", "global_config", is_flag=True, help="Import to global config")
@click.pass_context
def import_config(ctx, file_path: str, merge: bool, global_config: bool):
    """Import configuration from file"""
    import_file = Path(file_path)
    
    if not import_file.exists():
        error(f"File not found: {file_path}")
        ctx.exit(1)
    
    # Load import file
    try:
        with open(import_file) as f:
            if import_file.suffix.lower() == '.json':
                import_data = json.load(f)
            else:
                import_data = yaml.safe_load(f)
    except json.JSONDecodeError:
        error("Invalid JSON data")
        ctx.exit(1)
    except Exception as e:
        error(f"Failed to parse file: {e}")
        ctx.exit(1)
    
    # Determine target config file
    if global_config:
        config_dir = Path.home() / ".config" / "aitbc"
        config_dir.mkdir(parents=True, exist_ok=True)
        config_file = config_dir / "config.yaml"
    else:
        config_file = Path.cwd() / ".aitbc.yaml"
    
    # Load existing config if merging
    if merge and config_file.exists():
        with open(config_file) as f:
            config_data = yaml.safe_load(f) or {}
        config_data.update(import_data)
    else:
        config_data = import_data
    
    # Save config
    with open(config_file, 'w') as f:
        yaml.dump(config_data, f, default_flow_style=False)
    
    if ctx.obj['output_format'] == 'table':
        success(f"Configuration imported to {config_file}")


@config.command()
@click.pass_context
def validate(ctx):
    """Validate configuration"""
    config = ctx.obj['config']
    
    errors = []
    warnings = []
    
    # Validate coordinator URL
    if not config.coordinator_url:
        errors.append("Coordinator URL is not set")
    elif not config.coordinator_url.startswith(('http://', 'https://')):
        errors.append("Coordinator URL must start with http:// or https://")
    
    # Validate API key
    if not config.api_key:
        warnings.append("API key is not set")
    elif len(config.api_key) < 10:
        errors.append("API key appears to be too short")
    
    # Validate timeout
    timeout = getattr(config, 'timeout', 30)
    if not isinstance(timeout, (int, float)) or timeout <= 0:
        errors.append("Timeout must be a positive number")
    
    # Output results
    result = {
        "valid": len(errors) == 0,
        "errors": errors,
        "warnings": warnings
    }
    
    if errors:
        error("Configuration validation failed")
        ctx.exit(1)
    elif warnings:
        if ctx.obj['output_format'] == 'table':
            success("Configuration valid with warnings")
    else:
        if ctx.obj['output_format'] == 'table':
            success("Configuration is valid")
    
    output(result, ctx.obj['output_format'])


@config.command()
def environments():
    """List available environments"""
    env_vars = [
        'AITBC_COORDINATOR_URL',
        'AITBC_API_KEY',
        'AITBC_TIMEOUT',
        'AITBC_CONFIG_FILE',
        'CLIENT_API_KEY',
        'MINER_API_KEY',
        'ADMIN_API_KEY'
    ]
    
    env_data = {}
    for var in env_vars:
        value = os.getenv(var)
        if value:
            if 'API_KEY' in var:
                value = "***REDACTED***"
            env_data[var] = value
    
    output({
        "environment_variables": env_data,
        "note": "Use export VAR=value to set environment variables"
    })


@config.group()
def profiles():
    """Manage configuration profiles"""
    pass


@profiles.command()
@click.argument("name")
@click.pass_context
def save(ctx, name: str):
    """Save current configuration as a profile"""
    config = ctx.obj['config']
    
    # Create profiles directory
    profiles_dir = Path.home() / ".config" / "aitbc" / "profiles"
    profiles_dir.mkdir(parents=True, exist_ok=True)
    
    profile_file = profiles_dir / f"{name}.yaml"
    
    # Save profile (without API key)
    profile_data = {
        "coordinator_url": config.coordinator_url,
        "timeout": getattr(config, 'timeout', 30)
    }
    
    with open(profile_file, 'w') as f:
        yaml.dump(profile_data, f, default_flow_style=False)
    
    if ctx.obj['output_format'] == 'table':
        success(f"Profile '{name}' saved")


@profiles.command()
def list():
    """List available profiles"""
    profiles_dir = Path.home() / ".config" / "aitbc" / "profiles"
    
    if not profiles_dir.exists():
        output({"profiles": []})
        return
    
    profiles = []
    for profile_file in profiles_dir.glob("*.yaml"):
        with open(profile_file) as f:
            profile_data = yaml.safe_load(f)
        
        profiles.append({
            "name": profile_file.stem,
            "coordinator_url": profile_data.get("coordinator_url"),
            "timeout": profile_data.get("timeout", 30)
        })
    
    output({"profiles": profiles})


@profiles.command()
@click.argument("name")
@click.pass_context
def load(ctx, name: str):
    """Load a configuration profile"""
    profiles_dir = Path.home() / ".config" / "aitbc" / "profiles"
    profile_file = profiles_dir / f"{name}.yaml"
    
    if not profile_file.exists():
        error(f"Profile '{name}' not found")
        ctx.exit(1)
    
    with open(profile_file) as f:
        profile_data = yaml.safe_load(f)
    
    # Load to current config
    config_file = Path.cwd() / ".aitbc.yaml"
    
    with open(config_file, 'w') as f:
        yaml.dump(profile_data, f, default_flow_style=False)
    
    if ctx.obj['output_format'] == 'table':
        success(f"Profile '{name}' loaded")


@profiles.command()
@click.argument("name")
@click.pass_context
def delete(ctx, name: str):
    """Delete a configuration profile"""
    profiles_dir = Path.home() / ".config" / "aitbc" / "profiles"
    profile_file = profiles_dir / f"{name}.yaml"
    
    if not profile_file.exists():
        error(f"Profile '{name}' not found")
        ctx.exit(1)
    
    if not click.confirm(f"Delete profile '{name}'?"):
        return
    
    profile_file.unlink()
    if ctx.obj['output_format'] == 'table':
        success(f"Profile '{name}' deleted")


@config.command(name="set-secret")
@click.argument("key")
@click.argument("value")
@click.pass_context
def set_secret(ctx, key: str, value: str):
    """Set an encrypted configuration value"""
    from ..utils import encrypt_value
    
    config_dir = Path.home() / ".config" / "aitbc"
    config_dir.mkdir(parents=True, exist_ok=True)
    secrets_file = config_dir / "secrets.json"
    
    secrets = {}
    if secrets_file.exists():
        with open(secrets_file) as f:
            secrets = json.load(f)
    
    secrets[key] = encrypt_value(value)
    
    with open(secrets_file, "w") as f:
        json.dump(secrets, f, indent=2)
    
    # Restrict file permissions
    secrets_file.chmod(0o600)
    
    if ctx.obj['output_format'] == 'table':
        success(f"Secret '{key}' saved (encrypted)")
    output({"key": key, "status": "encrypted"}, ctx.obj['output_format'])


@config.command(name="get-secret")
@click.argument("key")
@click.pass_context
def get_secret(ctx, key: str):
    """Get a decrypted configuration value"""
    from ..utils import decrypt_value
    
    secrets_file = Path.home() / ".config" / "aitbc" / "secrets.json"
    
    if not secrets_file.exists():
        error("No secrets file found")
        ctx.exit(1)
        return
    
    with open(secrets_file) as f:
        secrets = json.load(f)
    
    if key not in secrets:
        error(f"Secret '{key}' not found")
        ctx.exit(1)
        return
    
    decrypted = decrypt_value(secrets[key])
    output({"key": key, "value": decrypted}, ctx.obj['output_format'])


# Add profiles group to config
config.add_command(profiles)
