"""
Global auth storage I/O for Lattice.

Shell layer - performs I/O and returns Result[T, E].

Reference: RFC-XXX Global Auth Storage
"""

from __future__ import annotations

import json
import os
from pathlib import Path

from returns.result import Failure, Result, Success

from lattice.core.auth import validate_provider_name

# Path to the global auth.json file (~/.config/lattice/auth.json)
AUTH_FILE: Path = Path.home() / ".config" / "lattice" / "auth.json"


# @invar:allow shell_result: Path accessor for I/O-dependent config location
# @invar:allow shell_pure_logic: Path accessor co-located with I/O operations that use it
def get_auth_file_path() -> Path:
    """Return path to auth.json file.

    Returns a Path object pointing to ~/.config/lattice/auth.json.

    >>> p = get_auth_file_path()
    >>> p.name
    'auth.json'
    >>> '.config' in str(p)
    True
    >>> 'lattice' in str(p)
    True
    """
    return AUTH_FILE


__all__ = [
    "AUTH_FILE",
    "get_auth_file_path",
    "save_auth",
    "load_auth",
    "get_auth",
    "delete_auth",
]


# @shell_complexity: File I/O with existence check, parse, and permission handling
def save_auth(provider: str, api_key: str) -> Result[None, str]:
    """Save API key for provider.

    - Validates provider name
    - Creates ~/.config/lattice/ if not exists
    - Sets file permissions to 0o600
    - Updates or adds provider entry

    >>> result = save_auth('test_provider', 'sk-test')
    >>> isinstance(result, Success) or isinstance(result, Failure)
    True
    """
    # Validate provider name
    validation = validate_provider_name(provider)
    if validation is not True:
        assert isinstance(validation, str)  # for type narrowing
        return Failure(validation)

    try:
        # Ensure directory exists
        AUTH_FILE.parent.mkdir(parents=True, exist_ok=True)

        # Load existing auth or start fresh
        auth_data: dict[str, dict] = {}
        if AUTH_FILE.exists():
            try:
                content = AUTH_FILE.read_text()
                if content.strip():
                    auth_data = json.loads(content)
            except json.JSONDecodeError:
                # Corrupted file, start fresh
                auth_data = {}

        # Update provider entry
        auth_data[provider] = {"api_key": api_key}

        # Write with secure permissions
        AUTH_FILE.write_text(json.dumps(auth_data, indent=2))
        os.chmod(AUTH_FILE, 0o600)

        return Success(None)
    except (OSError, IOError) as e:
        return Failure(f"Failed to save auth: {e}")


# @shell_complexity: File I/O with existence check and parse error handling
def load_auth() -> Result[dict[str, dict], str]:
    """Load all stored auth entries.

    Returns empty dict if file doesn't exist.

    >>> result = load_auth()
    >>> isinstance(result, Success) or isinstance(result, Failure)
    True
    """
    try:
        if not AUTH_FILE.exists():
            return Success({})

        content = AUTH_FILE.read_text()
        if not content.strip():
            return Success({})

        auth_data = json.loads(content)
        return Success(auth_data)
    except json.JSONDecodeError as e:
        return Failure(f"Failed to parse auth file: {e}")
    except (OSError, IOError) as e:
        return Failure(f"Failed to read auth file: {e}")


def get_auth(provider: str) -> Result[str | None, str]:
    """Get API key for specific provider.

    Validates provider name before looking up.

    Returns None if provider not found.

    >>> result = get_auth('unknown_provider_xyz')
    >>> isinstance(result, Success) or isinstance(result, Failure)
    True
    """
    # Validate provider name
    validation = validate_provider_name(provider)
    if validation is not True:
        assert isinstance(validation, str)  # for type narrowing
        return Failure(validation)

    load_result = load_auth()
    if isinstance(load_result, Failure):
        return load_result

    auth_data = load_result.unwrap()
    provider_data = auth_data.get(provider)
    if provider_data is None:
        return Success(None)

    api_key = provider_data.get("api_key")
    return Success(api_key)


# @shell_complexity: File I/O with existence check, update, and cleanup
def delete_auth(provider: str) -> Result[bool, str]:
    """Delete API key for provider.

    Validates provider name before deletion.

    Returns True if deleted, False if not found.

    >>> result = delete_auth('unknown_provider_xyz')
    >>> isinstance(result, Success) or isinstance(result, Failure)
    True
    """
    # Validate provider name
    validation = validate_provider_name(provider)
    if validation is not True:
        assert isinstance(validation, str)  # for type narrowing
        return Failure(validation)

    load_result = load_auth()
    if isinstance(load_result, Failure):
        return load_result

    auth_data = load_result.unwrap()

    if provider not in auth_data:
        return Success(False)

    del auth_data[provider]

    try:
        if auth_data:
            AUTH_FILE.write_text(json.dumps(auth_data, indent=2))
        else:
            # Remove file if empty
            AUTH_FILE.unlink()
        return Success(True)
    except (OSError, IOError) as e:
        return Failure(f"Failed to delete auth: {e}")
