from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict, Optional

from oasyce.services.asset_lifecycle import ASSET_STATE_CANDIDATE, ASSET_STATE_DRAFT
from oasyce.services.source_asset_policy import resolve_source_asset_pricing


PORTFOLIO_ASSET_CLASS_GENERIC = "generic_asset"
PORTFOLIO_ASSET_CLASS_OPEN_SOURCE = "open_source_source"
PORTFOLIO_ASSET_CLASS_RESTRICTED = "restricted_asset"


@dataclass(frozen=True)
class PortfolioRegistrationDecision:
    resolved_price_model: str
    asset_class: str
    publish_action: str = "new_asset"
    reason: Optional[str] = None
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass(frozen=True)
class PortfolioCandidateDecision:
    lifecycle_state: str
    recommended_price_model: str
    asset_class: str
    publish_action: str
    reason: Optional[str] = None
    metadata: Dict[str, Any] = field(default_factory=dict)


def resolve_register_policy(
    file_path: str,
    *,
    requested_price_model: str = "auto",
) -> PortfolioRegistrationDecision:
    pricing_decision = resolve_source_asset_pricing(
        file_path,
        requested_price_model=requested_price_model,
    )
    asset_class = _asset_class_for_pricing(pricing_decision.reason)
    metadata = dict(pricing_decision.metadata)
    metadata.setdefault("asset_class", asset_class)
    metadata.setdefault("recommended_price_model", pricing_decision.resolved_price_model)
    metadata.setdefault("publish_action", "new_asset")
    if pricing_decision.reason:
        metadata.setdefault("portfolio_policy_reason", pricing_decision.reason)
    return PortfolioRegistrationDecision(
        resolved_price_model=pricing_decision.resolved_price_model,
        asset_class=asset_class,
        publish_action="new_asset",
        reason=pricing_decision.reason,
        metadata=metadata,
    )


def evaluate_candidate_policy(
    *,
    file_path: str,
    sensitivity: str,
    confidence: float,
    requested_price_model: str = "auto",
) -> PortfolioCandidateDecision:
    if sensitivity == "sensitive":
        reason = "sensitive_requires_review"
        metadata = {
            "asset_class": PORTFOLIO_ASSET_CLASS_RESTRICTED,
            "recommended_price_model": requested_price_model,
            "publish_action": "manual_review",
            "portfolio_policy_reason": reason,
            "review_required": True,
            "sensitivity": sensitivity,
            "confidence": confidence,
        }
        return PortfolioCandidateDecision(
            lifecycle_state=ASSET_STATE_DRAFT,
            recommended_price_model=requested_price_model,
            asset_class=PORTFOLIO_ASSET_CLASS_RESTRICTED,
            publish_action="manual_review",
            reason=reason,
            metadata=metadata,
        )

    registration = resolve_register_policy(
        file_path,
        requested_price_model=requested_price_model,
    )
    metadata = dict(registration.metadata)
    metadata.update(
        {
            "asset_class": registration.asset_class,
            "recommended_price_model": registration.resolved_price_model,
            "publish_action": "candidate",
            "sensitivity": sensitivity,
            "confidence": confidence,
        }
    )
    if registration.reason:
        metadata.setdefault("portfolio_policy_reason", registration.reason)
    return PortfolioCandidateDecision(
        lifecycle_state=ASSET_STATE_CANDIDATE,
        recommended_price_model=registration.resolved_price_model,
        asset_class=registration.asset_class,
        publish_action="candidate",
        reason=registration.reason,
        metadata=metadata,
    )


def _asset_class_for_pricing(reason: Optional[str]) -> str:
    if reason == "public_git_open_source_defaults_free":
        return PORTFOLIO_ASSET_CLASS_OPEN_SOURCE
    return PORTFOLIO_ASSET_CLASS_GENERIC
