"""Activities for team invitations and Novu notifications."""
import hashlib
import logging
import secrets

import httpx
from temporalio import activity

from optovia_workflows.types import (
    CreateInvitationInput,
    CreateInvitationResult,
    CreateInvitationTokenInput,
    CreateInvitationTokenResult,
    UpdateInvitationTokenStatusInput,
    UpdateInvitationTokenStatusResult,
    SendInviteNotificationInput,
    SendInviteNotificationResult,
)

from ..config import settings

logger = logging.getLogger(__name__)

CREATE_INVITATION_MUTATION = """
mutation CreateInvitationFromWorkflow($input: CreateInvitationFromWorkflowInput!) {
  createInvitationFromWorkflow(input: $input) {
    success
    message
    invitationUuid
  }
}
"""

CREATE_TOKEN_MUTATION = """
mutation CreateInvitationToken($input: CreateInvitationTokenInput!) {
  createInvitationToken(input: $input) {
    success
    message
    token {
      uuid
    }
  }
}
"""

UPDATE_TOKEN_STATUS_MUTATION = """
mutation UpdateInvitationTokenStatus($input: UpdateInvitationTokenStatusInput!) {
  updateInvitationTokenStatus(input: $input) {
    success
    message
    token {
      uuid
    }
  }
}
"""


@activity.defn(name="create_invitation")
def create_invitation(data: CreateInvitationInput) -> CreateInvitationResult:
    url = f"http://{settings.TEAMS_INTERNAL_URL}/graphql/m2m/"

    payload = {
        "teamUuid": data.team_uuid,
        "email": data.email,
        "role": data.role,
        "invitedBy": data.invited_by,
        "expiresAt": data.expires_at,
    }

    with httpx.Client(timeout=settings.TEAMS_TIMEOUT) as client:
        response = client.post(
            url,
            json={"query": CREATE_INVITATION_MUTATION, "variables": {"input": payload}},
            headers={"Content-Type": "application/json"},
        )
        response.raise_for_status()
        result = response.json()

    if "errors" in result:
        return CreateInvitationResult(success=False, message=str(result["errors"]))

    mutation_result = result.get("data", {}).get("createInvitationFromWorkflow", {})
    if not mutation_result.get("success"):
        return CreateInvitationResult(success=False, message=mutation_result.get("message", "Unknown error"))

    return CreateInvitationResult(success=True, invitation_uuid=mutation_result.get("invitationUuid", ""))


@activity.defn(name="create_invitation_token")
def create_invitation_token(data: CreateInvitationTokenInput) -> CreateInvitationTokenResult:
    raw_token = secrets.token_urlsafe(32)
    token_hash = hashlib.sha256(raw_token.encode("utf-8")).hexdigest()

    url = f"http://{settings.TEAMS_INTERNAL_URL}/graphql/m2m/"
    payload = {
        "invitationUuid": data.invitation_uuid,
        "tokenHash": token_hash,
        "expiresAt": data.expires_at,
    }

    with httpx.Client(timeout=settings.TEAMS_TIMEOUT) as client:
        response = client.post(
            url,
            json={"query": CREATE_TOKEN_MUTATION, "variables": {"input": payload}},
            headers={"Content-Type": "application/json"},
        )
        response.raise_for_status()
        result = response.json()

    if "errors" in result:
        return CreateInvitationTokenResult(success=False, message=str(result["errors"]))

    mutation_result = result.get("data", {}).get("createInvitationToken", {})
    if not mutation_result.get("success"):
        return CreateInvitationTokenResult(success=False, message=mutation_result.get("message", "Unknown error"))

    token_uuid = (mutation_result.get("token") or {}).get("uuid", "")
    return CreateInvitationTokenResult(success=True, token=raw_token, token_uuid=token_uuid)


@activity.defn(name="update_invitation_token_status")
def update_invitation_token_status(data: UpdateInvitationTokenStatusInput) -> UpdateInvitationTokenStatusResult:
    url = f"http://{settings.TEAMS_INTERNAL_URL}/graphql/m2m/"
    payload = {"tokenUuid": data.token_uuid, "status": data.status}

    with httpx.Client(timeout=settings.TEAMS_TIMEOUT) as client:
        response = client.post(
            url,
            json={"query": UPDATE_TOKEN_STATUS_MUTATION, "variables": {"input": payload}},
            headers={"Content-Type": "application/json"},
        )
        response.raise_for_status()
        result = response.json()

    if "errors" in result:
        return UpdateInvitationTokenStatusResult(success=False, message=str(result["errors"]))

    mutation_result = result.get("data", {}).get("updateInvitationTokenStatus", {})
    if not mutation_result.get("success"):
        return UpdateInvitationTokenStatusResult(success=False, message=mutation_result.get("message", "Unknown error"))

    return UpdateInvitationTokenStatusResult(success=True, message="OK")


@activity.defn(name="send_invite_notification")
def send_invite_notification(data: SendInviteNotificationInput) -> SendInviteNotificationResult:
    if not settings.NOVU_API_KEY or not settings.NOVU_TRIGGER_ID:
        return SendInviteNotificationResult(success=False, message="Novu config missing")

    url = f"{settings.NOVU_API_URL}/v1/events/trigger"
    invite_url = f"{settings.INVITE_ACCEPT_URL}?token={data.token}"

    payload = {
        "name": settings.NOVU_TRIGGER_ID,
        "to": {
            "subscriberId": data.email,
            "email": data.email,
        },
        "payload": {
            "team_uuid": data.team_uuid,
            "role": data.role,
            "invite_url": invite_url,
        },
    }

    headers = {
        "Content-Type": "application/json",
        "Authorization": f"ApiKey {settings.NOVU_API_KEY}",
    }

    try:
        with httpx.Client(timeout=settings.NOVU_TIMEOUT) as client:
            response = client.post(url, json=payload, headers=headers)
            response.raise_for_status()
        return SendInviteNotificationResult(success=True)
    except Exception as exc:
        logger.exception("Failed to send Novu invite")
        return SendInviteNotificationResult(success=False, message=str(exc))
