"""
Storage logic for Envy.
Handles reading/writing the secrets database and .env file generation.
"""

import json
import os
import subprocess
import sys
from typing import Any, Optional
from datetime import datetime
from rich.console import Console

console = Console()

# Default paths
ENVY_DIR = ".envy"
DB_FILE = ".envy/secrets.json"


def ensure_envy_dir():
    """Ensure the .envy directory exists and is hidden on Windows."""
    created = not os.path.exists(ENVY_DIR)
    os.makedirs(ENVY_DIR, exist_ok=True)
    
    # Hide the folder on Windows (similar to .git)
    if created and sys.platform == "win32":
        try:
            subprocess.run(
                ["attrib", "+h", ENVY_DIR],
                check=True,
                capture_output=True
            )
        except subprocess.SubprocessError:
            pass  # Silently fail if we can't hide the folder


def load_db() -> dict:
    """Load the secrets database."""
    if not os.path.exists(DB_FILE):
        return {
            "active_profile": "dev",
            "profiles": {"dev": {}, "prod": {}, "staging": {}},
            "metadata": {}
        }
    
    with open(DB_FILE, "r") as f:
        return json.load(f)


def save_db(data: dict):
    """Save the secrets database."""
    ensure_envy_dir()
    with open(DB_FILE, "w") as f:
        json.dump(data, f, indent=4)


# ==================== REMOTE ORIGIN ====================

def get_remote() -> Optional[dict]:
    """Get the remote origin configuration."""
    db = load_db()
    return db.get("remote")


def set_remote(project_slug: str, api_url: str = None):
    """Set the remote origin for this project."""
    db = load_db()
    db["remote"] = {
        "origin": project_slug,
        "api_url": api_url,
        "added_at": datetime.now().isoformat()
    }
    save_db(db)


def remove_remote():
    """Remove the remote origin."""
    db = load_db()
    if "remote" in db:
        del db["remote"]
        save_db(db)


def get_profile_secrets(profile: str) -> dict:
    """Get all secrets for a specific profile."""
    db = load_db()
    return db.get("profiles", {}).get(profile, {})


def set_secret(profile: str, key: str, encrypted_value: str, metadata: Optional[dict] = None):
    """Set an encrypted secret in a profile."""
    db = load_db()
    
    if profile not in db["profiles"]:
        db["profiles"][profile] = {}
    
    db["profiles"][profile][key] = encrypted_value
    
    # Store metadata separately
    if metadata:
        if "metadata" not in db:
            db["metadata"] = {}
        if profile not in db["metadata"]:
            db["metadata"][profile] = {}
        db["metadata"][profile][key] = metadata
    
    save_db(db)


def delete_secret(profile: str, key: str) -> bool:
    """Delete a secret from a profile."""
    db = load_db()
    
    if profile not in db["profiles"]:
        return False
    
    if key not in db["profiles"][profile]:
        return False
    
    del db["profiles"][profile][key]
    
    # Also remove metadata
    if "metadata" in db and profile in db["metadata"] and key in db["metadata"][profile]:
        del db["metadata"][profile][key]
    
    save_db(db)
    return True


def get_secret_metadata(profile: str, key: str) -> Optional[dict]:
    """Get metadata for a specific secret."""
    db = load_db()
    return db.get("metadata", {}).get(profile, {}).get(key)


def create_profile(name: str) -> bool:
    """Create a new profile."""
    db = load_db()
    
    if name in db["profiles"]:
        return False
    
    db["profiles"][name] = {}
    save_db(db)
    return True


def delete_profile(name: str) -> bool:
    """Delete a profile."""
    db = load_db()
    
    if name not in db["profiles"]:
        return False
    
    del db["profiles"][name]
    
    # Remove metadata for this profile
    if "metadata" in db and name in db["metadata"]:
        del db["metadata"][name]
    
    save_db(db)
    return True


def list_profiles() -> list[str]:
    """List all profiles."""
    db = load_db()
    return list(db.get("profiles", {}).keys())


def set_active_profile(name: str) -> bool:
    """Set the active profile."""
    db = load_db()
    
    if name not in db["profiles"]:
        return False
    
    db["active_profile"] = name
    save_db(db)
    return True


def get_active_profile() -> str:
    """Get the currently active profile."""
    db = load_db()
    return db.get("active_profile", "dev")


def generate_env_file(
    decrypted_secrets: dict[str, str],
    output_path: str = ".env",
    profile: str = "dev"
) -> str:
    """Generate a .env file from decrypted secrets."""
    lines = [
        f"# Generated by Envy - Profile: {profile}",
        f"# Generated at: {datetime.now().isoformat()}",
        f"# WARNING: This file contains sensitive data. Do not commit to version control!",
        ""
    ]
    
    for key, value in sorted(decrypted_secrets.items()):
        # Handle values that need quoting
        if any(c in value for c in [' ', '"', "'", '\n', '\t', '#', '=']):
            # Escape double quotes and use double quote wrapping
            escaped_value = value.replace('\\', '\\\\').replace('"', '\\"')
            lines.append(f'{key}="{escaped_value}"')
        else:
            lines.append(f"{key}={value}")
    
    content = "\n".join(lines) + "\n"
    
    with open(output_path, "w") as f:
        f.write(content)
    
    return output_path


def parse_env_file(file_path: str = ".env") -> dict[str, str]:
    """Parse an existing .env file."""
    env_vars = {}
    
    if not os.path.exists(file_path):
        return env_vars
    
    with open(file_path, "r") as f:
        for line in f:
            line = line.strip()
            
            # Skip comments and empty lines
            if not line or line.startswith("#"):
                continue
            
            # Parse KEY=VALUE
            if "=" in line:
                key, _, value = line.partition("=")
                key = key.strip()
                value = value.strip()
                
                # Remove surrounding quotes if present
                if (value.startswith('"') and value.endswith('"')) or \
                   (value.startswith("'") and value.endswith("'")):
                    value = value[1:-1]
                
                env_vars[key] = value
    
    return env_vars


def import_from_env_file(file_path: str = ".env") -> dict[str, str]:
    """Import variables from a .env file."""
    return parse_env_file(file_path)


def export_env_from_process() -> dict[str, str]:
    """Export current process environment variables."""
    return dict(os.environ)


def get_all_keys(profiles: Optional[list[str]] = None) -> dict[str, set[str]]:
    """Get all keys across specified profiles."""
    db = load_db()
    
    if profiles is None:
        profiles = list(db.get("profiles", {}).keys())
    
    result = {}
    for profile in profiles:
        result[profile] = set(db.get("profiles", {}).get(profile, {}).keys())
    
    return result


def find_drift(source_profile: str, target_profile: str) -> dict:
    """Find drift between two profiles."""
    db = load_db()
    
    source_keys = set(db.get("profiles", {}).get(source_profile, {}).keys())
    target_keys = set(db.get("profiles", {}).get(target_profile, {}).keys())
    
    return {
        "missing_in_target": source_keys - target_keys,
        "missing_in_source": target_keys - source_keys,
        "common": source_keys & target_keys
    }
