"""
VPC Evidence Loader - Load VPC resources from JSON evidence files

This module provides EvidenceLoader class for loading VPC resource counts from
JSON evidence files generated by AWS API inventory collection.

Strategic Context:
- Extracted from vpc-inventory-analyzer.py lines 330-429
- Supports both live AWS API and evidence file analysis
- CRITICAL: Distinguishes Interface VPCEs ($7.30/mo) vs Gateway VPCEs (FREE)
- Evidence files follow naming pattern: {vpc_id}-{resource_type}.json

Evidence File Format:
- vpc-xxx-enis.json: Network interfaces (ENI activity indicator)
- vpc-xxx-nat-gateways.json: NAT Gateways ($32.85/month each)
- vpc-xxx-vpc-endpoints.json: VPC Endpoints (Interface vs Gateway)
- vpc-xxx-ec2-instances.json: EC2 instances
- vpc-xxx-lambda-functions.json: Lambda functions
- vpc-xxx-rds-instances.json: RDS database instances
- vpc-xxx-tgw-attachments.json: Transit Gateway attachments
- vpc-xxx-subnets.json: Subnets
"""

import json
from pathlib import Path
from typing import List, Dict, Any
from runbooks.vpc.models import VPCResources


class EvidenceLoader:
    """
    Load VPC resources from JSON evidence files.

    Evidence files are generated by AWS API inventory collection and stored
    in artifacts/evidence/network/ directory with standardized naming:
    {vpc_id}-{resource_type}.json

    This enables cost analysis without requiring live AWS API access.
    """

    def __init__(self, evidence_dir: Path):
        """
        Initialize evidence loader.

        Args:
            evidence_dir: Path to directory containing JSON evidence files
                         (e.g., /Volumes/Working/1xOps/CloudOps-Runbooks/artifacts/evidence/network)
        """
        self.evidence_dir = Path(evidence_dir)

        if not self.evidence_dir.exists():
            raise ValueError(f"Evidence directory not found: {evidence_dir}")

    def load_vpc_resources(self, vpc_id: str) -> VPCResources:
        """
        Load resource counts from JSON evidence files for specific VPC.

        Evidence files processed:
        - {vpc_id}-enis.json: Network interfaces (0 ENIs = unused VPC)
        - {vpc_id}-nat-gateways.json: NAT Gateways ($32.85/month each)
        - {vpc_id}-vpc-endpoints.json: Interface ($7.30/mo) vs Gateway (FREE)
        - {vpc_id}-ec2-instances.json: EC2 compute instances
        - {vpc_id}-lambda-functions.json: Lambda functions
        - {vpc_id}-rds-instances.json: RDS database instances
        - {vpc_id}-tgw-attachments.json: Transit Gateway attachments
        - {vpc_id}-subnets.json: Subnets

        Args:
            vpc_id: VPC identifier (e.g., vpc-123)

        Returns:
            VPCResources: Resource counts for VPC

        Example:
            loader = EvidenceLoader(Path("artifacts/evidence/network"))
            resources = loader.load_vpc_resources("vpc-007462e1e648ef6de")
            print(f"NAT Gateways: {resources.nat_gateways}")
            print(f"Interface VPCEs: {resources.vpce_interface}")
            print(f"Gateway VPCEs: {resources.vpce_gateway} (FREE)")
        """
        resources = VPCResources(vpc_id=vpc_id)

        # Load ENIs (primary activity indicator)
        resources.enis = self._load_eni_count(vpc_id)

        # Load NAT Gateways (primary cost driver: $32.85/month each)
        resources.nat_gateways = self._load_nat_gateway_count(vpc_id)

        # Load VPC Endpoints (CRITICAL: distinguish Interface vs Gateway)
        vpce_counts = self._load_vpc_endpoint_counts(vpc_id)
        resources.vpce_interface = vpce_counts["interface"]
        resources.vpce_gateway = vpce_counts["gateway"]

        # Load compute resources
        resources.ec2_instances = self._load_ec2_instance_count(vpc_id)
        resources.lambda_functions = self._load_lambda_function_count(vpc_id)

        # Load database resources
        resources.rds_instances = self._load_rds_instance_count(vpc_id)

        # Load network resources
        resources.load_balancers = self._load_load_balancer_count(vpc_id)
        resources.tgw_attachments = self._load_tgw_attachment_count(vpc_id)
        resources.subnets = self._load_subnet_count(vpc_id)

        return resources

    def _load_json_file(self, filename: str) -> List[Any]:
        """
        Load JSON evidence file.

        Args:
            filename: Evidence file name (e.g., vpc-123-enis.json)

        Returns:
            List of resources from JSON file, empty list if file doesn't exist
        """
        file_path = self.evidence_dir / filename

        if not file_path.exists():
            return []

        try:
            with open(file_path, "r") as f:
                data = json.load(f)
                return data if isinstance(data, list) else []
        except (json.JSONDecodeError, IOError) as e:
            print(f"⚠️ Warning: Failed to load {filename}: {e}")
            return []

    def _load_eni_count(self, vpc_id: str) -> int:
        """
        Load ENI count from evidence file.

        ENI file format (array of arrays):
        [
            ["eni-xxx", "in-use", "interface", "description"],
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of network interfaces (0 = unused VPC)
        """
        enis = self._load_json_file(f"{vpc_id}-enis.json")
        return len(enis)

    def _load_nat_gateway_count(self, vpc_id: str) -> int:
        """
        Load NAT Gateway count from evidence file.

        NAT Gateway file format (array of arrays):
        [
            ["nat-xxx", "available", "subnet-xxx", ...],
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of NAT Gateways (each costs $32.85/month)
        """
        nat_gateways = self._load_json_file(f"{vpc_id}-nat-gateways.json")
        return len(nat_gateways)

    def _load_vpc_endpoint_counts(self, vpc_id: str) -> Dict[str, int]:
        """
        Load VPC Endpoint counts from evidence file.

        CRITICAL: Distinguish Interface vs Gateway endpoints for cost calculation.

        VPC Endpoint file format (array of arrays):
        [
            ["vpce-xxx", "com.amazonaws.region.s3", "Gateway", "available"],
            ["vpce-yyy", "com.amazonaws.region.ec2", "Interface", "available"],
            ...
        ]

        Cost implications:
        - Interface endpoints: $7.30/month EACH
        - Gateway endpoints (S3, DynamoDB): FREE

        Args:
            vpc_id: VPC identifier

        Returns:
            Dict with "interface" and "gateway" counts
        """
        vpce_data = self._load_json_file(f"{vpc_id}-vpc-endpoints.json")

        interface_count = 0
        gateway_count = 0

        for endpoint in vpce_data:
            if not isinstance(endpoint, list) or len(endpoint) < 3:
                continue

            endpoint_type = endpoint[2]  # Third element is type (Interface/Gateway)

            if endpoint_type == "Interface":
                interface_count += 1
            elif endpoint_type == "Gateway":
                gateway_count += 1

        return {"interface": interface_count, "gateway": gateway_count}

    def _load_ec2_instance_count(self, vpc_id: str) -> int:
        """
        Load EC2 instance count from evidence file.

        EC2 file format (array of Reservation arrays):
        [
            [  # Reservation 1
                {"InstanceId": "i-xxx", "State": {...}, ...},
                ...
            ],
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of EC2 instances
        """
        ec2_data = self._load_json_file(f"{vpc_id}-ec2-instances.json")

        instance_count = 0

        for reservation in ec2_data:
            if isinstance(reservation, list):
                # Count non-null instances in reservation
                instance_count += sum(1 for instance in reservation if instance)

        return instance_count

    def _load_lambda_function_count(self, vpc_id: str) -> int:
        """
        Load Lambda function count from evidence file.

        Lambda file format (array of function objects):
        [
            {"FunctionName": "func-1", "VpcConfig": {...}, ...},
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of Lambda functions attached to VPC
        """
        lambda_functions = self._load_json_file(f"{vpc_id}-lambda-functions.json")
        return len(lambda_functions)

    def _load_rds_instance_count(self, vpc_id: str) -> int:
        """
        Load RDS instance count from evidence file.

        RDS file format (array of DB instance objects):
        [
            {"DBInstanceIdentifier": "db-1", ...},
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of RDS database instances
        """
        rds_instances = self._load_json_file(f"{vpc_id}-rds-instances.json")
        return len(rds_instances)

    def _load_load_balancer_count(self, vpc_id: str) -> int:
        """
        Load load balancer count from evidence file.

        Load Balancer file format (array of LB objects):
        [
            {"LoadBalancerArn": "arn:...", "Type": "application", ...},
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of load balancers (ALB/NLB)
        """
        load_balancers = self._load_json_file(f"{vpc_id}-load-balancers.json")
        return len(load_balancers)

    def _load_tgw_attachment_count(self, vpc_id: str) -> int:
        """
        Load Transit Gateway attachment count from evidence file.

        TGW Attachment file format (array of attachment objects):
        [
            {"TransitGatewayAttachmentId": "tgw-attach-xxx", ...},
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of Transit Gateway attachments (indicates cross-account connectivity)
        """
        tgw_attachments = self._load_json_file(f"{vpc_id}-tgw-attachments.json")
        return len(tgw_attachments)

    def _load_subnet_count(self, vpc_id: str) -> int:
        """
        Load subnet count from evidence file.

        Subnet file format (array of subnet objects):
        [
            {"SubnetId": "subnet-xxx", "CidrBlock": "10.0.1.0/24", ...},
            ...
        ]

        Args:
            vpc_id: VPC identifier

        Returns:
            Number of subnets in VPC
        """
        subnets = self._load_json_file(f"{vpc_id}-subnets.json")
        return len(subnets)
