"""Shared BOT session state and distributed operation leases."""

from __future__ import annotations

from datetime import datetime, timedelta, timezone
from sqlalchemy import select

from config.control_plane import get_control_plane_session
from bridge_platform.tenants.models import TenantIntegration


def update_state(tenant_id: str, bot_id: str, *, state: str, worker_id: str) -> dict:
    with get_control_plane_session() as session:
        row = _row(session, tenant_id, bot_id, lock=True)
        config = dict(row.config_json or {})
        config.update({"state": state, "worker_id": worker_id, "updated_at": _now().isoformat()})
        row.status, row.config_json = state, config
        session.commit()
        return _public(config)


def acquire_lease(tenant_id: str, bot_id: str, *, owner: str, operation: str, ttl_seconds: int = 120) -> dict:
    now = _now()
    with get_control_plane_session() as session:
        row = _row(session, tenant_id, bot_id, lock=True)
        config = dict(row.config_json or {})
        expires = _parse(config.get("lease_expires_at"))
        if expires and expires > now and config.get("lease_owner") != owner:
            raise RuntimeError("BOT is busy")
        config.update({"lease_owner": owner, "lease_operation": operation,
                       "lease_expires_at": (now + timedelta(seconds=max(10, min(ttl_seconds, 900)))).isoformat()})
        row.config_json = config
        session.commit()
        return _public(config)


def release_lease(tenant_id: str, bot_id: str, *, owner: str) -> None:
    with get_control_plane_session() as session:
        row = _row(session, tenant_id, bot_id, lock=True)
        config = dict(row.config_json or {})
        if config.get("lease_owner") == owner:
            for key in ("lease_owner", "lease_operation", "lease_expires_at"):
                config.pop(key, None)
            row.config_json = config
            session.commit()


def _row(session, tenant_id: str, bot_id: str, *, lock: bool) -> TenantIntegration:
    query = select(TenantIntegration).where(TenantIntegration.tenant_id == tenant_id,
        TenantIntegration.app_id == "aroflo_connector_app",
        TenantIntegration.integration_name == f"bot_session_{bot_id}")
    row = session.execute(query.with_for_update() if lock else query).scalar_one_or_none()
    if row is None:
        row = TenantIntegration(tenant_id=tenant_id, app_id="aroflo_connector_app",
            integration_name=f"bot_session_{bot_id}", status="offline", config_json={"state": "offline"})
        session.add(row)
        session.flush()
    return row


def _now(): return datetime.now(timezone.utc)
def _parse(value):
    try: return datetime.fromisoformat(value) if value else None
    except (TypeError, ValueError): return None
def _public(config):
    expires = _parse(config.get("lease_expires_at"))
    return {"state": config.get("state", "offline"), "worker_id": config.get("worker_id", ""),
            "busy": bool(expires and expires > _now()), "lease_operation": config.get("lease_operation", ""),
            "updated_at": config.get("updated_at", "")}
