# -*- coding: utf-8 -*-
"""Location: ./plugins/header_injector/header_injector.py
Copyright 2025
SPDX-License-Identifier: Apache-2.0
Authors: Mihai Criveti

Header Injector Plugin.

Injects custom HTTP headers into resource fetches by merging into payload.metadata["headers"].

Hook: resource_pre_fetch
"""

# Future
from __future__ import annotations

# Standard
from typing import Dict, Optional

# Third-Party
from pydantic import BaseModel

# First-Party
from cpex.framework import (
    Plugin,
    PluginConfig,
    PluginContext,
    ResourcePreFetchPayload,
    ResourcePreFetchResult,
)


class HeaderInjectorConfig(BaseModel):
    """Configuration for header injection.

    Attributes:
        headers: Dictionary of headers to inject.
        uri_prefixes: Optional list of URI prefixes to filter on.
    """

    headers: Dict[str, str] = {}
    uri_prefixes: Optional[list[str]] = None  # only apply when URI startswith any prefix


def _should_apply(uri: str, prefixes: Optional[list[str]]) -> bool:
    """Check if headers should be applied to a URI.

    Args:
        uri: Resource URI.
        prefixes: Optional list of URI prefixes.

    Returns:
        True if headers should be applied.
    """
    if not prefixes:
        return True
    return any(uri.startswith(p) for p in prefixes)


class HeaderInjectorPlugin(Plugin):
    """Inject custom headers for resource fetching."""

    def __init__(self, config: PluginConfig) -> None:
        """Initialize the header injector plugin.

        Args:
            config: Plugin configuration.
        """
        super().__init__(config)
        self._cfg = HeaderInjectorConfig(**(config.config or {}))

    async def resource_pre_fetch(self, payload: ResourcePreFetchPayload, context: PluginContext) -> ResourcePreFetchResult:
        """Inject custom headers before resource fetch.

        Args:
            payload: Resource fetch payload.
            context: Plugin execution context.

        Returns:
            Result with modified headers if applicable.
        """
        if not _should_apply(payload.uri, self._cfg.uri_prefixes):
            return ResourcePreFetchResult(continue_processing=True)
        md = dict(payload.metadata or {})
        hdrs = {**md.get("headers", {}), **self._cfg.headers}
        md["headers"] = hdrs
        new_payload = ResourcePreFetchPayload(uri=payload.uri, metadata=md)
        return ResourcePreFetchResult(modified_payload=new_payload, metadata={"headers_injected": True, "count": len(self._cfg.headers)})
