"""Lizenz-Verwaltung und -Pruefung."""
import logging
from datetime import datetime
from config import TIMEZONE
import aiosqlite

logger = logging.getLogger("osint.license")


async def check_license(db: aiosqlite.Connection, organization_id: int) -> dict:
    """Prueft den Lizenzstatus einer Organisation.

    Returns:
        dict mit: valid, status, license_type, max_users, current_users, read_only, message
    """
    # Organisation pruefen
    cursor = await db.execute(
        "SELECT id, name, is_active FROM organizations WHERE id = ?",
        (organization_id,),
    )
    org = await cursor.fetchone()
    if not org:
        return {"valid": False, "status": "not_found", "read_only": True, "message": "Organisation nicht gefunden"}

    if not org["is_active"]:
        return {"valid": False, "status": "org_disabled", "read_only": True, "message": "Organisation deaktiviert"}

    # Aktive Lizenz suchen
    cursor = await db.execute(
        """SELECT * FROM licenses
           WHERE organization_id = ? AND status = 'active'
           ORDER BY created_at DESC LIMIT 1""",
        (organization_id,),
    )
    license_row = await cursor.fetchone()

    if not license_row:
        return {"valid": False, "status": "no_license", "read_only": True, "message": "Keine aktive Lizenz"}

    # Ablauf pruefen
    now = datetime.now(TIMEZONE)
    valid_until = license_row["valid_until"]

    if valid_until is not None:
        try:
            expiry = datetime.fromisoformat(valid_until)
            if expiry.tzinfo is None:
                expiry = expiry.replace(tzinfo=TIMEZONE)
            if now > expiry:
                return {
                    "valid": False,
                    "status": "expired",
                    "license_type": license_row["license_type"],
                    "read_only": True,
                    "message": "Lizenz abgelaufen",
                }
        except (ValueError, TypeError):
            pass

    # Nutzerzahl pruefen
    cursor = await db.execute(
        "SELECT COUNT(*) as cnt FROM users WHERE organization_id = ? AND is_active = 1",
        (organization_id,),
    )
    current_users = (await cursor.fetchone())["cnt"]

    return {
        "valid": True,
        "status": license_row["status"],
        "license_type": license_row["license_type"],
        "max_users": license_row["max_users"],
        "current_users": current_users,
        "read_only": False,
        "message": "Lizenz aktiv",
    }


async def can_add_user(db: aiosqlite.Connection, organization_id: int) -> tuple[bool, str]:
    """Prueft ob ein neuer Nutzer hinzugefuegt werden kann (Nutzer-Limit).

    Returns:
        (erlaubt, grund)
    """
    lic = await check_license(db, organization_id)
    if not lic["valid"]:
        return False, lic["message"]

    if lic["current_users"] >= lic["max_users"]:
        return False, f"Nutzer-Limit erreicht ({lic['current_users']}/{lic['max_users']})"

    return True, ""


async def charge_usage_to_tenant(
    db: aiosqlite.Connection,
    tenant_id: int | None,
    usage,
    source: str,
) -> None:
    """Verbucht Token-Verbrauch auf einen Tenant.

    Aktualisiert `token_usage_monthly` (UPSERT pro organization_id+year_month+source)
    und zieht Credits von der aktiven Lizenz ab (wenn cost_per_credit gesetzt).

    Args:
        db: offene aiosqlite.Connection
        tenant_id: Organisations-ID oder None (dann nur geloggt, keine DB-Buchung)
        usage: ClaudeUsage oder UsageAccumulator mit input_tokens/output_tokens/
               cache_creation_tokens/cache_read_tokens/total_cost_usd/call_count
        source: 'monitor' | 'enhance' | 'chat'

    Der Helper ruft KEIN db.commit() auf — die Transaktionsgrenzen bestimmt der Caller.
    Ohne Verbrauch (total_cost_usd == 0) oder ohne tenant_id wird nichts gebucht.
    """
    total_cost = getattr(usage, "total_cost_usd", None)
    if total_cost is None:
        total_cost = getattr(usage, "cost_usd", 0.0)

    if not tenant_id:
        logger.info(
            f"charge_usage_to_tenant[{source}]: kein tenant_id, uebersprungen "
            f"(cost=${total_cost:.4f})"
        )
        return

    if total_cost <= 0:
        return

    input_tokens = getattr(usage, "input_tokens", 0)
    output_tokens = getattr(usage, "output_tokens", 0)
    cache_creation = getattr(usage, "cache_creation_tokens", 0)
    cache_read = getattr(usage, "cache_read_tokens", 0)
    api_calls = getattr(usage, "call_count", 1)
    refresh_increment = 1 if source == "monitor" else 0

    year_month = datetime.now(TIMEZONE).strftime("%Y-%m")

    await db.execute(
        """
        INSERT INTO token_usage_monthly
            (organization_id, year_month, source, input_tokens, output_tokens,
             cache_creation_tokens, cache_read_tokens, total_cost_usd, api_calls, refresh_count)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ON CONFLICT(organization_id, year_month, source) DO UPDATE SET
            input_tokens = input_tokens + excluded.input_tokens,
            output_tokens = output_tokens + excluded.output_tokens,
            cache_creation_tokens = cache_creation_tokens + excluded.cache_creation_tokens,
            cache_read_tokens = cache_read_tokens + excluded.cache_read_tokens,
            total_cost_usd = total_cost_usd + excluded.total_cost_usd,
            api_calls = api_calls + excluded.api_calls,
            refresh_count = refresh_count + excluded.refresh_count,
            updated_at = CURRENT_TIMESTAMP
        """,
        (
            tenant_id, year_month, source,
            input_tokens, output_tokens, cache_creation, cache_read,
            round(total_cost, 7), api_calls, refresh_increment,
        ),
    )

    lic_cursor = await db.execute(
        "SELECT cost_per_credit FROM licenses WHERE organization_id = ? AND status = 'active' ORDER BY id DESC LIMIT 1",
        (tenant_id,),
    )
    lic = await lic_cursor.fetchone()
    credits_consumed = 0.0
    if lic and lic["cost_per_credit"] and lic["cost_per_credit"] > 0:
        credits_consumed = total_cost / lic["cost_per_credit"]
        await db.execute(
            "UPDATE licenses SET credits_used = COALESCE(credits_used, 0) + ? WHERE organization_id = ? AND status = 'active'",
            (round(credits_consumed, 2), tenant_id),
        )

    logger.info(
        f"charge_usage_to_tenant[{source}] Tenant {tenant_id}: "
        f"${total_cost:.4f} -> {round(credits_consumed, 2)} Credits"
    )


async def expire_licenses(db: aiosqlite.Connection):
    """Setzt abgelaufene Lizenzen auf 'expired'. Taeglich aufrufen."""
    cursor = await db.execute(
        """SELECT id, organization_id FROM licenses
           WHERE status = 'active'
           AND valid_until IS NOT NULL
           AND valid_until < datetime('now')"""
    )
    expired = await cursor.fetchall()

    count = 0
    for lic in expired:
        await db.execute(
            "UPDATE licenses SET status = 'expired' WHERE id = ?",
            (lic["id"],),
        )
        count += 1
        logger.info(f"Lizenz {lic['id']} fuer Org {lic['organization_id']} als abgelaufen markiert")

    if count > 0:
        await db.commit()
        logger.info(f"{count} Lizenz(en) als abgelaufen markiert")

    return count
