"""
ANSI/ANS Standards Handler

Manages licensed standards documents (ANSI/ANS-8 series for nuclear criticality safety).
These are copyrighted materials that require licensing agreements.

Note: This module provides structure and metadata handling only.
Actual document acquisition requires manual licensing from ANSI/ANS.
"""

import logging
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from pathlib import Path

logger = logging.getLogger(__name__)


class StandardsOrganization(Enum):
    """Standards organizations relevant to NCS."""

    ANSI = "American National Standards Institute"
    ANS = "American Nuclear Society"
    ASTM = "ASTM International"
    IEEE = "Institute of Electrical and Electronics Engineers"
    ISO = "International Organization for Standardization"


@dataclass
class Standard:
    """Represents a standards document."""

    designation: str  # e.g., "ANSI/ANS-8.1-2014"
    title: str
    organization: StandardsOrganization = StandardsOrganization.ANS
    publication_date: datetime | None = None
    reaffirmed_date: datetime | None = None
    supersedes: str | None = None  # Previous version
    superseded_by: str | None = None  # Newer version if obsolete
    abstract: str | None = None
    scope: str | None = None
    ics_codes: list[str] = field(default_factory=list)  # International Classification for Standards
    pages: int | None = None
    price: float | None = None
    purchase_url: str | None = None
    is_licensed: bool = False
    local_path: Path | None = None

    @property
    def doc_id(self) -> str:
        """Generate standardized document ID."""
        return self.designation

    @property
    def is_current(self) -> bool:
        """Check if this is the current version of the standard."""
        return self.superseded_by is None


# NCS-relevant standards catalog
NCS_STANDARDS_CATALOG: list[Standard] = [
    # ANSI/ANS-8 Series - Nuclear Criticality Safety
    Standard(
        designation="ANSI/ANS-8.1-2014",
        title="Nuclear Criticality Safety in Operations with Fissionable Materials Outside Reactors",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2014, 1, 1),
        reaffirmed_date=datetime(2019, 1, 1),
        abstract="Provides criteria for nuclear criticality safety in the handling, storing, processing, and transporting of fissionable materials outside nuclear reactors.",
        scope="Operations with fissionable materials outside reactors",
        pages=28,
        purchase_url="https://www.ans.org/store/item-240248/",
    ),
    Standard(
        designation="ANSI/ANS-8.3-1997",
        title="Criticality Accident Alarm System",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1997, 1, 1),
        reaffirmed_date=datetime(2017, 1, 1),
        abstract="Provides criteria for criticality accident alarm systems for detection of nuclear criticality accidents.",
        scope="Criticality accident alarm systems",
        pages=12,
        purchase_url="https://www.ans.org/store/item-240249/",
    ),
    Standard(
        designation="ANSI/ANS-8.5-1996",
        title="Use of Borosilicate-Glass Raschig Rings as a Neutron Absorber in Solutions of Fissile Material",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1996, 1, 1),
        reaffirmed_date=datetime(2017, 1, 1),
        abstract="Provides requirements for using borosilicate-glass Raschig rings for criticality control.",
        scope="Raschig ring criticality control",
        pages=8,
        purchase_url="https://www.ans.org/store/item-240250/",
    ),
    Standard(
        designation="ANSI/ANS-8.6-1983",
        title="Safety in Conducting Subcritical Neutron-Multiplication Measurements In Situ",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1983, 1, 1),
        reaffirmed_date=datetime(2017, 1, 1),
        abstract="Provides safety criteria for conducting subcritical neutron-multiplication measurements.",
        scope="Subcritical measurements",
        pages=10,
        purchase_url="https://www.ans.org/store/item-240251/",
    ),
    Standard(
        designation="ANSI/ANS-8.7-1998",
        title="Nuclear Criticality Safety in the Storage of Fissile Materials",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1998, 1, 1),
        reaffirmed_date=datetime(2017, 1, 1),
        abstract="Provides nuclear criticality safety guidance for storage of fissile materials.",
        scope="Fissile material storage",
        pages=14,
        purchase_url="https://www.ans.org/store/item-240252/",
    ),
    Standard(
        designation="ANSI/ANS-8.10-2015",
        title="Criteria for Nuclear Criticality Safety Controls in Operations with Shielding and Confinement",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2015, 1, 1),
        abstract="Provides criteria for criticality safety when shielding and confinement are used.",
        scope="Shielding and confinement",
        pages=16,
        purchase_url="https://www.ans.org/store/item-240253/",
    ),
    Standard(
        designation="ANSI/ANS-8.12-1987",
        title="Nuclear Criticality Control and Safety of Plutonium-Uranium Fuel Mixtures Outside Reactors",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1987, 1, 1),
        reaffirmed_date=datetime(2016, 1, 1),
        abstract="Provides guidance for criticality safety with Pu-U fuel mixtures.",
        scope="Pu-U fuel mixtures",
        pages=20,
        purchase_url="https://www.ans.org/store/item-240254/",
    ),
    Standard(
        designation="ANSI/ANS-8.17-2004",
        title="Criticality Safety Criteria for the Handling, Storage, and Transportation of LWR Fuel Outside Reactors",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2004, 1, 1),
        reaffirmed_date=datetime(2019, 1, 1),
        abstract="Provides criticality safety criteria for LWR fuel handling, storage, and transportation.",
        scope="LWR fuel handling",
        pages=18,
        purchase_url="https://www.ans.org/store/item-240255/",
    ),
    Standard(
        designation="ANSI/ANS-8.19-2014",
        title="Administrative Practices for Nuclear Criticality Safety",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2014, 1, 1),
        abstract="Provides administrative practices for ensuring nuclear criticality safety.",
        scope="Administrative practices",
        pages=14,
        purchase_url="https://www.ans.org/store/item-240256/",
    ),
    Standard(
        designation="ANSI/ANS-8.20-1991",
        title="Nuclear Criticality Safety Training",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1991, 1, 1),
        reaffirmed_date=datetime(2015, 1, 1),
        abstract="Provides guidance for nuclear criticality safety training programs.",
        scope="Training requirements",
        pages=8,
        purchase_url="https://www.ans.org/store/item-240257/",
    ),
    Standard(
        designation="ANSI/ANS-8.21-1995",
        title="Use of Fixed Neutron Absorbers in Nuclear Facilities Outside Reactors",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1995, 1, 1),
        reaffirmed_date=datetime(2019, 1, 1),
        abstract="Provides requirements for using fixed neutron absorbers for criticality control.",
        scope="Fixed neutron absorbers",
        pages=10,
        purchase_url="https://www.ans.org/store/item-240258/",
    ),
    Standard(
        designation="ANSI/ANS-8.22-1997",
        title="Nuclear Criticality Safety Based on Limiting and Controlling Moderators",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(1997, 1, 1),
        reaffirmed_date=datetime(2016, 1, 1),
        abstract="Provides criteria for criticality safety through moderator control.",
        scope="Moderator control",
        pages=12,
        purchase_url="https://www.ans.org/store/item-240259/",
    ),
    Standard(
        designation="ANSI/ANS-8.24-2017",
        title="Validation of Neutron Transport Methods for Nuclear Criticality Safety Calculations",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2017, 1, 1),
        abstract="Provides requirements for validation of criticality safety calculation methods.",
        scope="Calculation validation",
        pages=22,
        purchase_url="https://www.ans.org/store/item-240260/",
    ),
    Standard(
        designation="ANSI/ANS-8.26-2007",
        title="Criticality Safety Engineer Training and Qualification Program",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2007, 1, 1),
        reaffirmed_date=datetime(2016, 1, 1),
        abstract="Provides requirements for criticality safety engineer training and qualification.",
        scope="Engineer qualification",
        pages=14,
        purchase_url="https://www.ans.org/store/item-240261/",
    ),
    Standard(
        designation="ANSI/ANS-8.27-2015",
        title="Burnup Credit for LWR Fuel",
        organization=StandardsOrganization.ANS,
        publication_date=datetime(2015, 1, 1),
        abstract="Provides requirements for using burnup credit in criticality safety analyses for LWR fuel.",
        scope="Burnup credit",
        pages=20,
        purchase_url="https://www.ans.org/store/item-240262/",
    ),
]


class StandardsHandler:
    """
    Handler for standards documents.

    Manages metadata and licensing status for ANSI/ANS standards
    relevant to nuclear criticality safety.

    Note: This does not download standards automatically due to
    copyright restrictions. Use register_licensed_standard() to
    associate locally-acquired standards with their metadata.
    """

    def __init__(self, standards_dir: Path | None = None):
        """
        Initialize standards handler.

        Args:
            standards_dir: Directory containing licensed standards PDFs
        """
        self.standards_dir = standards_dir
        self._catalog = {s.designation: s for s in NCS_STANDARDS_CATALOG}

    def get_standard(self, designation: str) -> Standard | None:
        """
        Get standard metadata by designation.

        Args:
            designation: Standard designation (e.g., "ANSI/ANS-8.1-2014")

        Returns:
            Standard metadata or None if not in catalog
        """
        return self._catalog.get(designation)

    def list_standards(
        self,
        organization: StandardsOrganization | None = None,
        current_only: bool = True,
    ) -> list[Standard]:
        """
        List standards in catalog.

        Args:
            organization: Filter by organization
            current_only: Only include current (non-superseded) standards

        Returns:
            List of standards
        """
        standards = list(self._catalog.values())

        if organization:
            standards = [s for s in standards if s.organization == organization]

        if current_only:
            standards = [s for s in standards if s.is_current]

        return sorted(standards, key=lambda s: s.designation)

    def register_licensed_standard(
        self,
        designation: str,
        local_path: Path,
    ) -> bool:
        """
        Register a licensed standard with its local file path.

        Args:
            designation: Standard designation
            local_path: Path to the licensed PDF file

        Returns:
            True if registration successful, False if standard not in catalog
        """
        if designation not in self._catalog:
            logger.warning(f"Standard {designation} not in catalog")
            return False

        if not local_path.exists():
            logger.error(f"File not found: {local_path}")
            return False

        standard = self._catalog[designation]
        standard.is_licensed = True
        standard.local_path = local_path
        logger.info(f"Registered licensed standard: {designation}")
        return True

    def get_licensed_standards(self) -> list[Standard]:
        """Get all standards that have been licensed and registered."""
        return [s for s in self._catalog.values() if s.is_licensed]

    def get_missing_standards(self) -> list[Standard]:
        """Get standards that need licensing."""
        return [s for s in self._catalog.values() if not s.is_licensed]

    def get_licensing_summary(self) -> dict:
        """Get summary of licensing status."""
        all_standards = list(self._catalog.values())
        licensed = [s for s in all_standards if s.is_licensed]
        missing = [s for s in all_standards if not s.is_licensed]

        total_cost = sum(
            s.price for s in missing if s.price is not None
        )

        return {
            "total_standards": len(all_standards),
            "licensed": len(licensed),
            "missing": len(missing),
            "estimated_licensing_cost": total_cost,
            "missing_designations": [s.designation for s in missing],
        }
