"""Connection management — connect, test, and persist Odoo connection settings."""

from cli_anything.odoo_12.utils.odoo_backend import (
    OdooBackend,
    OdooRPC,
    get_connection_params,
    load_config,
    save_config,
)

_SENSITIVE_KEYS = ("client_secret", "access_token", "refresh_token")


def get_rpc(url: str | None = None, db: str | None = None,
            user: str | None = None, password: str | None = None,
            backend: str | None = None) -> OdooBackend:
    """Get an authenticated OdooBackend instance (REST or XML-RPC)."""
    params = get_connection_params(url, db, user, password)
    cfg = load_config()
    backend = backend or cfg.get("backend", "rest")

    if backend == "rest":
        from cli_anything.odoo_12.utils.odoo_rest import OdooREST
        rpc = OdooREST(
            **params,
            client_id=cfg.get("client_id"),
            client_secret=cfg.get("client_secret"),
            access_token=cfg.get("access_token"),
            refresh_token=cfg.get("refresh_token"),
            token_expiry=cfg.get("token_expiry"),
            grant_type=cfg.get("grant_type", "client_credentials"),
        )
    else:
        rpc = OdooRPC(**params)

    rpc.authenticate()

    # Persist tokens after REST authentication
    if backend == "rest" and hasattr(rpc, "access_token") and rpc.access_token:
        cfg.update({
            "access_token": rpc.access_token,
            "refresh_token": rpc.refresh_token,
            "token_expiry": rpc.token_expiry,
        })
        save_config(cfg)

    return rpc


def connect(url: str | None = None, db: str | None = None,
            user: str | None = None, password: str | None = None,
            save: bool = False, backend: str | None = None,
            client_id: str | None = None,
            client_secret: str | None = None,
            grant_type: str | None = None) -> dict:
    """Connect to an Odoo instance and verify credentials.

    Returns connection info dict on success, raises RuntimeError on failure.
    """
    params = get_connection_params(url, db, user, password)
    cfg = load_config()
    backend = backend or cfg.get("backend", "rest")

    if backend == "rest":
        from cli_anything.odoo_12.utils.odoo_rest import OdooREST
        cid = client_id or cfg.get("client_id")
        csecret = client_secret or cfg.get("client_secret")
        gt = grant_type or cfg.get("grant_type", "client_credentials")
        rpc = OdooREST(
            **params,
            client_id=cid,
            client_secret=csecret,
            access_token=cfg.get("access_token"),
            refresh_token=cfg.get("refresh_token"),
            token_expiry=cfg.get("token_expiry"),
            grant_type=gt,
        )
    else:
        rpc = OdooRPC(**params)

    result = rpc.check_connection()

    if save:
        save_data = {
            "url": params["url"],
            "db": params["db"],
            "user": params["user"],
            "password": params["password"],
            "backend": backend,
        }
        if backend == "rest":
            save_data["grant_type"] = gt
            if client_id:
                save_data["client_id"] = client_id
            elif cfg.get("client_id"):
                save_data["client_id"] = cfg["client_id"]
            if client_secret:
                save_data["client_secret"] = client_secret
            elif cfg.get("client_secret"):
                save_data["client_secret"] = cfg["client_secret"]
            if hasattr(rpc, "access_token") and rpc.access_token:
                save_data["access_token"] = rpc.access_token
                save_data["refresh_token"] = rpc.refresh_token
                save_data["token_expiry"] = rpc.token_expiry
        save_config(save_data)
        result["saved"] = True

    return result


def show_config() -> dict:
    """Show current saved configuration with sensitive values masked."""
    cfg = load_config()
    if not cfg:
        return {"status": "not configured", "hint": "Use 'connect' to set up"}
    masked = dict(cfg)
    if "password" in masked and masked["password"]:
        masked["password"] = masked["password"][:3] + "***"
    for key in _SENSITIVE_KEYS:
        if key in masked and masked[key]:
            masked[key] = str(masked[key])[:8] + "***"
    return masked


def delete_config(key: str | None = None) -> dict:
    """Delete a config key or all config."""
    cfg = load_config()
    if key:
        if key in cfg:
            del cfg[key]
            save_config(cfg)
            return {"deleted": key}
        return {"error": f"{key} not found"}
    save_config({})
    return {"deleted": "all"}


def setup_rest(client_id: str, client_secret: str,
               url: str | None = None, db: str | None = None,
               user: str | None = None, password: str | None = None,
               grant_type: str = "client_credentials") -> dict:
    """Set up REST API backend with OAuth2 credentials.

    Validates the client_id/secret against Odoo and saves to config.
    """
    from cli_anything.odoo_12.utils.odoo_rest import OdooREST

    params = get_connection_params(url, db, user, password)
    rpc = OdooREST(**params, client_id=client_id, client_secret=client_secret,
                   grant_type=grant_type)
    rpc.authenticate()

    cfg = load_config()
    cfg.update({
        "url": params["url"],
        "db": params["db"],
        "user": params["user"],
        "password": params["password"],
        "backend": "rest",
        "grant_type": grant_type,
        "client_id": client_id,
        "client_secret": client_secret,
        "access_token": rpc.access_token,
        "refresh_token": rpc.refresh_token,
        "token_expiry": rpc.token_expiry,
    })
    save_config(cfg)

    return {
        "status": "configured",
        "backend": "rest",
        "url": params["url"],
        "db": params["db"],
        "user": params["user"],
        "uid": rpc.uid,
    }
