"""API contract definitions for the AiVibe universal platform.

Documents the expected REST API endpoints, request/response shapes for
both the platform API (api.aivibe.cloud) and app API (api.aicippy.com).
These contracts serve as typed documentation - the actual server implementation
lives in the platform backend, not in this CLI package.

Tenant DB Schema (managed server-side):
    Tables in {tenant_id}_db.aivibe.cloud are prefixed per-app:
      - aicippy_com_conversations
      - aicippy_com_tenant_memory
      - aicippy_com_agent_runs
      - aicippy_com_rules
      - aicippy_com_profile_config
      - aicippy_com_mcp_connectors
      - aicippy_com_session_logs
      - aicippy_com_invocation_logs
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Final

# =============================================================================
# Platform API (api.aivibe.cloud) — Universal tenant/plan/credit management
# =============================================================================

PLATFORM_API_VERSION: Final[str] = "v1"


@dataclass(frozen=True, slots=True)
class TenantByEmailRequest:
    """Path parameter for tenant lookup by email."""

    email: str


@dataclass(frozen=True, slots=True)
class TenantByEmailResponse:
    """Response from GET /api/v1/tenants/by-email/{email}."""

    tenant_id: str
    org_tenant_id: str
    email: str
    name: str
    created_at: str  # ISO 8601


@dataclass(frozen=True, slots=True)
class PlanResponse:
    """Response from GET /api/v1/tenants/{tenant_id}/plan."""

    plan: str  # "chakra", "vajra", "aarambh", "admin"
    status: str  # "active", "expired", "cancelled", "suspended", "no_plan"
    credits_remaining: int
    credits_total: int
    expiry: str | None  # ISO 8601 or null
    is_admin: bool


@dataclass(frozen=True, slots=True)
class CreditsResponse:
    """Response from GET /api/v1/tenants/{tenant_id}/credits."""

    credits_remaining: int


@dataclass(frozen=True, slots=True)
class CreditDeductRequest:
    """Request body for POST /api/v1/tenants/{tenant_id}/credits/deduct."""

    amount: int
    source: str  # "aicippy"
    description: str  # "aicippy_chat"


@dataclass(frozen=True, slots=True)
class CreditDeductResponse:
    """Response from POST /api/v1/tenants/{tenant_id}/credits/deduct."""

    success: bool
    credits_remaining: int
    transaction_id: str | None
    error: str | None


@dataclass(frozen=True, slots=True)
class HealthResponse:
    """Response from GET /api/v1/health."""

    status: str  # "healthy"
    version: str


@dataclass(frozen=True, slots=True)
class TenantRolesResponse:
    """Response from GET /api/v1/tenants/{tenant_id}/roles."""

    roles: list[dict[str, Any]]  # [{role, apps, granted_at, granted_by}]


@dataclass(frozen=True, slots=True)
class AssignRoleRequest:
    """Request body for POST /api/v1/tenants/{tenant_id}/roles."""

    role: str  # "admin", "user"
    apps: list[str]  # ["*"] for all apps, or ["aicippy.com", "aivibe.cloud"]


@dataclass(frozen=True, slots=True)
class AssignRoleResponse:
    """Response from POST /api/v1/tenants/{tenant_id}/roles."""

    success: bool
    role: str
    apps: list[str]
    granted_at: str  # ISO 8601


@dataclass(frozen=True, slots=True)
class OrgResponse:
    """Response from GET /api/v1/orgs/{org_tenant_id}."""

    org_tenant_id: str
    name: str
    created_at: str  # ISO 8601
    member_count: int


@dataclass(frozen=True, slots=True)
class OrgMembersResponse:
    """Response from GET /api/v1/orgs/{org_tenant_id}/members."""

    members: list[dict[str, Any]]  # [{tenant_id, email, name, created_at}]


@dataclass(frozen=True, slots=True)
class DeleteTenantResponse:
    """Response from DELETE /api/v1/tenants/{tenant_id}.

    This endpoint performs a soft-delete: the tenant status is set to
    ``inactive`` permanently. There is no mechanism to reactivate an
    inactive tenant via any feature, UI, or API.
    """

    success: bool
    tenant_id: str
    status: str  # Always "inactive" on success


# =============================================================================
# App API (api.aicippy.com) — AiCippy-specific operations
# =============================================================================

APP_API_VERSION: Final[str] = "v1"

# POST /api/v1/memory/conversations
# Body: {user_id, session_id, messages: [{role, content, timestamp}]}


@dataclass(frozen=True, slots=True)
class SaveConversationRequest:
    """Request body for POST /api/v1/memory/conversations."""

    user_id: str
    session_id: str
    messages: list[dict[str, Any]]


@dataclass(frozen=True, slots=True)
class SaveConversationResponse:
    """Response from POST /api/v1/memory/conversations."""

    conversation_id: str


# GET /api/v1/memory/conversations?user_id={user_id}&limit={limit}


@dataclass(frozen=True, slots=True)
class ListConversationsResponse:
    """Response from GET /api/v1/memory/conversations."""

    conversations: list[dict[str, Any]]


@dataclass(frozen=True, slots=True)
class SaveMemoryRequest:
    """Request body for PUT /api/v1/memory/tenant/{key}."""

    user_id: str
    value: Any


# GET /api/v1/memory/tenant/{key}?user_id={user_id}


@dataclass(frozen=True, slots=True)
class GetMemoryResponse:
    """Response from GET /api/v1/memory/tenant/{key}."""

    key: str
    value: Any
    updated_at: str  # ISO 8601


# GET /api/v1/memory/tenant?user_id={user_id}


@dataclass(frozen=True, slots=True)
class ListMemoriesResponse:
    """Response from GET /api/v1/memory/tenant."""

    entries: list[dict[str, Any]]


# GET /api/v1/profile


@dataclass(frozen=True, slots=True)
class ProfileResponse:
    """Response from GET /api/v1/profile."""

    user_id: str
    email: str
    name: str
    preferences: dict[str, Any]


@dataclass(frozen=True, slots=True)
class UpdateProfileRequest:
    """Request body for PATCH /api/v1/profile."""

    updates: dict[str, Any]


# GET /api/v1/rules


@dataclass(frozen=True, slots=True)
class ListRulesResponse:
    """Response from GET /api/v1/rules."""

    rules: list[dict[str, Any]]


@dataclass(frozen=True, slots=True)
class SaveRuleRequest:
    """Request body for POST /api/v1/rules."""

    rule: dict[str, Any]


@dataclass(frozen=True, slots=True)
class SaveRuleResponse:
    """Response from POST /api/v1/rules."""

    rule_id: str


# GET /api/v1/connectors


@dataclass(frozen=True, slots=True)
class ListConnectorsResponse:
    """Response from GET /api/v1/connectors."""

    connectors: list[dict[str, Any]]


@dataclass(frozen=True, slots=True)
class SaveConnectorRequest:
    """Request body for POST /api/v1/connectors."""

    connector: dict[str, Any]


@dataclass(frozen=True, slots=True)
class SaveConnectorResponse:
    """Response from POST /api/v1/connectors."""

    connector_id: str


@dataclass(frozen=True, slots=True)
class SessionLogRequest:
    """Request body for POST /api/v1/logs/sessions."""

    session_data: dict[str, Any]


@dataclass(frozen=True, slots=True)
class InvocationLogRequest:
    """Request body for POST /api/v1/logs/invocations."""

    invocation_data: dict[str, Any]


# =============================================================================
# API Endpoint Summary
# =============================================================================

PLATFORM_ENDPOINTS: Final[dict[str, dict[str, str]]] = {
    "get_tenant": {
        "method": "GET",
        "path": "/api/v1/tenants/by-email/{email}",
        "purpose": "Look up tenant by email",
    },
    "validate_plan": {
        "method": "GET",
        "path": "/api/v1/tenants/{tenant_id}/plan",
        "purpose": "Get plan details + validity",
    },
    "get_credits": {
        "method": "GET",
        "path": "/api/v1/tenants/{tenant_id}/credits",
        "purpose": "Get remaining credits",
    },
    "deduct_credits": {
        "method": "POST",
        "path": "/api/v1/tenants/{tenant_id}/credits/deduct",
        "purpose": "Deduct credits (atomic)",
    },
    "health": {
        "method": "GET",
        "path": "/api/v1/health",
        "purpose": "Health check",
    },
    "get_tenant_roles": {
        "method": "GET",
        "path": "/api/v1/tenants/{tenant_id}/roles",
        "purpose": "Get tenant role assignments (admin, user, etc.)",
    },
    "assign_role": {
        "method": "POST",
        "path": "/api/v1/tenants/{tenant_id}/roles",
        "purpose": "Assign role to tenant (admin with app scope)",
    },
    "get_org": {
        "method": "GET",
        "path": "/api/v1/orgs/{org_tenant_id}",
        "purpose": "Get organization details",
    },
    "get_org_members": {
        "method": "GET",
        "path": "/api/v1/orgs/{org_tenant_id}/members",
        "purpose": "List organization members",
    },
    "delete_tenant": {
        "method": "DELETE",
        "path": "/api/v1/tenants/{tenant_id}",
        "purpose": "Soft-delete tenant (sets status to inactive, irreversible)",
    },
}

APP_ENDPOINTS: Final[dict[str, dict[str, str]]] = {
    "save_conversation": {
        "method": "POST",
        "path": "/api/v1/memory/conversations",
        "purpose": "Save conversation",
    },
    "list_conversations": {
        "method": "GET",
        "path": "/api/v1/memory/conversations",
        "purpose": "List conversations",
    },
    "save_memory": {
        "method": "PUT",
        "path": "/api/v1/memory/tenant/{key}",
        "purpose": "Save tenant memory entry",
    },
    "get_memory": {
        "method": "GET",
        "path": "/api/v1/memory/tenant/{key}",
        "purpose": "Get tenant memory entry",
    },
    "list_memories": {
        "method": "GET",
        "path": "/api/v1/memory/tenant",
        "purpose": "List all tenant memories",
    },
    "get_profile": {
        "method": "GET",
        "path": "/api/v1/profile",
        "purpose": "Get user profile",
    },
    "update_profile": {
        "method": "PATCH",
        "path": "/api/v1/profile",
        "purpose": "Update user profile",
    },
    "get_rules": {
        "method": "GET",
        "path": "/api/v1/rules",
        "purpose": "Get agent rules",
    },
    "save_rule": {
        "method": "POST",
        "path": "/api/v1/rules",
        "purpose": "Save agent rule",
    },
    "list_connectors": {
        "method": "GET",
        "path": "/api/v1/connectors",
        "purpose": "List MCP connectors",
    },
    "save_connector": {
        "method": "POST",
        "path": "/api/v1/connectors",
        "purpose": "Save MCP connector config",
    },
    "log_session": {
        "method": "POST",
        "path": "/api/v1/logs/sessions",
        "purpose": "Log session data",
    },
    "log_invocation": {
        "method": "POST",
        "path": "/api/v1/logs/invocations",
        "purpose": "Log invocation data",
    },
}
