"""
AIPTX Key Validation - AI Thinking Display
===========================================

Professional terminal display for AI reasoning during key detection
and validation. Shows live vulnerability context and key analysis.
"""

from __future__ import annotations

import sys
import time
from dataclasses import dataclass
from typing import Optional, Any

from .base import APIKeyInfo, ValidationResult, RiskLevel, KeyType


# ANSI Color codes and styles
class Style:
    # Reset
    RESET = "\033[0m"
    BOLD = "\033[1m"
    DIM = "\033[2m"
    ITALIC = "\033[3m"
    UNDERLINE = "\033[4m"
    BLINK = "\033[5m"

    # Colors
    BLACK = "\033[30m"
    RED = "\033[31m"
    GREEN = "\033[32m"
    YELLOW = "\033[33m"
    BLUE = "\033[34m"
    MAGENTA = "\033[35m"
    CYAN = "\033[36m"
    WHITE = "\033[37m"

    # Bright colors
    BRIGHT_BLACK = "\033[90m"
    BRIGHT_RED = "\033[91m"
    BRIGHT_GREEN = "\033[92m"
    BRIGHT_YELLOW = "\033[93m"
    BRIGHT_BLUE = "\033[94m"
    BRIGHT_MAGENTA = "\033[95m"
    BRIGHT_CYAN = "\033[96m"
    BRIGHT_WHITE = "\033[97m"

    # Background colors
    BG_RED = "\033[41m"
    BG_GREEN = "\033[42m"
    BG_YELLOW = "\033[43m"
    BG_BLUE = "\033[44m"
    BG_MAGENTA = "\033[45m"
    BG_CYAN = "\033[46m"


# Box drawing characters
class Box:
    H = "─"  # Horizontal
    V = "│"  # Vertical
    TL = "╭"  # Top-left corner
    TR = "╮"  # Top-right corner
    BL = "╰"  # Bottom-left corner
    BR = "╯"  # Bottom-right corner
    LT = "├"  # Left T
    RT = "┤"  # Right T
    TT = "┬"  # Top T
    BT = "┴"  # Bottom T
    CROSS = "┼"


# Icons
class Icons:
    BRAIN = "🧠"
    KEY = "🔑"
    LOCK = "🔒"
    UNLOCK = "🔓"
    CHECK = "✓"
    CROSS = "✗"
    WARNING = "⚠"
    FIRE = "🔥"
    SHIELD = "🛡"
    TARGET = "🎯"
    CHART = "📊"
    LIGHTNING = "⚡"
    ARROW = "→"
    DOT = "•"
    SPARK = "✦"


class KeyValidationThinking:
    """
    Professional AI thinking display for key validation.

    Creates visually appealing terminal output showing the AI's
    analysis process during key detection and validation.
    """

    WIDTH = 60  # Box width

    def __init__(self, enabled: bool = True, output_stream=None):
        self.enabled = enabled
        self.output = output_stream or sys.stdout

    def _print(self, text: str) -> None:
        """Print text to output stream."""
        if self.enabled:
            print(text, file=self.output, flush=True)

    def _box_line(self, left: str, content: str, right: str, width: int = None) -> str:
        """Create a box line with content."""
        w = width or self.WIDTH
        padding = w - 2 - len(self._strip_ansi(content))
        return f"{left}{content}{' ' * max(0, padding)}{right}"

    def _strip_ansi(self, text: str) -> str:
        """Remove ANSI codes for length calculation."""
        import re
        return re.sub(r'\033\[[0-9;]*m', '', text)

    def _header_box(self, icon: str, title: str, color: str = Style.BRIGHT_CYAN) -> str:
        """Create a header box."""
        w = self.WIDTH
        title_line = f" {icon} {title} "
        padding_total = w - 2 - len(title_line)
        left_pad = padding_total // 2
        right_pad = padding_total - left_pad

        lines = [
            f"{color}{Box.TL}{Box.H * (w - 2)}{Box.TR}{Style.RESET}",
            f"{color}{Box.V}{Style.RESET}{' ' * left_pad}{Style.BOLD}{title_line}{Style.RESET}{' ' * right_pad}{color}{Box.V}{Style.RESET}",
            f"{color}{Box.LT}{Box.H * (w - 2)}{Box.RT}{Style.RESET}",
        ]
        return "\n".join(lines)

    def _content_line(self, label: str, value: str, color: str = Style.BRIGHT_CYAN, icon: str = Icons.DOT) -> str:
        """Create a content line within the box."""
        content = f" {icon} {label}: {Style.BOLD}{value}{Style.RESET}"
        return f"{color}{Box.V}{Style.RESET}{content}{' ' * max(0, self.WIDTH - 2 - len(self._strip_ansi(content)))}{color}{Box.V}{Style.RESET}"

    def _footer_box(self, color: str = Style.BRIGHT_CYAN) -> str:
        """Create a footer box line."""
        return f"{color}{Box.BL}{Box.H * (self.WIDTH - 2)}{Box.BR}{Style.RESET}"

    # ==================== Key Detection Display ====================

    def think_key_detection(
        self,
        vuln_type: str,
        vuln_title: str = "",
        target_url: str = "",
        severity: str = "",
        evidence_preview: str = "",
    ) -> None:
        """
        Display AI analysis when detecting keys from a finding.

        Shows the vulnerability context being analyzed.
        """
        # Clean up the vuln_type display
        vuln_display = vuln_title or vuln_type.replace("_", " ").title()
        if vuln_display == "Unknown":
            return  # Don't show for unknown types

        severity_colors = {
            "critical": Style.BRIGHT_RED,
            "high": Style.RED,
            "medium": Style.YELLOW,
            "low": Style.BLUE,
            "info": Style.DIM,
        }
        sev_color = severity_colors.get(severity.lower(), Style.WHITE)

        self._print("")
        self._print(self._header_box(Icons.BRAIN, "AI KEY ANALYSIS", Style.BRIGHT_CYAN))
        self._print(self._content_line("Analyzing", vuln_display, icon=Icons.TARGET))

        if severity:
            sev_display = f"{sev_color}{severity.upper()}{Style.RESET}"
            self._print(self._content_line("Severity", sev_display, icon=Icons.WARNING))

        if target_url:
            # Truncate long URLs
            url_display = target_url[:40] + "..." if len(target_url) > 43 else target_url
            self._print(self._content_line("Location", url_display, icon=Icons.ARROW))

        if evidence_preview:
            # Show first 35 chars of evidence
            preview = evidence_preview[:35].replace("\n", " ").strip()
            if len(evidence_preview) > 35:
                preview += "..."
            self._print(self._content_line("Evidence", f'"{preview}"', icon=Icons.SPARK))

        self._print(self._content_line("Action", "Scanning for exposed credentials", icon=Icons.LIGHTNING))
        self._print(self._footer_box())
        self._print("")

    def think_key_found(self, key_info: APIKeyInfo) -> None:
        """Display when a key is detected."""
        key_type = key_info.key_type.value.upper()
        confidence = int(key_info.confidence * 100)

        # Confidence color
        if confidence >= 90:
            conf_color = Style.BRIGHT_GREEN
        elif confidence >= 70:
            conf_color = Style.YELLOW
        else:
            conf_color = Style.DIM

        self._print("")
        self._print(self._header_box(Icons.KEY, f"{key_type} KEY DETECTED", Style.BRIGHT_GREEN))
        self._print(self._content_line("Type", key_type, Style.BRIGHT_GREEN, Icons.KEY))
        self._print(self._content_line("Value", key_info.masked_value, Style.BRIGHT_GREEN, Icons.LOCK))
        self._print(self._content_line("Confidence", f"{conf_color}{confidence}%{Style.RESET}", Style.BRIGHT_GREEN, Icons.CHART))

        if key_info.detected_pattern:
            self._print(self._content_line("Pattern", key_info.detected_pattern, Style.BRIGHT_GREEN, Icons.TARGET))

        self._print(self._content_line("Status", "Queued for validation", Style.BRIGHT_GREEN, Icons.ARROW))
        self._print(self._footer_box(Style.BRIGHT_GREEN))
        self._print("")

    def think_validation_start(self, key_info: APIKeyInfo) -> None:
        """Display when starting validation."""
        key_type = key_info.key_type.value.upper()
        endpoint = self._get_validation_endpoint(key_info.key_type)

        self._print("")
        self._print(self._header_box(Icons.LIGHTNING, f"VALIDATING {key_type}", Style.BRIGHT_YELLOW))
        self._print(self._content_line("Endpoint", endpoint, Style.BRIGHT_YELLOW, Icons.ARROW))
        self._print(self._content_line("Method", "API authentication test", Style.BRIGHT_YELLOW, Icons.TARGET))
        self._print(self._footer_box(Style.BRIGHT_YELLOW))

    def think_validation_result(self, result: ValidationResult) -> None:
        """Display validation result."""
        if result.is_valid:
            self._display_valid_key(result)
        else:
            self._display_invalid_key(result)

    def _display_valid_key(self, result: ValidationResult) -> None:
        """Display a valid key result."""
        key_type = result.key_info.key_type.value.upper()

        risk_display = {
            RiskLevel.CRITICAL: (f"{Style.BG_RED}{Style.BOLD} CRITICAL {Style.RESET}", Style.BRIGHT_RED, Icons.FIRE),
            RiskLevel.HIGH: (f"{Style.BRIGHT_RED}HIGH{Style.RESET}", Style.RED, Icons.WARNING),
            RiskLevel.MEDIUM: (f"{Style.YELLOW}MEDIUM{Style.RESET}", Style.YELLOW, Icons.WARNING),
            RiskLevel.LOW: (f"{Style.BLUE}LOW{Style.RESET}", Style.BLUE, Icons.SHIELD),
            RiskLevel.INFO: (f"{Style.DIM}INFO{Style.RESET}", Style.DIM, Icons.DOT),
        }

        risk_text, color, risk_icon = risk_display.get(
            result.risk_level,
            (result.risk_level.value.upper(), Style.WHITE, Icons.DOT)
        )

        # Extract identity
        identity = (
            result.identity_info.get("user") or
            result.identity_info.get("login") or
            result.identity_info.get("email") or
            result.identity_info.get("account_id") or
            result.identity_info.get("name") or
            "Authenticated"
        )

        self._print("")
        self._print(self._header_box(Icons.UNLOCK, f"{key_type} KEY VALID", Style.BRIGHT_GREEN))
        self._print(self._content_line("Identity", str(identity)[:40], Style.BRIGHT_GREEN, Icons.CHECK))

        account = result.identity_info.get("account") or result.identity_info.get("team") or result.identity_info.get("org")
        if account:
            self._print(self._content_line("Account", str(account)[:40], Style.BRIGHT_GREEN, Icons.TARGET))

        self._print(self._content_line("Permissions", f"{len(result.permissions)} discovered", Style.BRIGHT_GREEN, Icons.KEY))
        self._print(self._content_line("Resources", f"{len(result.resources_accessible)} accessible", Style.BRIGHT_GREEN, Icons.CHART))
        self._print(self._content_line("Risk Level", risk_text, Style.BRIGHT_GREEN, risk_icon))

        if result.exploitation_potential:
            self._print(self._content_line("Exploit", result.exploitation_potential[:40], Style.BRIGHT_GREEN, Icons.FIRE))

        self._print(self._footer_box(Style.BRIGHT_GREEN))

        # Show permissions if critical/high risk
        if result.permissions and result.risk_level in [RiskLevel.CRITICAL, RiskLevel.HIGH]:
            self._print(f"  {Style.DIM}Permissions: {', '.join(result.permissions[:5])}{Style.RESET}")

        self._print("")

    def _display_invalid_key(self, result: ValidationResult) -> None:
        """Display an invalid key result."""
        key_type = result.key_info.key_type.value.upper()

        self._print("")
        self._print(self._header_box(Icons.CROSS, f"{key_type} KEY INVALID", Style.BRIGHT_YELLOW))
        self._print(self._content_line("Status", "Authentication failed", Style.BRIGHT_YELLOW, Icons.CROSS))

        if result.error:
            error_display = result.error[:45] if len(result.error) > 45 else result.error
            self._print(self._content_line("Reason", error_display, Style.BRIGHT_YELLOW, Icons.WARNING))

        self._print(self._content_line("Action", "Skipping exploitation", Style.BRIGHT_YELLOW, Icons.ARROW))
        self._print(self._footer_box(Style.BRIGHT_YELLOW))
        self._print("")

    def think_risk_assessment(
        self,
        risk_level: RiskLevel,
        exploitation_potential: str,
        attack_vectors: list[str],
    ) -> None:
        """Display risk assessment."""
        risk_colors = {
            RiskLevel.CRITICAL: Style.BRIGHT_RED,
            RiskLevel.HIGH: Style.RED,
            RiskLevel.MEDIUM: Style.YELLOW,
            RiskLevel.LOW: Style.BLUE,
            RiskLevel.INFO: Style.DIM,
        }

        color = risk_colors.get(risk_level, Style.WHITE)

        self._print("")
        self._print(self._header_box(Icons.SHIELD, "RISK ASSESSMENT", color))
        self._print(self._content_line("Risk", f"{color}{risk_level.value.upper()}{Style.RESET}", color, Icons.WARNING))

        if exploitation_potential:
            self._print(self._content_line("Impact", exploitation_potential[:40], color, Icons.FIRE))

        self._print(self._content_line("Vectors", f"{len(attack_vectors)} identified", color, Icons.TARGET))
        self._print(self._footer_box(color))

        # Show attack vectors
        if attack_vectors:
            for vector in attack_vectors[:3]:
                self._print(f"  {Style.DIM}{Icons.ARROW} {vector}{Style.RESET}")

        self._print("")

    def think_batch_summary(
        self,
        total_keys: int,
        valid_keys: int,
        by_risk: dict[RiskLevel, int],
    ) -> None:
        """Display summary after batch validation."""
        critical = by_risk.get(RiskLevel.CRITICAL, 0)
        high = by_risk.get(RiskLevel.HIGH, 0)

        # Choose color based on severity
        if critical > 0:
            color = Style.BRIGHT_RED
        elif high > 0:
            color = Style.RED
        elif valid_keys > 0:
            color = Style.BRIGHT_GREEN
        else:
            color = Style.BRIGHT_CYAN

        self._print("")
        self._print(f"{color}{'═' * self.WIDTH}{Style.RESET}")
        self._print(self._header_box(Icons.CHART, "KEY VALIDATION SUMMARY", color))

        self._print(self._content_line("Total Detected", str(total_keys), color, Icons.KEY))
        self._print(self._content_line("Valid Keys", f"{Style.BRIGHT_GREEN}{valid_keys}{Style.RESET}", color, Icons.CHECK))
        self._print(self._content_line("Invalid", str(total_keys - valid_keys), color, Icons.CROSS))

        # Risk breakdown
        self._print(f"{color}{Box.V}{Style.RESET} {Icons.DOT} Risk Breakdown:{' ' * (self.WIDTH - 21)}{color}{Box.V}{Style.RESET}")

        if critical > 0:
            self._print(f"{color}{Box.V}{Style.RESET}   {Style.BRIGHT_RED}{Icons.FIRE} Critical: {critical}{Style.RESET}{' ' * (self.WIDTH - 20 - len(str(critical)))}{color}{Box.V}{Style.RESET}")
        if high > 0:
            self._print(f"{color}{Box.V}{Style.RESET}   {Style.RED}{Icons.WARNING} High: {high}{Style.RESET}{' ' * (self.WIDTH - 15 - len(str(high)))}{color}{Box.V}{Style.RESET}")
        if by_risk.get(RiskLevel.MEDIUM, 0) > 0:
            med = by_risk[RiskLevel.MEDIUM]
            self._print(f"{color}{Box.V}{Style.RESET}   {Style.YELLOW}{Icons.DOT} Medium: {med}{Style.RESET}{' ' * (self.WIDTH - 17 - len(str(med)))}{color}{Box.V}{Style.RESET}")
        if by_risk.get(RiskLevel.LOW, 0) > 0:
            low = by_risk[RiskLevel.LOW]
            self._print(f"{color}{Box.V}{Style.RESET}   {Style.BLUE}{Icons.SHIELD} Low: {low}{Style.RESET}{' ' * (self.WIDTH - 14 - len(str(low)))}{color}{Box.V}{Style.RESET}")

        self._print(self._footer_box(color))
        self._print(f"{color}{'═' * self.WIDTH}{Style.RESET}")
        self._print("")

    def think_scan_start(self, target: str, finding_count: int) -> None:
        """Display when starting a key scan."""
        if finding_count == 0:
            return

        self._print("")
        self._print(self._header_box(Icons.BRAIN, "STARTING KEY ANALYSIS", Style.BRIGHT_CYAN))
        self._print(self._content_line("Target", target[:45], icon=Icons.TARGET))
        self._print(self._content_line("Findings", str(finding_count), icon=Icons.CHART))
        self._print(self._content_line("Scanning for", "API keys, tokens, credentials", icon=Icons.KEY))
        self._print(self._footer_box())
        self._print("")

    def _get_validation_endpoint(self, key_type: KeyType) -> str:
        """Get the validation endpoint for a key type."""
        endpoints = {
            KeyType.AWS: "sts.amazonaws.com",
            KeyType.GCP: "oauth2.googleapis.com",
            KeyType.AZURE: "login.microsoftonline.com",
            KeyType.GITHUB: "api.github.com/user",
            KeyType.GITLAB: "gitlab.com/api/v4/user",
            KeyType.SLACK: "slack.com/api/auth.test",
            KeyType.STRIPE: "api.stripe.com/v1/balance",
            KeyType.TWILIO: "api.twilio.com",
            KeyType.SENDGRID: "api.sendgrid.com/v3/user/profile",
            KeyType.ATLASSIAN: "atlassian.net/rest/api/3/myself",
        }
        return endpoints.get(key_type, "API endpoint")


# ==================== Global Instance ====================

_thinking_instance: Optional[KeyValidationThinking] = None


def get_thinking(enabled: bool = True) -> KeyValidationThinking:
    """Get or create global thinking instance."""
    global _thinking_instance
    if _thinking_instance is None:
        _thinking_instance = KeyValidationThinking(enabled=enabled)
    return _thinking_instance


def set_thinking_enabled(enabled: bool) -> None:
    """Enable or disable thinking display globally."""
    global _thinking_instance
    if _thinking_instance:
        _thinking_instance.enabled = enabled
    else:
        _thinking_instance = KeyValidationThinking(enabled=enabled)
