from typing import List, Tuple

from lib.models import ResourceEdge, ResourceNode


def extract(client) -> Tuple[List[ResourceNode], List[ResourceEdge]]:
    """
    Extract Lambda function nodes and their edges from an awslambda_client.

    Edges produced:
      - lambda → VPC         [network]
      - lambda → subnet      [network]
      - lambda → sg          [network]
      - lambda → event-source[triggers]  (from EventSourceMapping)
      - lambda → layer ARN   [depends_on]
      - lambda → DLQ target  [data_flow]
      - lambda → KMS key     [encrypts]
    """
    nodes: List[ResourceNode] = []
    edges: List[ResourceEdge] = []

    for fn in client.functions.values():
        props = {
            "runtime": fn.runtime,
            "vpc_id": fn.vpc_id,
        }
        if fn.environment:
            props["has_env_vars"] = True
        if fn.kms_key_arn:
            props["kms_key_arn"] = fn.kms_key_arn

        nodes.append(
            ResourceNode(
                id=fn.arn,
                type="lambda_function",
                name=fn.name,
                service="lambda",
                region=fn.region,
                account_id=client.audited_account,
                properties=props,
            )
        )

        # Network edges → VPC, subnets, security groups
        if fn.vpc_id:
            edges.append(
                ResourceEdge(
                    source_id=fn.arn,
                    target_id=fn.vpc_id,
                    edge_type="network",
                    label="in-vpc",
                )
            )
        for sg_id in fn.security_groups or []:
            edges.append(
                ResourceEdge(
                    source_id=fn.arn,
                    target_id=sg_id,
                    edge_type="network",
                    label="sg",
                )
            )
        for subnet_id in fn.subnet_ids or set():
            edges.append(
                ResourceEdge(
                    source_id=fn.arn,
                    target_id=subnet_id,
                    edge_type="network",
                    label="subnet",
                )
            )

        # Trigger edges from event source mappings
        for esm in getattr(fn, "event_source_mappings", []):
            edges.append(
                ResourceEdge(
                    source_id=esm.event_source_arn,
                    target_id=fn.arn,
                    edge_type="triggers",
                    label=f"esm:{esm.state}",
                )
            )

        # Layer dependency edges
        for layer in getattr(fn, "layers", []):
            edges.append(
                ResourceEdge(
                    source_id=fn.arn,
                    target_id=layer.arn,
                    edge_type="depends_on",
                    label="layer",
                )
            )

        # Dead-letter queue data-flow edge
        dlq = getattr(fn, "dead_letter_config", None)
        if dlq and dlq.target_arn:
            edges.append(
                ResourceEdge(
                    source_id=fn.arn,
                    target_id=dlq.target_arn,
                    edge_type="data_flow",
                    label="dlq",
                )
            )

        # KMS encryption edge
        if fn.kms_key_arn:
            edges.append(
                ResourceEdge(
                    source_id=fn.kms_key_arn,
                    target_id=fn.arn,
                    edge_type="encrypts",
                    label="kms",
                )
            )

    return nodes, edges
