from __future__ import annotations

import warnings
from urllib.parse import urlparse

import structlog
from httpx import HTTPStatusError

from mistralai.workflows.client import WorkflowsClient
from mistralai.workflows.core.config.config import config
from mistralai.workflows.exceptions import ErrorCode, WorkflowsException
from mistralai.workflows.protocol.v1.worker import WorkerInfo

logger = structlog.get_logger(__name__)


class WorkerRuntimeConfig(WorkerInfo):
    def apply(self) -> None:
        config.temporal.namespace = self.namespace
        config.temporal.server_url = normalize_temporal_url(self.scheduler_url)
        config.temporal.tls = self.tls


async def _fetch_worker_runtime_config(_api_key: str | None = None) -> WorkerRuntimeConfig:
    api_key = config.common.mistral_api_key.get_secret_value() if config.common.mistral_api_key else None
    workflows_client = WorkflowsClient(
        base_url=config.worker.server_url,
        api_version=config.worker.api_version,
        api_key=api_key or None,
        headers=config.worker.mistral_api_headers,
    )
    response = await workflows_client.who_am_i()
    logger.info("Worker runtime config resolved", namespace=response.namespace, scheduler_url=response.scheduler_url)
    return WorkerRuntimeConfig.model_validate_json(response.model_dump_json())


async def apply_worker_runtime_config(api_key: str | None = None) -> WorkerRuntimeConfig | None:
    try:
        runtime_config = await _fetch_worker_runtime_config(api_key)
        runtime_config.apply()
        logger.info(
            "Applied worker runtime config",
            namespace=runtime_config.namespace,
            scheduler_url=runtime_config.scheduler_url,
            tls=runtime_config.tls,
        )
        return runtime_config
    except HTTPStatusError as exc:
        if exc.response.status_code == 404:
            warnings.warn("Could not fetch worker config from server. Is your server up to date?")
            return None
        raise WorkflowsException(
            code=ErrorCode.WORKER_RUNTIME_CONFIG_ERROR,
            message="Failed to fetch worker runtime configuration from server",
        )


def normalize_temporal_url(url: str) -> str:
    original_url = url
    # If there's no scheme, urlparse misparses host:port inputs.
    # Prepend a dummy scheme so we can extract host and port correctly.
    if "://" not in url:
        url = f"dummy://{url}"

    parsed = urlparse(url)
    host = parsed.hostname
    if not host:
        raise ValueError(f"Unable to determine host from URL: {original_url}")

    if parsed.port is not None:
        port = parsed.port
    elif parsed.scheme == "https":
        port = 443
    elif parsed.scheme == "http":
        port = 80
    else:
        raise ValueError(f"Unable to determine port from URL: {original_url}")
    return f"{host}:{port}"
