from datetime import datetime

from rich.console import Console
from rich.panel import Panel
from rich.rule import Rule
from rich.table import Table
from rich.text import Text

console = Console()

CATEGORY_NAMES = {
    1: "DNS Compromise",
    2: "DNS Poisoning",
    3: "Fraud Orders",
    4: "DDoS Attack",
    5: "FTP Brute-Force",
    6: "Ping of Death",
    7: "Phishing",
    8: "Fraud VoIP",
    9: "Open Proxy",
    10: "Web Spam",
    11: "Comment Spam",
    12: "Blog Spam",
    13: "VPN IP",
    14: "Port Scan",
    15: "Hacking",
    16: "SQL Injection",
    17: "Spoofing",
    18: "Brute-Force",
    19: "Bad Web Bot",
    20: "Exploited Host",
    21: "Web App Attack",
    22: "SSH",
    23: "IoT Targeted",
}


def get_confidence_color(score: int) -> str:
    if score >= 80:
        return "red"
    elif score >= 50:
        return "yellow"
    elif score >= 25:
        return "bright_black"
    return "green"


def format_confidence_score(score: int) -> Text:
    color = get_confidence_color(score)
    return Text(f"{score}%", style=color)


def print_ip_details(data: dict):
    ip_data = data.get("data", {})

    confidence = ip_data.get("abuseConfidenceScore", 0)
    score_text = format_confidence_score(confidence)

    info_table = Table(show_header=False, box=None, padding=(0, 1))
    info_table.add_column("Key", style="bold cyan")
    info_table.add_column("Value")

    info_table.add_row("IP Address", ip_data.get("ipAddress", "N/A"))
    info_table.add_row("Confidence Score", str(score_text))
    info_table.add_row(
        "Country",
        f"{ip_data.get('countryCode', 'N/A')} ({ip_data.get('countryName', 'N/A')})",
    )
    info_table.add_row("ISP", ip_data.get("isp", "N/A"))
    info_table.add_row("Domain", ip_data.get("domain", "N/A"))
    info_table.add_row("Usage Type", ip_data.get("usageType", "N/A"))
    info_table.add_row("Total Reports", str(ip_data.get("totalReports", 0)))
    info_table.add_row("Distinct Users", str(ip_data.get("numDistinctUsers", 0)))
    info_table.add_row("Public", "Yes" if ip_data.get("isPublic") else "No")
    info_table.add_row("Whitelisted", "Yes" if ip_data.get("isWhitelisted") else "No")
    info_table.add_row("Tor", "Yes" if ip_data.get("isTor") else "No")

    if ip_data.get("lastReportedAt"):
        info_table.add_row("Last Reported", ip_data.get("lastReportedAt"))

    console.print(
        Panel(info_table, title="[bold]IP Information[/bold]", border_style="cyan")
    )

    if "reports" in ip_data and ip_data["reports"]:
        console.print()
        console.print(Rule("[bold]Recent Reports[/bold]"))

        reports_table = Table(show_header=True, header_style="bold magenta")
        reports_table.add_column("Date", style="dim")
        reports_table.add_column("Categories")
        reports_table.add_column("Reporter Country")
        reports_table.add_column("Comment", max_width=60)

        for report in ip_data["reports"][:10]:
            categories = ", ".join(
                CATEGORY_NAMES.get(c, str(c)) for c in report.get("categories", [])
            )
            reports_table.add_row(
                report.get("reportedAt", "").split("T")[0],
                categories,
                report.get("reporterCountryCode", "N/A"),
                report.get("comment", "")[:60],
            )

        console.print(reports_table)


def print_block_details(data: dict):
    block_data = data.get("data", {})

    info_table = Table(show_header=False, box=None)
    info_table.add_column("Key", style="bold cyan")
    info_table.add_column("Value")

    info_table.add_row("Network", block_data.get("networkAddress", ""))
    info_table.add_row("Netmask", block_data.get("netmask", ""))
    info_table.add_row(
        "Address Range",
        f"{block_data.get('minAddress', '')} - {block_data.get('maxAddress', '')}",
    )
    info_table.add_row("Possible Hosts", str(block_data.get("numPossibleHosts", 0)))
    info_table.add_row("Description", block_data.get("addressSpaceDesc", "N/A"))

    console.print(
        Panel(info_table, title="[bold]Block Information[/bold]", border_style="cyan")
    )

    if "reportedAddress" in block_data:
        console.print()
        console.print(Rule("[bold]Reported Addresses[/bold]"))

        table = Table(show_header=True, header_style="bold magenta")
        table.add_column("IP Address", style="cyan")
        table.add_column("Reports", justify="right")
        table.add_column("Confidence", justify="center")
        table.add_column("Last Reported", style="dim")

        for addr in block_data["reportedAddress"][:20]:
            score = addr.get("abuseConfidenceScore", 0)
            table.add_row(
                addr.get("ipAddress", ""),
                str(addr.get("numReports", 0)),
                format_confidence_score(score),
                addr.get("mostRecentReport", "").split("T")[0],
            )

        console.print(table)


def print_blacklist(data: dict):
    meta = data.get("meta", {})
    blacklist_data = data.get("data", [])

    if meta.get("generatedAt"):
        console.print(f"[dim]Generated: {meta['generatedAt']}[/dim]\n")

    table = Table(show_header=True, header_style="bold magenta")
    table.add_column("IP Address", style="cyan")
    table.add_column("Confidence", justify="center")
    table.add_column("Last Reported", style="dim")
    table.add_column("Country", justify="center")

    for entry in blacklist_data:
        score = entry.get("abuseConfidenceScore", 0)
        table.add_row(
            entry.get("ipAddress", ""),
            format_confidence_score(score),
            entry.get("lastReportedAt", "").split("T")[0]
            if entry.get("lastReportedAt")
            else "N/A",
            entry.get("countryCode", "N/A"),
        )

    console.print(table)


def print_report_result(data: dict):
    result_data = data.get("data", {})
    ip_addr = result_data.get("ipAddress", "")
    confidence = result_data.get("abuseConfidenceScore", 0)

    console.print(f"[green]Successfully reported {ip_addr}[/green]")
    console.print(f"Abuse Confidence Score: {format_confidence_score(confidence)}")


def print_error(error: str):
    console.print(f"[bold red]Error:[/bold red] {error}")
