"""
Hardcoded resource ARN extraction for services with quirky CloudTrail formats.

These 22 services have non-trivial extraction logic that can't be expressed
by generic IAM reference pattern resolution. All other services are handled
by the data-driven Layer 4 in resource_extractor.py.
"""

from __future__ import annotations

from ..models.cloudtrail import CloudTrailEvent

# Services with quirky extraction logic that can't be expressed
# by generic IAM reference pattern resolution.  All other services
# are handled by the data-driven Layer 4.
QUIRKY_SERVICES = frozenset({
    "s3",                    # Composite bucket/key, no region/account
    "ec2",                   # 10 resource types, nested instancesSet, response fallback
    "iam",                   # No region, priority order (user > role > policy)
    "sqs",                   # URL parsing to extract queue name
    "kms",                   # UUID vs alias/ prefix vs full ARN detection
    "eks",                   # Sub-resources (nodegroup, fargate) under cluster
    "glue",                  # Composite database/table from two params
    "ssm",                   # Leading slash stripping
    "route53",               # /hostedzone/ prefix stripping, no region
    "wafv2",                 # Scope-based path (regional vs global)
    "organizations",         # Wildcard org ID in ARN
    "events",                # Dual placeholder resolution (RuleName/EventBusName from name)
    "elasticloadbalancing",  # ALB app/ prefix not in IAM reference
    "monitoring",            # eventSource != IAM prefix (cloudwatch)
    "cloudformation",        # Stack ARN requires wildcard ID suffix (/*)
    "cloudfront",            # id/Id matches wrong pattern (origin-access-identity vs distribution)
    "cloudtrail",            # Trail name priority over event data store ARN passthrough
    "codepipeline",          # name fills multiple placeholders in stage/action patterns
    "config",                # configurationRecorderName placeholder mismatch
    "elasticache",           # Cluster priority over replication group, colon separator
    "rds",                   # Instance priority over cluster, dB prefix quirk
    "states",                # name fallback fills multiple placeholders in version patterns
})


def extract_from_quirky_service(
    event: CloudTrailEvent, region: str, account: str
) -> str | None:
    """Extract resource ARN using hardcoded service-specific patterns.

    Args:
        event: CloudTrail event to extract resource ARN from.
        region: AWS region (or "*" if unknown).
        account: AWS account ID (or "*" if unknown).

    Returns:
        Resource ARN string or None if no ARN could be resolved.
    """
    params = event.request_parameters or {}
    service = event.event_source.split(".")[0]

    # S3 bucket operations -- composite bucket/key, no region/account
    if service == "s3":
        bucket = params.get("bucketName")
        if bucket:
            key = params.get("key", "")
            if key:
                return f"arn:aws:s3:::{bucket}/{key}"
            return f"arn:aws:s3:::{bucket}"

    # EC2 operations -- 10 resource types, nested structures, response fallback
    if service == "ec2":
        instance_id = params.get("instanceId")
        if instance_id:
            return f"arn:aws:ec2:{region}:{account}:instance/{instance_id}"
        instances_set = params.get("instancesSet")
        if isinstance(instances_set, dict):
            items = instances_set.get("items", [])
            if items and isinstance(items[0], dict):
                iid = items[0].get("instanceId")
                if iid:
                    return f"arn:aws:ec2:{region}:{account}:instance/{iid}"
        volume_id = params.get("volumeId")
        if volume_id:
            return f"arn:aws:ec2:{region}:{account}:volume/{volume_id}"
        snapshot_id = params.get("snapshotId")
        if snapshot_id:
            return f"arn:aws:ec2:{region}:{account}:snapshot/{snapshot_id}"
        group_id = params.get("groupId")
        if group_id:
            return f"arn:aws:ec2:{region}:{account}:security-group/{group_id}"
        image_id = params.get("imageId")
        if image_id:
            return f"arn:aws:ec2:{region}:{account}:image/{image_id}"
        vpc_id = params.get("vpcId")
        if vpc_id:
            return f"arn:aws:ec2:{region}:{account}:vpc/{vpc_id}"
        subnet_id = params.get("subnetId")
        if subnet_id:
            return f"arn:aws:ec2:{region}:{account}:subnet/{subnet_id}"
        igw_id = params.get("internetGatewayId")
        if igw_id:
            return f"arn:aws:ec2:{region}:{account}:internet-gateway/{igw_id}"
        eni_id = params.get("networkInterfaceId")
        if eni_id:
            return f"arn:aws:ec2:{region}:{account}:network-interface/{eni_id}"
        key_name = params.get("keyName")
        if key_name:
            return f"arn:aws:ec2:{region}:{account}:key-pair/{key_name}"
        arn = ec2_from_response(event, region, account)
        if arn:
            return arn

    # IAM operations -- no region, priority order
    if service == "iam":
        if "userName" in params:
            return f"arn:aws:iam::{account}:user/{params['userName']}"
        if "roleName" in params:
            return f"arn:aws:iam::{account}:role/{params['roleName']}"
        if "policyArn" in params:
            return str(params["policyArn"])

    # SQS operations -- URL parsing
    if service == "sqs":
        queue_url = params.get("queueUrl") or params.get("QueueUrl")
        if queue_url:
            parts = str(queue_url).rstrip("/").split("/")
            if len(parts) >= 1:
                queue_name = parts[-1]
                return f"arn:aws:sqs:{region}:{account}:{queue_name}"
        q_name = params.get("queueName") or params.get("QueueName")
        if q_name:
            return f"arn:aws:sqs:{region}:{account}:{q_name}"

    # KMS operations -- UUID vs alias vs full ARN
    if service == "kms":
        key_id = params.get("keyId") or params.get("KeyId")
        if key_id:
            key_id = str(key_id)
            if key_id.startswith("arn:"):
                return key_id
            if key_id.startswith("alias/"):
                return f"arn:aws:kms:{region}:{account}:{key_id}"
            return f"arn:aws:kms:{region}:{account}:key/{key_id}"

    # EKS operations -- sub-resources under cluster
    if service == "eks":
        cluster_name = params.get("name") or params.get("clusterName")
        if cluster_name:
            cluster_name = str(cluster_name)
            if cluster_name.startswith("arn:"):
                return cluster_name
            nodegroup = params.get("nodegroupName")
            if nodegroup:
                return f"arn:aws:eks:{region}:{account}:nodegroup/{cluster_name}/{nodegroup}"
            fargate = params.get("fargateProfileName")
            if fargate:
                return f"arn:aws:eks:{region}:{account}:fargateprofile/{cluster_name}/{fargate}"
            return f"arn:aws:eks:{region}:{account}:cluster/{cluster_name}"

    # Glue operations -- composite database/table
    if service == "glue":
        database = params.get("databaseName") or params.get("DatabaseName")
        if database:
            table = params.get("tableName") or params.get("TableName")
            if table:
                return f"arn:aws:glue:{region}:{account}:table/{database}/{table}"
            return f"arn:aws:glue:{region}:{account}:database/{database}"

    # SSM operations -- leading slash stripping
    if service == "ssm":
        param_name = params.get("name") or params.get("Name")
        if param_name:
            param_name = str(param_name)
            if param_name.startswith("arn:"):
                return param_name
            clean_name = param_name.lstrip("/")
            return f"arn:aws:ssm:{region}:{account}:parameter/{clean_name}"
        doc_name = params.get("documentName") or params.get("DocumentName")
        if doc_name:
            return f"arn:aws:ssm:{region}:{account}:document/{doc_name}"

    # Route 53 operations -- /hostedzone/ prefix stripping, no region
    if service == "route53":
        zone_id = params.get("hostedZoneId") or params.get("HostedZoneId")
        if zone_id:
            zone_id = str(zone_id)
            if "/" in zone_id:
                zone_id = zone_id.rstrip("/").split("/")[-1]
            return f"arn:aws:route53:::hostedzone/{zone_id}"

    # WAFv2 operations -- scope-based path
    if service == "wafv2":
        web_acl_arn = params.get("webACLArn") or params.get("WebACLArn")
        if web_acl_arn and str(web_acl_arn).startswith("arn:"):
            return str(web_acl_arn)
        name = params.get("name") or params.get("Name")
        scope = params.get("scope") or params.get("Scope")
        if name and scope:
            scope_str = str(scope).lower()
            scope_path = "regional" if scope_str == "regional" else "global"
            return f"arn:aws:wafv2:{region}:{account}:{scope_path}/webacl/{name}/*"

    # EventBridge operations -- dual placeholder resolution
    if service == "events":
        event_bus = params.get("eventBusName") or params.get("EventBusName")
        if event_bus:
            event_bus = str(event_bus)
            if event_bus.startswith("arn:"):
                return event_bus
            return f"arn:aws:events:{region}:{account}:event-bus/{event_bus}"
        rule_name = params.get("name") or params.get("Name")
        if rule_name:
            return f"arn:aws:events:{region}:{account}:rule/{rule_name}"

    # ELBv2 operations -- ALB app/ prefix
    if service == "elasticloadbalancing":
        lb_arn = params.get("loadBalancerArn") or params.get("LoadBalancerArn")
        if lb_arn and str(lb_arn).startswith("arn:"):
            return str(lb_arn)
        lb_name = params.get("name") or params.get("Name")
        if lb_name:
            return (
                f"arn:aws:elasticloadbalancing:{region}:{account}:loadbalancer/app/{lb_name}/*"
            )
        tg_arn = params.get("targetGroupArn") or params.get("TargetGroupArn")
        if tg_arn and str(tg_arn).startswith("arn:"):
            return str(tg_arn)

    # CloudWatch (monitoring) operations -- eventSource != IAM prefix
    if service == "monitoring":
        alarm_name = params.get("alarmName") or params.get("AlarmName")
        if alarm_name:
            return f"arn:aws:cloudwatch:{region}:{account}:alarm:{alarm_name}"
        dashboard = params.get("dashboardName") or params.get("DashboardName")
        if dashboard:
            return f"arn:aws:cloudwatch::{account}:dashboard/{dashboard}"

    # CloudFormation operations -- wildcard stack ID suffix
    if service == "cloudformation":
        stack_name = params.get("stackName") or params.get("StackName")
        if stack_name:
            stack_name = str(stack_name)
            if stack_name.startswith("arn:"):
                return stack_name
            return f"arn:aws:cloudformation:{region}:{account}:stack/{stack_name}/*"

    # Organizations operations -- wildcard org ID
    if service == "organizations":
        target_id = params.get("accountId") or params.get("AccountId")
        if target_id:
            return f"arn:aws:organizations::{account}:account/o-*/{target_id}"
        ou_id = params.get("organizationalUnitId") or params.get("OrganizationalUnitId")
        if ou_id:
            return f"arn:aws:organizations::{account}:ou/o-*/{ou_id}"
        policy_id = params.get("policyId") or params.get("PolicyId")
        if policy_id:
            return f"arn:aws:organizations::{account}:policy/o-*/{policy_id}"

    # CloudFront operations -- regionless, id param ambiguity
    if service == "cloudfront":
        dist_id = params.get("id") or params.get("Id")
        if dist_id:
            return f"arn:aws:cloudfront::{account}:distribution/{dist_id}"

    # CloudTrail operations -- trail name priority over event data store
    if service == "cloudtrail":
        trail = params.get("trailName") or params.get("TrailName")
        if trail:
            trail = str(trail)
            if trail.startswith("arn:"):
                return trail
            return f"arn:aws:cloudtrail:{region}:{account}:trail/{trail}"
        eds = params.get("eventDataStore") or params.get("EventDataStore")
        if eds:
            eds = str(eds)
            if eds.startswith("arn:"):
                return eds
            return f"arn:aws:cloudtrail:{region}:{account}:eventdatastore/{eds}"

    # CodePipeline operations -- name fills multiple pattern placeholders
    if service == "codepipeline":
        name = (
            params.get("name")
            or params.get("Name")
            or params.get("pipelineName")
            or params.get("PipelineName")
        )
        if name:
            return f"arn:aws:codepipeline:{region}:{account}:{name}"

    # Config operations -- configurationRecorderName mismatch
    if service == "config":
        rule = params.get("configRuleName") or params.get("ConfigRuleName")
        if rule:
            return f"arn:aws:config:{region}:{account}:config-rule/{rule}"
        recorder = (
            params.get("configurationRecorderName")
            or params.get("ConfigurationRecorderName")
        )
        if recorder:
            return f"arn:aws:config:{region}:{account}:configuration-recorder/{recorder}"

    # ElastiCache operations -- cluster priority, colon separator
    if service == "elasticache":
        cluster_id = params.get("cacheClusterId") or params.get("CacheClusterId")
        if cluster_id:
            return f"arn:aws:elasticache:{region}:{account}:cluster:{cluster_id}"
        repl_id = params.get("replicationGroupId") or params.get("ReplicationGroupId")
        if repl_id:
            return f"arn:aws:elasticache:{region}:{account}:replicationgroup:{repl_id}"

    # RDS operations -- instance priority, dB prefix quirk
    if service == "rds":
        db_id = params.get("dBInstanceIdentifier") or params.get("DBInstanceIdentifier")
        if db_id:
            return f"arn:aws:rds:{region}:{account}:db:{db_id}"
        cluster_id = params.get("dBClusterIdentifier") or params.get("DBClusterIdentifier")
        if cluster_id:
            return f"arn:aws:rds:{region}:{account}:cluster:{cluster_id}"

    # Step Functions operations -- name fills version pattern placeholders
    if service == "states":
        sm_arn = params.get("stateMachineArn") or params.get("StateMachineArn")
        if sm_arn and str(sm_arn).startswith("arn:"):
            return str(sm_arn)
        exec_arn = params.get("executionArn") or params.get("ExecutionArn")
        if exec_arn and str(exec_arn).startswith("arn:"):
            return str(exec_arn)
        name = params.get("name") or params.get("Name")
        if name:
            return f"arn:aws:states:{region}:{account}:stateMachine:{name}"

    return None


def ec2_from_response(event: CloudTrailEvent, region: str, account: str) -> str | None:
    """Extract EC2 resource ARNs from responseElements.

    Handles cases like RunInstances where the resource ID only exists
    in the response (the instance doesn't exist yet at request time).
    """
    resp = event.response_elements
    if not resp or not isinstance(resp, dict):
        return None

    # RunInstances: responseElements.instancesSet.items[0].instanceId
    instances_set = resp.get("instancesSet")
    if isinstance(instances_set, dict):
        items = instances_set.get("items", [])
        if items and isinstance(items[0], dict):
            iid = items[0].get("instanceId")
            if iid:
                return f"arn:aws:ec2:{region}:{account}:instance/{iid}"

    # CreateVolume: responseElements.volumeId
    volume_id = resp.get("volumeId")
    if volume_id:
        return f"arn:aws:ec2:{region}:{account}:volume/{volume_id}"

    # CreateSnapshot: responseElements.snapshotId
    snapshot_id = resp.get("snapshotId")
    if snapshot_id:
        return f"arn:aws:ec2:{region}:{account}:snapshot/{snapshot_id}"

    # CreateSecurityGroup: responseElements.groupId
    group_id = resp.get("groupId")
    if group_id:
        return f"arn:aws:ec2:{region}:{account}:security-group/{group_id}"

    # CreateSubnet: responseElements.subnet.subnetId
    subnet = resp.get("subnet")
    if isinstance(subnet, dict):
        sid = subnet.get("subnetId")
        if sid:
            return f"arn:aws:ec2:{region}:{account}:subnet/{sid}"

    # CreateVpc: responseElements.vpc.vpcId
    vpc = resp.get("vpc")
    if isinstance(vpc, dict):
        vid = vpc.get("vpcId")
        if vid:
            return f"arn:aws:ec2:{region}:{account}:vpc/{vid}"

    # CreateInternetGateway: responseElements.internetGateway.internetGatewayId
    igw = resp.get("internetGateway")
    if isinstance(igw, dict):
        igw_id = igw.get("internetGatewayId")
        if igw_id:
            return f"arn:aws:ec2:{region}:{account}:internet-gateway/{igw_id}"

    return None
