"""Tenant-scoped AroFlo BOT profile storage."""

from __future__ import annotations

import re
from datetime import datetime, timezone

from sqlalchemy import select

from config.control_plane import get_control_plane_session
from bridge_platform.secrets.secrets_manager import SecretsManager
from bridge_platform.tenants.models import TenantApp, TenantIntegration


BOT_ID = re.compile(r"^[a-z][a-z0-9_]{1,31}$")
MAX_BOTS = 10


def list_bots(tenant_id: str) -> list[dict]:
    with get_control_plane_session() as session:
        binding = _binding(session, tenant_id)
        profiles = ((binding.config_json or {}).get("bot_pool") or {}).get("profiles") or {}
        states = {
            row.integration_name.removeprefix("bot_session_"): dict(row.config_json or {})
            for row in session.execute(select(TenantIntegration).where(
                TenantIntegration.tenant_id == tenant_id,
                TenantIntegration.app_id == "aroflo_connector_app",
                TenantIntegration.integration_name.like("bot_session_%"),
            )).scalars()
        }
        return [
            _public_profile(profile, states.get(bot_id) or {})
            for bot_id, profile in sorted(profiles.items())
        ]


def bot_pool_summary(tenant_id: str) -> dict:
    with get_control_plane_session() as session:
        binding = _binding(session, tenant_id)
        pool = dict((binding.config_json or {}).get("bot_pool") or {})
        licensed_limit = max(1, min(int(pool.get("licensed_bot_limit") or 1), MAX_BOTS))
    bots = list_bots(tenant_id)
    return {
        "bots": bots,
        "configured": len(bots),
        "connected": sum(1 for bot in bots if bot["state"] in {"connected", "online"}),
        "licensed_limit": licensed_limit,
        "can_add": len(bots) < licensed_limit,
    }


def configure_bot(
    tenant_id: str, *, bot_id: str, label: str, username: str,
    password: str, base_url: str, zones: list[str], enabled: bool,
    remember_30_days: bool, actor_id: str,
) -> dict:
    bot_id = str(bot_id or "").strip().lower()
    if not BOT_ID.fullmatch(bot_id):
        raise ValueError("bot_id must use lowercase letters, numbers, and underscores")
    clean_zones = sorted({str(zone).strip().lower() for zone in zones if str(zone).strip()})
    if not clean_zones:
        raise ValueError("At least one zone must be assigned")
    now = datetime.now(timezone.utc).isoformat()
    with get_control_plane_session() as session:
        binding = _binding(session, tenant_id)
        config = dict(binding.config_json or {})
        pool = dict(config.get("bot_pool") or {})
        profiles = dict(pool.get("profiles") or {})
        licensed_limit = max(1, min(int(pool.get("licensed_bot_limit") or 1), MAX_BOTS))
        if bot_id not in profiles and len(profiles) >= licensed_limit:
            raise ValueError("The BOT profile limit has been reached")
        previous = dict(profiles.get(bot_id) or {})
        profiles[bot_id] = {
            "bot_id": bot_id,
            "label": str(label or bot_id).strip()[:80],
            "zones": clean_zones,
            "enabled": bool(enabled),
            "remember_30_days": bool(remember_30_days),
            "state": "not_connected" if username and password else previous.get("state", "not_configured"),
            "created_at": previous.get("created_at", now),
            "updated_at": now,
        }
        pool["profiles"] = profiles
        config["bot_pool"] = pool
        binding.config_json = config
        session.commit()
    manager = SecretsManager()
    if username:
        manager.put_secret(tenant_id=tenant_id, app_id="aroflo_connector_app",
                           secret_name=f"bot_{bot_id}_username", secret_value=username,
                           actor_id=actor_id)
    if password:
        manager.put_secret(tenant_id=tenant_id, app_id="aroflo_connector_app",
                           secret_name=f"bot_{bot_id}_password", secret_value=password,
                           actor_id=actor_id)
    if base_url:
        manager.put_secret(tenant_id=tenant_id, app_id="aroflo_connector_app",
                           secret_name=f"bot_{bot_id}_base_url", secret_value=base_url,
                           actor_id=actor_id)
    return next(profile for profile in list_bots(tenant_id) if profile["bot_id"] == bot_id)


def _binding(session, tenant_id: str) -> TenantApp:
    binding = session.execute(select(TenantApp).where(
        TenantApp.tenant_id == tenant_id,
        TenantApp.app_id == "aroflo_connector_app",
    )).scalar_one_or_none()
    if binding is None or not binding.is_enabled:
        raise LookupError("AroFlo Connector is not enabled for this tenant")
    return binding


def _public_profile(profile: dict, session_state: dict | None = None) -> dict:
    session_state = session_state or {}
    lease_expires = session_state.get("lease_expires_at")
    busy = False
    if lease_expires:
        try:
            busy = datetime.fromisoformat(lease_expires) > datetime.now(timezone.utc)
        except (TypeError, ValueError):
            pass
    return {
        "bot_id": profile.get("bot_id", ""),
        "label": profile.get("label", ""),
        "zones": list(profile.get("zones") or []),
        "enabled": bool(profile.get("enabled")),
        "remember_30_days": bool(profile.get("remember_30_days")),
        "state": session_state.get("state") or profile.get("state", "not_configured"),
        "busy": busy,
        "worker_id": session_state.get("worker_id", ""),
        "lease_operation": session_state.get("lease_operation", "") if busy else "",
        "updated_at": profile.get("updated_at", ""),
    }
