#!/usr/bin/env python3
"""Zero trust cloud architecture assessment agent using AWS, Azure, and GCP SDKs."""

import json
import argparse
from datetime import datetime

try:
    import boto3
    from botocore.exceptions import ClientError
except ImportError:
    boto3 = None

try:
    HAS_AZURE = True
except ImportError:
    HAS_AZURE = False

try:
    HAS_GCP = True
except ImportError:
    HAS_GCP = False


ZERO_TRUST_PILLARS = [
    {"pillar": "Identity", "description": "Verify every identity with strong auth",
     "checks": ["MFA enforcement", "Conditional access policies", "Least privilege RBAC",
                 "Service account key rotation", "Passwordless authentication"]},
    {"pillar": "Device", "description": "Validate device posture before granting access",
     "checks": ["Device compliance policies", "MDM enrollment required",
                 "Certificate-based device identity", "OS patch level enforcement"]},
    {"pillar": "Network", "description": "Micro-segment and encrypt all communications",
     "checks": ["VPC/VNet segmentation", "Private endpoints for services",
                 "No public IPs on internal workloads", "TLS everywhere",
                 "Identity-Aware Proxy deployment"]},
    {"pillar": "Application", "description": "Secure app access without network trust",
     "checks": ["OAuth2/OIDC authentication", "API gateway with auth",
                 "No VPN-dependent access", "Runtime application self-protection"]},
    {"pillar": "Data", "description": "Classify and protect data at all states",
     "checks": ["Encryption at rest", "Encryption in transit",
                 "Data classification labels", "DLP policies active"]},
    {"pillar": "Visibility", "description": "Continuous monitoring and analytics",
     "checks": ["Centralized logging", "SIEM integration",
                 "User behavior analytics", "Real-time alerting"]},
]


def assess_aws_zero_trust(region="us-east-1"):
    """Assess AWS zero trust posture."""
    if boto3 is None:
        return {"error": "boto3 not installed"}
    findings = []

    iam = boto3.client("iam", region_name=region)
    try:
        summary = iam.get_account_summary()["SummaryMap"]
        if summary.get("AccountMFAEnabled", 0) == 0:
            findings.append({"pillar": "Identity", "check": "Root MFA",
                             "status": "FAIL", "severity": "CRITICAL",
                             "detail": "Root account MFA not enabled"})
        else:
            findings.append({"pillar": "Identity", "check": "Root MFA",
                             "status": "PASS", "detail": "Root MFA enabled"})
        users = iam.list_users()["Users"]
        for user in users[:20]:
            mfa = iam.list_mfa_devices(UserName=user["UserName"])["MFADevices"]
            if not mfa:
                findings.append({"pillar": "Identity", "check": "User MFA",
                                 "status": "FAIL", "severity": "HIGH",
                                 "detail": f"User {user['UserName']} has no MFA"})
    except ClientError as e:
        findings.append({"pillar": "Identity", "check": "IAM", "status": "ERROR", "detail": str(e)})

    ec2 = boto3.client("ec2", region_name=region)
    try:
        instances = ec2.describe_instances()
        for reservation in instances.get("Reservations", []):
            for inst in reservation.get("Instances", []):
                if inst.get("PublicIpAddress"):
                    findings.append({"pillar": "Network", "check": "Public IP",
                                     "status": "FAIL", "severity": "MEDIUM",
                                     "detail": f"Instance {inst['InstanceId']} has public IP "
                                               f"{inst['PublicIpAddress']}"})
    except ClientError as e:
        findings.append({"pillar": "Network", "status": "ERROR", "detail": str(e)})

    try:
        sgs = ec2.describe_security_groups()["SecurityGroups"]
        for sg in sgs:
            for rule in sg.get("IpPermissions", []):
                for ip in rule.get("IpRanges", []):
                    if ip.get("CidrIp") == "0.0.0.0/0":
                        port = rule.get("FromPort", "all")
                        findings.append({"pillar": "Network", "check": "Security Group",
                                         "status": "FAIL", "severity": "HIGH",
                                         "detail": f"SG {sg['GroupId']} port {port} open to 0.0.0.0/0"})
    except ClientError as e:
        findings.append({"pillar": "Network", "status": "ERROR", "detail": str(e)})

    s3 = boto3.client("s3", region_name=region)
    try:
        buckets = s3.list_buckets().get("Buckets", [])
        for bucket in buckets[:20]:
            try:
                enc = s3.get_bucket_encryption(Bucket=bucket["Name"])
                findings.append({"pillar": "Data", "check": "S3 Encryption",
                                 "status": "PASS", "detail": f"{bucket['Name']} encrypted"})
            except ClientError:
                findings.append({"pillar": "Data", "check": "S3 Encryption",
                                 "status": "FAIL", "severity": "HIGH",
                                 "detail": f"Bucket {bucket['Name']} has no default encryption"})
    except ClientError as e:
        findings.append({"pillar": "Data", "status": "ERROR", "detail": str(e)})

    ct = boto3.client("cloudtrail", region_name=region)
    try:
        trails = ct.describe_trails()["trailList"]
        if trails:
            findings.append({"pillar": "Visibility", "check": "CloudTrail",
                             "status": "PASS", "detail": f"{len(trails)} trail(s) configured"})
        else:
            findings.append({"pillar": "Visibility", "check": "CloudTrail",
                             "status": "FAIL", "severity": "CRITICAL",
                             "detail": "No CloudTrail trails configured"})
    except ClientError as e:
        findings.append({"pillar": "Visibility", "status": "ERROR", "detail": str(e)})

    return findings


def generate_zero_trust_scorecard(findings):
    """Generate a zero trust maturity scorecard from findings."""
    pillar_scores = {}
    for f in findings:
        pillar = f.get("pillar", "Unknown")
        if pillar not in pillar_scores:
            pillar_scores[pillar] = {"pass": 0, "fail": 0, "error": 0}
        status = f.get("status", "ERROR")
        if status == "PASS":
            pillar_scores[pillar]["pass"] += 1
        elif status == "FAIL":
            pillar_scores[pillar]["fail"] += 1
        else:
            pillar_scores[pillar]["error"] += 1

    scorecard = {}
    for pillar, counts in pillar_scores.items():
        total = counts["pass"] + counts["fail"]
        score = round(counts["pass"] / max(total, 1) * 100, 1)
        maturity = "Advanced" if score >= 80 else "Initial" if score >= 50 else "Traditional"
        scorecard[pillar] = {"score": score, "maturity": maturity,
                             "passed": counts["pass"], "failed": counts["fail"]}
    return scorecard


def run_zero_trust_assessment(region="us-east-1"):
    """Run comprehensive zero trust assessment."""
    print(f"\n{'='*60}")
    print(f"  ZERO TRUST CLOUD ARCHITECTURE ASSESSMENT")
    print(f"  Generated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC")
    print(f"{'='*60}\n")

    print(f"--- ZERO TRUST PILLARS ---")
    for p in ZERO_TRUST_PILLARS:
        print(f"  {p['pillar']}: {p['description']}")
        for c in p["checks"]:
            print(f"    - {c}")

    print(f"\n--- AWS ASSESSMENT (region: {region}) ---")
    findings = assess_aws_zero_trust(region)

    pass_count = sum(1 for f in findings if f.get("status") == "PASS")
    fail_count = sum(1 for f in findings if f.get("status") == "FAIL")
    print(f"  Total checks: {len(findings)}")
    print(f"  Passed: {pass_count} | Failed: {fail_count}")

    critical = [f for f in findings if f.get("severity") == "CRITICAL"]
    high = [f for f in findings if f.get("severity") == "HIGH"]
    if critical:
        print(f"\n  CRITICAL FINDINGS ({len(critical)}):")
        for f in critical:
            print(f"    [{f['pillar']}] {f.get('check', 'N/A')}: {f['detail']}")
    if high:
        print(f"\n  HIGH FINDINGS ({len(high)}):")
        for f in high[:10]:
            print(f"    [{f['pillar']}] {f.get('check', 'N/A')}: {f['detail']}")

    scorecard = generate_zero_trust_scorecard(findings)
    print(f"\n--- ZERO TRUST SCORECARD ---")
    for pillar, scores in scorecard.items():
        bar = "#" * int(scores["score"] / 5)
        print(f"  {pillar:<15} {scores['score']:>5.1f}% [{scores['maturity']}] {bar}")

    overall = round(sum(s["score"] for s in scorecard.values()) / max(len(scorecard), 1), 1)
    print(f"\n  OVERALL ZERO TRUST MATURITY: {overall}%")
    maturity = "Advanced" if overall >= 80 else "Initial" if overall >= 50 else "Traditional"
    print(f"  Maturity Level: {maturity}")

    print(f"\n{'='*60}\n")
    return {"findings": findings, "scorecard": scorecard, "overall_score": overall}


def main():
    parser = argparse.ArgumentParser(description="Zero Trust Cloud Architecture Agent")
    parser.add_argument("--region", default="us-east-1", help="AWS region")
    parser.add_argument("--assess", action="store_true", help="Run zero trust assessment")
    parser.add_argument("--pillars", action="store_true", help="Show zero trust pillars")
    parser.add_argument("--output", help="Save report to JSON")
    args = parser.parse_args()

    if args.pillars:
        for p in ZERO_TRUST_PILLARS:
            print(f"\n{p['pillar']}: {p['description']}")
            for c in p["checks"]:
                print(f"  - {c}")
    elif args.assess:
        report = run_zero_trust_assessment(args.region)
        if args.output:
            with open(args.output, "w") as f:
                json.dump(report, f, indent=2, default=str)
            print(f"[+] Report saved to {args.output}")
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
