"""Load Balancer usage report."""

from dataclasses import dataclass, field
from datetime import datetime

import boto3
from rich.console import Console

console = Console()


@dataclass
class TargetGroupInfo:
    """Target group info."""

    arn: str
    name: str
    target_count: int


@dataclass
class LoadBalancerInfo:
    """Basic Load Balancer info from AWS."""

    arn: str
    name: str
    type: str  # application, network, gateway, classic
    created: datetime
    dns_name: str


@dataclass
class LoadBalancerReport:
    """Load Balancer with its target info."""

    arn: str
    name: str
    type: str
    created: datetime
    dns_name: str
    target_groups: list[TargetGroupInfo] = field(default_factory=list)
    instance_count: int = 0  # For classic ELB

    @property
    def total_targets(self) -> int:
        if self.type == "classic":
            return self.instance_count
        return sum(tg.target_count for tg in self.target_groups)

    @property
    def is_orphaned(self) -> bool:
        return self.total_targets == 0

    def to_dict(self) -> dict:
        return {
            "arn": self.arn,
            "name": self.name,
            "type": self.type,
            "created": self.created.isoformat(),
            "dns_name": self.dns_name,
            "target_groups": [
                {"arn": tg.arn, "name": tg.name, "target_count": tg.target_count}
                for tg in self.target_groups
            ],
            "instance_count": self.instance_count,
            "total_targets": self.total_targets,
            "is_orphaned": self.is_orphaned,
        }


def get_elbv2_load_balancers(session: boto3.Session) -> list[LoadBalancerInfo]:
    """Fetch all ALB/NLB load balancers."""
    elbv2 = session.client("elbv2")
    paginator = elbv2.get_paginator("describe_load_balancers")

    load_balancers = []
    for page in paginator.paginate():
        for lb in page["LoadBalancers"]:
            load_balancers.append(
                LoadBalancerInfo(
                    arn=lb["LoadBalancerArn"],
                    name=lb["LoadBalancerName"],
                    type=lb["Type"],
                    created=lb["CreatedTime"],
                    dns_name=lb.get("DNSName", ""),
                )
            )

    console.print(f"Found {len(load_balancers)} ALB/NLB load balancers")
    return load_balancers


def get_classic_load_balancers(session: boto3.Session) -> list[LoadBalancerInfo]:
    """Fetch all Classic ELB load balancers."""
    elb = session.client("elb")
    paginator = elb.get_paginator("describe_load_balancers")

    load_balancers = []
    for page in paginator.paginate():
        for lb in page["LoadBalancerDescriptions"]:
            load_balancers.append(
                LoadBalancerInfo(
                    arn=f"classic:{lb['LoadBalancerName']}",
                    name=lb["LoadBalancerName"],
                    type="classic",
                    created=lb["CreatedTime"],
                    dns_name=lb.get("DNSName", ""),
                )
            )

    console.print(f"Found {len(load_balancers)} Classic ELB load balancers")
    return load_balancers


def get_target_groups_by_lb(session: boto3.Session) -> dict[str, list[TargetGroupInfo]]:
    """Get target groups mapped by load balancer ARN."""
    elbv2 = session.client("elbv2")

    # First, get all target groups
    tg_paginator = elbv2.get_paginator("describe_target_groups")
    target_groups = []
    for page in tg_paginator.paginate():
        for tg in page["TargetGroups"]:
            target_groups.append(tg)

    console.print(f"Found {len(target_groups)} target groups")

    # Get target count for each target group
    tg_targets: dict[str, int] = {}
    for tg in target_groups:
        tg_arn = tg["TargetGroupArn"]
        response = elbv2.describe_target_health(TargetGroupArn=tg_arn)
        tg_targets[tg_arn] = len(response.get("TargetHealthDescriptions", []))

    # Map target groups to load balancers
    lb_target_groups: dict[str, list[TargetGroupInfo]] = {}
    for tg in target_groups:
        tg_info = TargetGroupInfo(
            arn=tg["TargetGroupArn"],
            name=tg["TargetGroupName"],
            target_count=tg_targets.get(tg["TargetGroupArn"], 0),
        )
        for lb_arn in tg.get("LoadBalancerArns", []):
            lb_target_groups.setdefault(lb_arn, []).append(tg_info)

    return lb_target_groups


def get_classic_instance_counts(session: boto3.Session) -> dict[str, int]:
    """Get instance counts for Classic ELBs."""
    elb = session.client("elb")
    paginator = elb.get_paginator("describe_load_balancers")

    instance_counts: dict[str, int] = {}
    for page in paginator.paginate():
        for lb in page["LoadBalancerDescriptions"]:
            lb_name = lb["LoadBalancerName"]
            instance_counts[lb_name] = len(lb.get("Instances", []))

    return instance_counts


def build_report(
    session: boto3.Session | None = None,
) -> list[LoadBalancerReport]:
    """Build Load Balancer usage report."""
    if session is None:
        session = boto3.Session()

    # Fetch ALB/NLB
    elbv2_lbs = get_elbv2_load_balancers(session)
    lb_target_groups = get_target_groups_by_lb(session)

    # Fetch Classic ELB
    classic_lbs = get_classic_load_balancers(session)
    classic_instance_counts = get_classic_instance_counts(session)

    # Build report
    report = []

    # ALB/NLB
    for lb in elbv2_lbs:
        report.append(
            LoadBalancerReport(
                arn=lb.arn,
                name=lb.name,
                type=lb.type,
                created=lb.created,
                dns_name=lb.dns_name,
                target_groups=lb_target_groups.get(lb.arn, []),
            )
        )

    # Classic ELB
    for lb in classic_lbs:
        report.append(
            LoadBalancerReport(
                arn=lb.arn,
                name=lb.name,
                type=lb.type,
                created=lb.created,
                dns_name=lb.dns_name,
                instance_count=classic_instance_counts.get(lb.name, 0),
            )
        )

    return report


def delete_load_balancer(session: boto3.Session, lb_arn: str, lb_type: str) -> None:
    """Delete a load balancer."""
    if lb_type == "classic":
        elb = session.client("elb")
        lb_name = lb_arn.replace("classic:", "")
        elb.delete_load_balancer(LoadBalancerName=lb_name)
        console.print(f"  Deleted Classic ELB {lb_name}")
    else:
        elbv2 = session.client("elbv2")
        elbv2.delete_load_balancer(LoadBalancerArn=lb_arn)
        console.print(f"  Deleted {lb_type} load balancer {lb_arn.split('/')[-2]}")
