"""
Address Workflow.

This workflow handles the address creation process:
1. Create TeamAddress record in Django (Teams service)
2. Create node in ArangoDB (Geo service)
3. Trigger Prefect sync_node flow for isochrone/route calculations
4. Update address status to ready

Workflow-first approach: The address entity is created by the workflow,
not before it. This ensures we never have orphaned records.
"""

from datetime import timedelta

from temporalio import workflow
from temporalio.common import RetryPolicy

with workflow.unsafe.imports_passed_through():
    from ..types import (
        AddressData,
        AddressWorkflowResult,
        CreateAddressInDjangoInput,
        CreateAddressInDjangoResult,
        TriggerPrefectSyncInput,
        TriggerPrefectSyncResult,
        UpdateAddressStatusInput,
    )


# Retry policy for external API calls
EXTERNAL_API_RETRY = RetryPolicy(
    maximum_attempts=5,
    initial_interval=timedelta(seconds=2),
    backoff_coefficient=2.0,
    maximum_interval=timedelta(seconds=30),
)

# Retry policy for internal service calls
INTERNAL_API_RETRY = RetryPolicy(
    maximum_attempts=3,
    initial_interval=timedelta(seconds=1),
    backoff_coefficient=2.0,
    maximum_interval=timedelta(seconds=10),
)


@workflow.defn(name="create_address")
class AddressWorkflow:
    """
    Address creation workflow.

    Creates address in Django, then syncs to graph database
    and triggers route calculations.
    """

    @workflow.run
    async def run(self, data: AddressData) -> AddressWorkflowResult:
        """Execute the address creation workflow."""
        workflow.logger.info(
            "Starting address workflow %s for team %s",
            data.workflow_id,
            data.team_uuid,
        )

        # Step 1: Create address in Django (Teams service)
        create_result: CreateAddressInDjangoResult = await workflow.execute_activity(
            "create_address_in_django",
            CreateAddressInDjangoInput(
                workflow_id=data.workflow_id,
                team_uuid=data.team_uuid,
                name=data.name,
                address=data.address,
                latitude=data.latitude,
                longitude=data.longitude,
                country_code=data.country_code,
                is_default=data.is_default,
            ),
            schedule_to_close_timeout=timedelta(seconds=30),
            start_to_close_timeout=timedelta(seconds=15),
            retry_policy=INTERNAL_API_RETRY,
        )

        # Handle both dict (replay) and dataclass result
        success = (
            create_result.success
            if hasattr(create_result, "success")
            else create_result["success"]
        )
        if not success:
            message = (
                create_result.message
                if hasattr(create_result, "message")
                else create_result["message"]
            )
            workflow.logger.error("Failed to create address in Django: %s", message)
            return AddressWorkflowResult(
                status="failed",
                message=f"Failed to create address: {message}",
            )

        address_uuid = (
            create_result.address_uuid
            if hasattr(create_result, "address_uuid")
            else create_result["address_uuid"]
        )
        team_type = (
            create_result.team_type
            if hasattr(create_result, "team_type")
            else create_result.get("team_type", "buyer")
        )
        workflow.logger.info("Created address %s in Django (team_type=%s)", address_uuid, team_type)

        # Step 2: Trigger Prefect sync_node flow (only if we have coordinates)
        # Prefect will create node in ArangoDB, calculate isochrones, and connect to graph
        sync_success = False
        sync_error = ""

        if data.latitude is not None and data.longitude is not None:
            try:
                sync_result: TriggerPrefectSyncResult = await workflow.execute_activity(
                    "trigger_prefect_sync",
                    TriggerPrefectSyncInput(
                        node_uuid=address_uuid,
                        name=data.name,
                        latitude=data.latitude,
                        longitude=data.longitude,
                        country_code=data.country_code,
                        node_type=team_type,  # "buyer" or "seller"
                        team_uuid=data.team_uuid,
                    ),
                    schedule_to_close_timeout=timedelta(minutes=35),
                    start_to_close_timeout=timedelta(minutes=35),
                    retry_policy=EXTERNAL_API_RETRY,
                )
                # Handle both dict (replay) and dataclass result
                sync_success = (
                    sync_result.success
                    if hasattr(sync_result, "success")
                    else sync_result["success"]
                )

                if sync_success:
                    flow_run_id = (
                        sync_result.flow_run_id
                        if hasattr(sync_result, "flow_run_id")
                        else sync_result["flow_run_id"]
                    )
                    workflow.logger.info(
                        "Prefect sync completed for address %s (type=%s), flow_run_id=%s",
                        address_uuid,
                        team_type,
                        flow_run_id,
                    )
                else:
                    sync_error = (
                        sync_result.message
                        if hasattr(sync_result, "message")
                        else sync_result.get("message", "Unknown error")
                    )
                    workflow.logger.error(
                        "Prefect sync failed for address %s: %s",
                        address_uuid,
                        sync_error,
                    )
            except Exception as e:
                sync_error = str(e)
                workflow.logger.error("Failed to trigger Prefect sync: %s", sync_error)
        else:
            # No coordinates - consider it an error
            sync_error = "No coordinates provided for address"
            workflow.logger.warning(sync_error)

        # Step 3: Update address status based on Prefect result
        final_status = "active" if sync_success else "error"
        await workflow.execute_activity(
            "update_address_status",
            UpdateAddressStatusInput(
                address_uuid=address_uuid,
                status=final_status,
                error_message=sync_error if not sync_success else None,
            ),
            schedule_to_close_timeout=timedelta(seconds=30),
            start_to_close_timeout=timedelta(seconds=15),
            retry_policy=INTERNAL_API_RETRY,
        )

        workflow.logger.info(
            "Address workflow completed: address=%s, status=%s",
            address_uuid,
            final_status,
        )

        return AddressWorkflowResult(
            status="completed" if sync_success else "failed",
            address_uuid=address_uuid,
            graph_node_id=address_uuid if sync_success else "",
            message=sync_error if not sync_success else "",
        )
