"""
Settings and API key management endpoints.
"""

from flask import request, current_app
from .auth import require_api_key, generate_api_key, _hash_key
from .helpers import api_success, api_error

# Keys that must NEVER be exposed via the API
_SENSITIVE_KEYS = {
    "spotify.client_id",
    "spotify.client_secret",
    "tidal.client_id",
    "tidal.client_secret",
    "tidal_tokens",
    "tidal_download.session",
    "qobuz.session",
    "plex.token",
    "jellyfin.api_key",
    "navidrome.password",
    "soulseek.api_key",
    "listenbrainz.token",
    "acoustid.api_key",
    "lastfm.api_key",
    "genius.access_token",
    "hydrabase.api_key",
}


def register_routes(bp):

    # ---- Settings ----

    @bp.route("/settings", methods=["GET"])
    @require_api_key
    def get_settings():
        """Get current settings (sensitive values redacted)."""
        try:
            cfg = current_app.soulsync["config_manager"]
            raw = dict(cfg.config_data) if hasattr(cfg, "config_data") else {}

            sanitized = _redact_sensitive(raw)
            return api_success({"settings": sanitized})
        except Exception as e:
            return api_error("SETTINGS_ERROR", str(e), 500)

    @bp.route("/settings", methods=["PATCH"])
    @require_api_key
    def update_settings():
        """Update settings (partial).

        Body: {"key": "value", ...}  — dot-notation keys accepted.
        """
        body = request.get_json(silent=True) or {}
        if not body:
            return api_error("BAD_REQUEST", "Empty body.", 400)

        try:
            cfg = current_app.soulsync["config_manager"]
            updated = []
            for key, value in body.items():
                # Block writing API keys through settings endpoint
                if key == "api_keys":
                    continue
                cfg.set(key, value)
                updated.append(key)

            return api_success({"message": "Settings updated.", "updated_keys": updated})
        except Exception as e:
            return api_error("SETTINGS_ERROR", str(e), 500)

    # ---- API Key Management ----

    @bp.route("/api-keys", methods=["GET"])
    @require_api_key
    def list_api_keys():
        """List all API keys (prefix + label only, never the full key)."""
        try:
            cfg = current_app.soulsync["config_manager"]
            keys = cfg.get("api_keys", [])
            return api_success({
                "keys": [
                    {
                        "id": k.get("id"),
                        "label": k.get("label", ""),
                        "key_prefix": k.get("key_prefix", ""),
                        "created_at": k.get("created_at"),
                        "last_used_at": k.get("last_used_at"),
                    }
                    for k in keys
                ]
            })
        except Exception as e:
            return api_error("SETTINGS_ERROR", str(e), 500)

    @bp.route("/api-keys", methods=["POST"])
    @require_api_key
    def create_api_key():
        """Generate a new API key.

        Body: {"label": "My Bot"}
        The raw key is returned ONCE in the response.
        """
        body = request.get_json(silent=True) or {}
        label = body.get("label", "")

        try:
            cfg = current_app.soulsync["config_manager"]
            raw_key, record = generate_api_key(label)
            keys = cfg.get("api_keys", [])
            keys.append(record)
            cfg.set("api_keys", keys)

            return api_success({
                "key": raw_key,
                "id": record["id"],
                "label": record["label"],
                "key_prefix": record["key_prefix"],
                "created_at": record["created_at"],
            }, status=201)
        except Exception as e:
            return api_error("SETTINGS_ERROR", str(e), 500)

    @bp.route("/api-keys/<key_id>", methods=["DELETE"])
    @require_api_key
    def revoke_api_key(key_id):
        """Revoke (delete) an API key by its ID."""
        try:
            cfg = current_app.soulsync["config_manager"]
            keys = cfg.get("api_keys", [])
            original_len = len(keys)
            keys = [k for k in keys if k.get("id") != key_id]

            if len(keys) == original_len:
                return api_error("NOT_FOUND", "API key not found.", 404)

            cfg.set("api_keys", keys)
            return api_success({"message": "API key revoked."})
        except Exception as e:
            return api_error("SETTINGS_ERROR", str(e), 500)

    # ---- Bootstrap endpoint (no auth required) ----

    @bp.route("/api-keys/bootstrap", methods=["POST"])
    def bootstrap_api_key():
        """Generate the first API key when none exist (no auth required).

        This endpoint only works when zero API keys are configured.
        Body: {"label": "My First Key"}
        """
        try:
            cfg = current_app.soulsync["config_manager"]
            existing = cfg.get("api_keys", [])
            if existing:
                return api_error("FORBIDDEN",
                                 "API keys already exist. Use an authenticated request to create more.", 403)

            body = request.get_json(silent=True) or {}
            label = body.get("label", "Default")

            raw_key, record = generate_api_key(label)
            cfg.set("api_keys", [record])

            return api_success({
                "key": raw_key,
                "id": record["id"],
                "label": record["label"],
                "key_prefix": record["key_prefix"],
                "created_at": record["created_at"],
            }, status=201)
        except Exception as e:
            return api_error("SETTINGS_ERROR", str(e), 500)


def _redact_sensitive(config, prefix=""):
    """Recursively redact sensitive values from a config dict."""
    if not isinstance(config, dict):
        return config

    result = {}
    for key, value in config.items():
        full_key = f"{prefix}.{key}" if prefix else key
        if any(full_key.startswith(s) for s in _SENSITIVE_KEYS):
            result[key] = "***REDACTED***"
        elif isinstance(value, dict):
            result[key] = _redact_sensitive(value, full_key)
        else:
            result[key] = value
    return result
