"""
Canonical Control Library schemas.

Phase 1 Step 4: extracted from ``compliance.api.canonical_control_routes``.
"""

from typing import Any, Optional

from pydantic import BaseModel


class FrameworkResponse(BaseModel):
    id: str
    framework_id: str
    name: str
    version: str
    description: Optional[str] = None
    owner: Optional[str] = None
    policy_version: Optional[str] = None
    release_state: str
    created_at: str
    updated_at: str


class ControlResponse(BaseModel):
    id: str
    framework_id: str
    control_id: str
    title: str
    objective: str
    rationale: str
    scope: dict[str, Any]
    requirements: list[Any]
    test_procedure: list[Any]
    evidence: list[Any]
    severity: str
    risk_score: Optional[float] = None
    implementation_effort: Optional[str] = None
    evidence_confidence: Optional[float] = None
    open_anchors: list[Any]
    release_state: str
    tags: list[Any]
    created_at: str
    updated_at: str


class ControlCreateRequest(BaseModel):
    framework_id: str  # e.g. 'bp_security_v1'
    control_id: str  # e.g. 'AUTH-003'
    title: str
    objective: str
    rationale: str
    scope: dict[str, Any] = {}
    requirements: list[Any] = []
    test_procedure: list[Any] = []
    evidence: list[Any] = []
    severity: str = "medium"
    risk_score: Optional[float] = None
    implementation_effort: Optional[str] = None
    evidence_confidence: Optional[float] = None
    open_anchors: list[Any] = []
    release_state: str = "draft"
    tags: list[Any] = []


class ControlUpdateRequest(BaseModel):
    title: Optional[str] = None
    objective: Optional[str] = None
    rationale: Optional[str] = None
    scope: Optional[dict[str, Any]] = None
    requirements: Optional[list[Any]] = None
    test_procedure: Optional[list[Any]] = None
    evidence: Optional[list[Any]] = None
    severity: Optional[str] = None
    risk_score: Optional[float] = None
    implementation_effort: Optional[str] = None
    evidence_confidence: Optional[float] = None
    open_anchors: Optional[list[Any]] = None
    release_state: Optional[str] = None
    tags: Optional[list[Any]] = None


class SimilarityCheckRequest(BaseModel):
    source_text: str
    candidate_text: str


class SimilarityCheckResponse(BaseModel):
    max_exact_run: int
    token_overlap: float
    ngram_jaccard: float
    embedding_cosine: float
    lcs_ratio: float
    status: str
    details: dict[str, Any]


__all__ = [
    "FrameworkResponse",
    "ControlResponse",
    "ControlCreateRequest",
    "ControlUpdateRequest",
    "SimilarityCheckRequest",
    "SimilarityCheckResponse",
]
