"""
Address-related activities for platform worker.

These activities handle:
- Creating addresses in Django Teams service
- Creating nodes in ArangoDB
- Triggering Prefect sync_node flow
- Updating address status
"""

import logging

import httpx
from temporalio import activity

from optovia_workflows.types import (
    CreateAddressInDjangoInput,
    CreateAddressInDjangoResult,
    TriggerPrefectSyncInput,
    TriggerPrefectSyncResult,
    UpdateAddressStatusInput,
    UpdateAddressStatusResult,
)

from ..config import settings

logger = logging.getLogger(__name__)


CREATE_ADDRESS_MUTATION = """
mutation CreateAddressFromWorkflow(
    $workflowId: String!,
    $teamUuid: String!,
    $name: String!,
    $address: String!,
    $latitude: Float,
    $longitude: Float,
    $countryCode: String,
    $isDefault: Boolean
) {
    createAddressFromWorkflow(
        workflowId: $workflowId,
        teamUuid: $teamUuid,
        name: $name,
        address: $address,
        latitude: $latitude,
        longitude: $longitude,
        countryCode: $countryCode,
        isDefault: $isDefault
    ) {
        success
        addressUuid
        message
    }
}
"""


UPDATE_ADDRESS_STATUS_MUTATION = """
mutation UpdateAddressStatus(
    $addressUuid: String!,
    $status: String!,
    $errorMessage: String
) {
    updateAddressStatus(
        addressUuid: $addressUuid,
        status: $status,
        errorMessage: $errorMessage
    ) {
        success
        message
    }
}
"""


@activity.defn(name="create_address_in_django")
def create_address_in_django(data: CreateAddressInDjangoInput) -> CreateAddressInDjangoResult:
    """
    Create TeamAddress in Django Teams service via GraphQL M2M endpoint.
    """
    url = f"http://{settings.TEAMS_INTERNAL_URL}/graphql/m2m/"

    logger.info(
        "Creating address for team %s (workflow=%s)",
        data.team_uuid,
        data.workflow_id,
    )

    with httpx.Client(timeout=settings.TEAMS_TIMEOUT) as client:
        response = client.post(
            url,
            json={
                "query": CREATE_ADDRESS_MUTATION,
                "variables": {
                    "workflowId": data.workflow_id,
                    "teamUuid": data.team_uuid,
                    "name": data.name,
                    "address": data.address,
                    "latitude": data.latitude,
                    "longitude": data.longitude,
                    "countryCode": data.country_code,
                    "isDefault": data.is_default,
                },
            },
            headers={"Content-Type": "application/json"},
        )
        response.raise_for_status()

        result = response.json()
        if "errors" in result:
            error_msg = str(result["errors"])
            logger.error("GraphQL errors: %s", error_msg)
            return CreateAddressInDjangoResult(success=False, message=error_msg)

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

        address_uuid = mutation_result.get("addressUuid", "")
        logger.info("Created address %s for team %s", address_uuid, data.team_uuid)

        return CreateAddressInDjangoResult(
            success=True,
            address_uuid=address_uuid,
        )


@activity.defn(name="update_address_status")
def update_address_status(data: UpdateAddressStatusInput) -> UpdateAddressStatusResult:
    """
    Update address status in Django Teams service via GraphQL M2M endpoint.
    """
    url = f"http://{settings.TEAMS_INTERNAL_URL}/graphql/m2m/"

    logger.info(
        "Updating address %s status to %s",
        data.address_uuid,
        data.status,
    )

    with httpx.Client(timeout=settings.TEAMS_TIMEOUT) as client:
        response = client.post(
            url,
            json={
                "query": UPDATE_ADDRESS_STATUS_MUTATION,
                "variables": {
                    "addressUuid": data.address_uuid,
                    "status": data.status,
                    "errorMessage": data.error_message,
                },
            },
            headers={"Content-Type": "application/json"},
        )
        response.raise_for_status()

        result = response.json()
        if "errors" in result:
            error_msg = str(result["errors"])
            logger.error("GraphQL errors: %s", error_msg)
            return UpdateAddressStatusResult(success=False, message=error_msg)

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

        return UpdateAddressStatusResult(success=True)


@activity.defn(name="trigger_prefect_sync")
def trigger_prefect_sync(data: TriggerPrefectSyncInput) -> TriggerPrefectSyncResult:
    """
    Trigger Prefect sync_node flow for isochrone/route calculations.

    Creates flow run and returns immediately. Prefect will signal Temporal
    workflow when done via prefect_sync_completed signal.

    If node data (name, lat, lon, etc.) is provided, passes it directly to Prefect.
    Otherwise, passes only node_uuid and Prefect will fetch from Odoo.
    """
    logger.info("Triggering Prefect sync for node %s", data.node_uuid)

    try:
        # Get deployment ID
        deployment_url = f"{settings.PREFECT_API_URL}/deployments/name/sync-node/sync-node-deployment"

        with httpx.Client(timeout=30) as client:
            response = client.get(deployment_url)
            response.raise_for_status()
            deployment_id = response.json()["id"]

            # Build parameters based on available data
            if data.name and data.latitude and data.longitude:
                # User address - pass full node_data to Prefect
                node_data = {
                    "uuid": data.node_uuid,
                    "name": data.name,
                    "latitude": data.latitude,
                    "longitude": data.longitude,
                    "country_code": data.country_code,
                    "transport_types": ["auto"],  # User addresses support auto only
                    "node_type": data.node_type or "buyer",  # Default to buyer
                    "team_uuid": data.team_uuid,
                    "workflow_id": data.workflow_id,  # For Prefect to signal back
                }
                parameters = {"node_data": node_data}
                logger.info(
                    "Triggering Prefect sync with node_data for %s (type=%s)",
                    data.node_uuid,
                    node_data["node_type"],
                )
            else:
                # Logistics node - pass only UUID, Prefect will fetch from Odoo
                parameters = {"node_uuid": data.node_uuid}
                logger.info(
                    "Triggering Prefect sync with node_uuid for %s (will fetch from Odoo)",
                    data.node_uuid,
                )

            # Create flow run
            run_url = f"{settings.PREFECT_API_URL}/deployments/{deployment_id}/create_flow_run"
            response = client.post(
                run_url,
                json={"parameters": parameters},
            )
            response.raise_for_status()
            flow_run = response.json()
            flow_run_id = flow_run["id"]

            logger.info(
                "Created Prefect flow run %s for node %s, Prefect will signal when done",
                flow_run_id,
                data.node_uuid,
            )

            # Return immediately - Prefect will signal Temporal workflow when done
            return TriggerPrefectSyncResult(
                success=True,
                flow_run_id=flow_run_id,
            )

    except httpx.HTTPStatusError as exc:
        # Re-raise 5xx errors for Temporal to retry
        if exc.response.status_code >= 500:
            logger.error("Prefect API returned %s, will retry", exc.response.status_code)
            raise
        logger.error("Failed to trigger Prefect sync: %s", exc)
        return TriggerPrefectSyncResult(
            success=False,
            message=str(exc),
        )
    except Exception as e:
        logger.error("Failed to trigger Prefect sync: %s", e)
        return TriggerPrefectSyncResult(
            success=False,
            message=str(e),
        )
