# Copyright 2024 Klira AI
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""PHI pipeline contract — defines the PII/PHI de-identification interface.

Architecture: Custom export with protobuf mutation (see Phase 0.4 in plan).

Pipeline:
    1. Spans created during agent execution (zero latency impact).
    2. BatchSpanProcessor buffers spans normally.
    3. KliraOTLPSpanExporter.export() serializes to protobuf (mutable).
    4. If anonymization=True, walk protobuf attributes:
       a. Presidio AnalyzerEngine.analyze() → entity results
       b. Presidio AnonymizerEngine.anonymize() → cleaned text
       c. Overwrite protobuf StringValue in-place
       d. Append klira.phi.* attributes per span
    5. Send modified protobuf via HTTP POST.

Failure mode: If Presidio fails on any span, export UNCHANGED (fail-open).
    The span will have klira.phi.detected absent (not False), which the
    platform treats as "scan failed — flag for manual review."

No SpanProcessor approach (rejected — see plan Phase 0.4 for rationale).
No summary span (rejected — batch can span multiple traces).
"""

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum


class PhiMethod(Enum):
    """Anonymization methods supported by the PHI pipeline."""

    REDACT = "redact"
    MASK = "mask"
    REPLACE = "replace"
    HASH = "hash"


# Attributes that will be scanned for PII/PHI content (exact match).
# Additional attributes are matched via PHI_SCANNABLE_PATTERNS below.
PHI_SCANNABLE_ATTRIBUTES: tuple[str, ...] = (
    "gen_ai.prompt",
    "gen_ai.prompt.original",
    "klira.output",
    "klira.input",
)

# Glob patterns for additional attribute matching (fnmatch syntax).
# Any attribute key matching one of these patterns is scanned for PHI.
PHI_SCANNABLE_PATTERNS: tuple[str, ...] = (
    "*.content",
    "*.text",
    "*.message",
    "klira.clinical.*",
    "klira.healthcare.*",
)


@dataclass(frozen=True)
class PhiEntityResult:
    """Result of PHI detection for a single entity."""

    entity_type: str
    start: int
    end: int
    score: float


@dataclass(frozen=True)
class PhiScanResult:
    """Result of PHI scanning for a single attribute value."""

    detected: bool
    entity_count: int
    entity_types: tuple[str, ...]
    anonymized_text: str | None = None
    entities: tuple[PhiEntityResult, ...] = ()


@dataclass(frozen=True)
class PhiSpanAttributes:
    """PHI-related attributes to append to a span after scanning.

    These are appended as new KeyValue entries in the protobuf, not set
    on the Python ReadableSpan (which is immutable).
    """

    detected: bool
    entity_count: int = 0
    entity_types: tuple[str, ...] = ()
