"""FunctionPlugin ABC per GCAP-SPEC-FUNCTION-DESCRIPTOR-0001 section 4."""
from __future__ import annotations

import hashlib
import json
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Any


@dataclass
class FunctionContext:
    trigger_event_kind: str = ""
    trigger_event_cid: str = ""
    chronicle_session_id: str = ""
    gsap_context_id: str = ""
    invocation_id: str = ""
    pipeline_run_id: str = ""


@dataclass
class FunctionResult:
    success: bool = False
    data: Any = None
    error: str | None = None
    lineage_cid: str = ""
    duration_ms: float = 0.0
    metadata: dict[str, Any] = field(default_factory=dict)

    def output_cid(self) -> str:
        """Compute content-addressable hash of the output data."""
        canonical = json.dumps(self.data, sort_keys=True, separators=(",", ":"), default=str)
        return "sha256:" + hashlib.sha256(canonical.encode()).hexdigest()


class FunctionPlugin(ABC):
    """Abstract base for governed serverless functions."""

    function_id: str = ""
    corpus_entry_cid: str = ""
    capability_mask: int = 0
    trigger_events: list[str] = []
    accord_template: str = ""
    gsap_required: bool = True
    chronicle_enabled: bool = True
    max_duration_seconds: int = 30
    display_name: str = ""
    description: str = ""
    version: str = "0.1.0"

    @abstractmethod
    async def handle(self, event: dict[str, Any], context: FunctionContext) -> FunctionResult:
        ...

    @abstractmethod
    def health_check(self) -> bool:
        ...

    def descriptor(self) -> dict[str, Any]:
        """JSON-LD descriptor per GCAP-SPEC-FUNCTION-DESCRIPTOR-0001 §2."""
        return {
            "@context": "https://schema.gsap.dev/function/v1",
            "@type": "FunctionDescriptor",
            "function_id": self.function_id,
            "corpus_entry_cid": self.corpus_entry_cid,
            "capability_mask": self.capability_mask,
            "trigger_events": self.trigger_events,
            "accord_template": self.accord_template,
            "gsap_required": self.gsap_required,
            "chronicle_enabled": self.chronicle_enabled,
            "max_duration_seconds": self.max_duration_seconds,
            "display_name": self.display_name,
            "description": self.description,
            "version": self.version,
        }

    def knative_manifest(self, image: str, namespace: str = "default") -> dict[str, Any]:
        """Generate Knative Service manifest."""
        return {
            "apiVersion": "serving.knative.dev/v1",
            "kind": "Service",
            "metadata": {
                "name": self.function_id,
                "namespace": namespace,
                "labels": {
                    "gcap.dev/function-id": self.function_id,
                    "gcap.dev/capability-mask": str(self.capability_mask),
                },
                "annotations": {
                    "gcap.dev/corpus-entry-cid": self.corpus_entry_cid,
                    "gcap.dev/gsap-required": str(self.gsap_required).lower(),
                },
            },
            "spec": {
                "template": {
                    "metadata": {
                        "annotations": {
                            "autoscaling.knative.dev/minScale": "0",
                            "autoscaling.knative.dev/maxScale": "10",
                        },
                    },
                    "spec": {
                        "timeoutSeconds": self.max_duration_seconds,
                        "containers": [
                            {
                                "image": image,
                                "env": [
                                    {"name": "GCAP_FUNCTION_ID", "value": self.function_id},
                                    {"name": "GCAP_CAPABILITY_MASK", "value": str(self.capability_mask)},
                                ],
                            }
                        ],
                    },
                },
            },
        }
