use uuid::Uuid;

/// Generate an ARN for a resource.
pub fn generate_arn(
    service: &str,
    resource_type: &str,
    identifier: &str,
    region: &str,
    account_id: &str,
) -> String {
    match service {
        "iam" => format!("arn:aws:iam::{account_id}:{resource_type}/{identifier}"),
        "s3" => format!("arn:aws:s3:::{identifier}"),
        _ => format!("arn:aws:{service}:{region}:{account_id}:{resource_type}/{identifier}"),
    }
}

/// Generate a service-appropriate resource ID.
pub fn generate_id(service: &str, resource_type: &str) -> String {
    let short = &Uuid::new_v4().simple().to_string()[..8];
    let long = &Uuid::new_v4().simple().to_string()[..17];
    match (service, resource_type) {
        ("ec2", "vpc") => format!("vpc-{short}"),
        ("ec2", "subnet") => format!("subnet-{short}"),
        ("ec2", "security-group") => format!("sg-{short}"),
        ("ec2", "security-group-rule") => format!("sgr-{short}"),
        ("ec2", "internet-gateway") => format!("igw-{short}"),
        ("ec2", "nat-gateway") => format!("nat-{short}"),
        ("ec2", "route-table") => format!("rtb-{short}"),
        ("ec2", "elastic-ip") => format!("eipalloc-{short}"),
        ("ec2", "instance") => format!("i-{long}"),
        ("ec2", "launch-template") => format!("lt-{long}"),
        ("ec2", "volume") => format!("vol-{long}"),
        ("ec2", "instance-profile") => format!("ip-{short}"),
        ("elasticloadbalancing", "loadbalancer") => format!("arn-lb-{short}"),
        ("elasticloadbalancing", "targetgroup") => format!("arn-tg-{short}"),
        ("elasticloadbalancing", "listener") => format!("arn-listener-{short}"),
        ("lambda", "function") => identifier_or_uuid(long),
        ("ssm", "parameter") => identifier_or_uuid(long),
        ("kms", "key") => Uuid::new_v4().to_string(),
        ("acm", "certificate") => Uuid::new_v4().to_string(),
        ("route53", "record") => format!("record-{short}"),
        ("secretsmanager", "secret") => format!("secret-{short}"),
        ("backup", "plan") => Uuid::new_v4().to_string(),
        ("backup", "vault") => format!("vault-{short}"),
        ("dlm", "policy") => format!("policy-{short}"),
        ("wafv2", "webacl") => Uuid::new_v4().to_string(),
        ("codebuild", "project") => format!("project-{short}"),
        ("autoscaling", "group") => format!("asg-{short}"),
        ("logs", "log-group") => identifier_or_uuid(long),
        ("events", "rule") => identifier_or_uuid(long),
        _ => format!("{resource_type}-{short}"),
    }
}

fn identifier_or_uuid(fallback: &str) -> String {
    fallback.to_string()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ec2_vpc_id_format() {
        let id = generate_id("ec2", "vpc");
        assert!(id.starts_with("vpc-"), "got: {id}");
        assert_eq!(id.len(), 12); // vpc- + 8 hex chars
    }

    #[test]
    fn iam_arn_has_no_region() {
        let arn = generate_arn("iam", "role", "my-role", "us-east-1", "000000000000");
        assert_eq!(arn, "arn:aws:iam::000000000000:role/my-role");
    }

    #[test]
    fn ec2_arn_has_region() {
        let arn = generate_arn("ec2", "vpc", "vpc-abc123", "us-east-1", "000000000000");
        assert_eq!(arn, "arn:aws:ec2:us-east-1:000000000000:vpc/vpc-abc123");
    }
}
