"""Nazar Interactive Shell - Claude Code benzeri interaktif terminal arayuzu."""
import os
import sys
import re
import time
from pathlib import Path

from prompt_toolkit import PromptSession
from prompt_toolkit.completion import Completer, Completion, PathCompleter
from prompt_toolkit.history import FileHistory
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.styles import Style

from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.syntax import Syntax
from rich.text import Text
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
from rich import box


BANNER = """[bold cyan]
  ███╗   ██╗ █████╗ ███████╗ █████╗ ██████╗
  ████╗  ██║██╔══██╗╚══███╔╝██╔══██╗██╔══██╗
  ██╔██╗ ██║███████║  ███╔╝ ███████║██████╔╝
  ██║╚██╗██║██╔══██║ ███╔╝  ██╔══██║██╔══██╗
  ██║ ╚████║██║  ██║███████╗██║  ██║██║  ██║
  ╚═╝  ╚═══╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝[/bold cyan]
  [dim]Otonom Guvenlik & Kalite Tarayici[/dim]
"""

HELP_TEXT = """
[bold]BASLANGIC:[/bold]
  Projenizin yolunu yazin, Nazar gerisini halleder:
  [green]nazar> ~/Desktop/MyProject[/green]

[bold]TARAMA:[/bold]
  [cyan]/scan <yol>[/cyan]         Projeyi tara ve analiz et

[bold]SONUCLARI INCELE:[/bold]
  [cyan]/report[/cyan]             Basarisiz testleri goster
  [cyan]/report failed[/cyan]      Sadece basarisizlari goster
  [cyan]/report security[/cyan]    Sadece guvenlik sonuclarini goster
  [cyan]/report appstore[/cyan]    Sadece App Store sonuclarini goster
  [cyan]/detail <no>[/cyan]        Testin detayini + sorunlu kodu goster
  [cyan]/guide <no>[/cyan]         Adim adim duzeltme rehberi

[bold]CIKTI:[/bold]
  [cyan]/export html[/cyan]        Interaktif HTML rapor olustur
  [cyan]/export json[/cyan]        JSON cikti (CI/CD icin)
  [cyan]/export sarif[/cyan]       GitHub Code Scanning formati

[bold]BILGI:[/bold]
  [cyan]/categories[/cyan]         22 kategori ve kontrol sayilari
  [cyan]/stats[/cyan]              Genel istatistikler
  [cyan]/update[/cyan]             Nazar'i son versiyona guncelle
  [cyan]/clear[/cyan]              Ekrani temizle
  [cyan]/quit[/cyan]               Cikis

[bold]IPUCLARI:[/bold]
  [dim]Tab[/dim]                  Komut ve dosya yolu otomatik tamamlama
  [dim]Yukari/Asagi ok[/dim]      Onceki komutlari geri cagirma
  [dim]Ctrl+C[/dim]               Islemi iptal et
"""


class NazarCompleter(Completer):
    COMMANDS = ["/scan", "/report", "/detail", "/guide", "/export", "/categories", "/stats", "/clear", "/update", "/help", "/quit"]
    FILTERS = ["failed", "passed", "all", "security", "appstore", "code_quality", "ux_text", "ui_component", "cross_file"]
    FORMATS = ["html", "json", "sarif", "junit", "markdown"]

    def __init__(self):
        self.path_completer = PathCompleter(expanduser=True)

    def get_completions(self, document, complete_event):
        text = document.text_before_cursor.strip()
        if text.startswith("/report "):
            sub = text.split(" ", 1)[1]
            for f in self.FILTERS:
                if f.startswith(sub):
                    yield Completion(f, start_position=-len(sub))
        elif text.startswith("/export "):
            sub = text.split(" ", 1)[1]
            for f in self.FORMATS:
                if f.startswith(sub):
                    yield Completion(f, start_position=-len(sub))
        elif text.startswith("/"):
            for cmd in self.COMMANDS:
                if cmd.startswith(text):
                    yield Completion(cmd, start_position=-len(text))
        else:
            yield from self.path_completer.get_completions(document, complete_event)


def _grade(rate):
    for min_r, g in [(97,"A+"),(93,"A"),(90,"A-"),(87,"B+"),(83,"B"),(80,"B-"),(77,"C+"),(73,"C"),(70,"C-"),(67,"D+"),(63,"D"),(60,"D-"),(0,"F")]:
        if rate >= min_r:
            return g
    return "F"


class NazarShell:
    def __init__(self):
        self.console = Console()
        history_dir = Path.home() / ".nazar"
        history_dir.mkdir(exist_ok=True)
        self.session = PromptSession(
            history=FileHistory(str(history_dir / "history")),
            completer=NazarCompleter(),
        )
        self.results = None
        self.plan_data = None
        self.project_path = None

    def _show_header(self, welcome=False):
        """Ekrani temizle ve banner goster (responsive)."""
        import subprocess
        subprocess.run(['clear'], check=False)
        from nazar import __version__
        width = self.console.width or 80

        if width >= 60:
            self.console.print(BANNER)
        else:
            self.console.print("[bold cyan]  NAZAR[/bold cyan]")
            self.console.print(f"  [dim]Otonom Guvenlik & Kalite Tarayici[/dim]")

        if width >= 80:
            self.console.print(f"  [dim]v{__version__}[/dim]  |  [bold]180+[/bold] kontrol  |  [bold]29[/bold] kategori  |  [bold]15+[/bold] framework  |  [bold]87[/bold] rehber")
        else:
            self.console.print(f"  [dim]v{__version__}[/dim] | [bold]180+[/bold] kontrol | [bold]29[/bold] kategori")

        if welcome:
            self._check_update_on_start()
            self.console.print()
            self.console.print("  [green]Taramak istediginiz projenin yolunu yazin:[/green]")
            self.console.print("  [dim]Ornek: ~/Desktop/MyProject | /help[/dim]")
        self.console.print()

    def run(self):
        self._show_header(welcome=True)
        while True:
            try:
                text = self.session.prompt(HTML('<style fg="#6366f1"><b>nazar</b></style><style fg="#475569">&gt; </style>'))
                text = text.strip()
                if not text:
                    continue
                self._show_header()
                self._handle(text)
            except KeyboardInterrupt:
                self.console.print("\n[dim]Iptal edildi.[/dim]")
            except EOFError:
                self.console.print("\n[dim]Gorusuruz![/dim]")
                break

    def _handle(self, text):
        if text.startswith("/"):
            parts = text.split(None, 1)
            cmd, arg = parts[0].lower(), parts[1] if len(parts) > 1 else ""
            cmds = {"/scan": lambda: self._scan(arg), "/report": lambda: self._report(arg), "/detail": lambda: self._detail(arg), "/guide": lambda: self._guide(arg), "/export": lambda: self._export(arg), "/categories": self._categories, "/stats": self._stats, "/clear": self._clear, "/update": self._update, "/help": lambda: self.console.print(HELP_TEXT), "/quit": lambda: sys.exit(0), "/exit": lambda: sys.exit(0)}
            fn = cmds.get(cmd)
            if fn:
                fn()
            else:
                self.console.print(f"\n[red]  Bilinmeyen komut: {cmd}[/red]")
                self.console.print("[dim]  /help ile tum komutlari gorebilirsiniz.[/dim]\n")
        elif text in (".", "./"):
            self.console.print("\n[yellow]  Mevcut dizini taramak yerine proje yolunu belirtin.[/yellow]")
            self.console.print("[dim]  Ornek: ~/Desktop/MyProject[/dim]\n")
        elif os.path.exists(os.path.expanduser(text)) or text.startswith("/") or text.startswith("~"):
            self._scan(text)
        else:
            self.console.print(f"\n[dim]  '{text}' bulunamadi. Gecerli bir proje yolu veya /help yazin.[/dim]\n")

    def _scan(self, path_str):
        if not path_str:
            self.console.print("\n[yellow]  Hangi projeyi taramak istiyorsunuz?[/yellow]")
            self.console.print("[dim]  Ornek: /scan ~/Desktop/MyProject[/dim]")
            self.console.print("[dim]  Veya direkt dosya yolunu yazin: ~/Desktop/MyProject[/dim]\n")
            return
        # Path duzeltmeleri
        expanded = os.path.expanduser(path_str)
        # /desktop/x -> /Users/kullanici/Desktop/x otomatik cevir
        if expanded.lower().startswith("/desktop/"):
            expanded = os.path.expanduser("~/Desktop/" + expanded[9:])
        elif expanded.lower().startswith("desktop/"):
            expanded = os.path.expanduser("~/Desktop/" + expanded[8:])
        path = Path(expanded).resolve()
        if not path.exists():
            self.console.print(f"\n[red]  Yol bulunamadi: {path}[/red]")
            self.console.print("[dim]  Dosya yolunu kontrol edin. Tab ile otomatik tamamlama kullanabilirsiniz.[/dim]\n")
            return

        # Proje dizini teyidi
        verified = self._verify_project_path(path)
        if verified is None:
            return  # kullanici iptal etti
        path = verified

        self.project_path = str(path)
        start_time = time.time()

        from nazar.scanner.project_scanner import ProjectScanner
        from nazar.planner.test_planner import TestPlanner
        from nazar.runners.orchestrator import TestOrchestrator
        from nazar.cache.scan_cache import ScanCache
        from rich.live import Live

        # Faz 0: Hizli on-analiz - proje tipini goster
        scan_start = time.time()
        scanner = ProjectScanner(self.project_path)

        # Proje tipini hizlica tespit et (sadece tech_stack)
        scanner._detect_tech_stack()
        tech = scanner.result.tech_stack
        proj_name = path.name

        self.console.print(f"\n  [bold]{proj_name}[/bold] [dim]({tech})[/dim]")

        # Onceki tarama var mi?
        cache = ScanCache(self.project_path)
        prev = cache.get_last_scan_summary()
        if prev:
            self.console.print(f"  [dim]Onceki tarama: {prev['grade']} ({prev['pass_rate']}%) - {cache.time_since_last_scan()}[/dim]")

        # Profil secim menusu
        profile = self._select_profile(tech, prev)
        if profile is None:
            return

        def _scan_with_live():
            """Tarama sirasinda canli dosya gosterimi."""
            import threading
            result_holder = [None]
            done = threading.Event()

            def do_scan():
                result_holder[0] = scanner.scan()
                done.set()

            t = threading.Thread(target=do_scan, daemon=True)
            t.start()

            dots = ["   ", ".  ", ".. ", "..."]
            idx = 0
            with Live(console=self.console, refresh_per_second=4, transient=True) as live:
                while not done.is_set():
                    elapsed = time.time() - scan_start
                    file_count = len(scanner.result.source_files) if hasattr(scanner, 'result') else 0
                    tech = scanner.result.tech_stack if hasattr(scanner, 'result') and scanner.result.tech_stack != "unknown" else ""
                    idx += 1

                    tech_str = f" | {tech}" if tech else ""
                    anim = dots[idx % len(dots)]
                    panel_content = (
                        f"  [bold cyan]1/3[/bold cyan] Proje taraniyor{anim}\n"
                        f"  [dim]{elapsed:.1f}s | {file_count} dosya{tech_str}[/dim]"
                    )
                    live.update(Panel(panel_content, border_style="cyan", expand=False))
                    done.wait(timeout=0.25)

            return result_holder[0]

        scan_result = _scan_with_live()
        scan_dur = time.time() - scan_start
        self.console.print(f"  [bold cyan][1/3][/bold cyan] Proje tarandi [green]{scan_result.tech_stack}[/green] | {scan_result.screen_count} ekran | {scan_result.api_endpoint_count} API | {len(scan_result.source_files)} dosya [dim]({scan_dur:.1f}s)[/dim]")

        # Faz 2: Planlama (secilen profil ile)
        plan_start = time.time()
        plan_profile = profile if profile not in ("incremental", "diff") else "full"
        planner = TestPlanner(scan_result, profile=plan_profile)
        plan = planner.create_plan()
        self.plan_data = plan.to_dict()
        plan_dur = time.time() - plan_start
        self.console.print(f"  [bold yellow][2/3][/bold yellow] {plan.total_tests} test planlanidi ({len(plan.categories)} kategori) [dim]({plan_dur:.1f}s)[/dim]")

        # Faz 3: Calistirma - CANLI IZLEME
        self.console.print(f"  [bold green][3/3][/bold green] Testler calistiriliyor...\n")
        orchestrator = TestOrchestrator(self.project_path, self.plan_data)
        tests = self.plan_data.get("tests", [])
        self.results = []
        passed = 0
        failed = 0
        current_cat = ""
        cat_results = {}

        from rich.live import Live
        from rich.layout import Layout
        from rich.align import Align

        run_start = time.time()
        active_test_name = ""
        active_test_start = 0
        active_test_idx = [0]
        spin_frames = [">", ">>", ">>>", ">>"]
        spin_idx = [0]

        def build_live_with_spinner():
            """Spinner dahil canli gosterim."""
            completed = len(self.results)
            total = len(tests)
            pct = (completed / total * 100) if total > 0 else 0
            elapsed = time.time() - run_start
            rate = (passed / completed * 100) if completed > 0 else 0

            bar_w = 30
            filled = int(bar_w * completed / max(total, 1))
            bar = "[green]" + "=" * filled + "[/green][dim]" + "-" * (bar_w - filled) + "[/dim]"

            spin = spin_frames[spin_idx[0] % len(spin_frames)]
            spin_idx[0] += 1
            active_elapsed = time.time() - active_test_start if active_test_start else 0

            if active_test_name:
                active_line = f"  [yellow]{spin}[/yellow] [bold]{active_test_name[:50]}[/bold] [dim]{active_elapsed:.0f}s[/dim]"
            else:
                active_line = "  [dim]Bekleniyor...[/dim]"

            # Son testler
            recent_lines = []
            for r in self.results[-3:]:
                icon = "[green]OK[/green]" if r["passed"] else "[red]XX[/red]"
                recent_lines.append(f"  {icon} {r['name'][:42]} [dim]{r.get('duration',0):.1f}s[/dim]")
            recent_text = "\n".join(recent_lines) if recent_lines else ""

            # Kategoriler
            cat_lines = []
            for cat, cd in cat_results.items():
                ct = cd["p"] + cd["f"]
                cr = (cd["p"] / ct * 100) if ct > 0 else 0
                ci = "[green]+[/green]" if cr >= 80 else "[yellow]![/yellow]" if cr >= 50 else "[red]-[/red]"
                mini_w = 8
                mini_f = int(mini_w * cd["p"] / max(ct, 1))
                mini_bar = "[green]" + "=" * mini_f + "[/green][dim]" + "-" * (mini_w - mini_f) + "[/dim]"
                is_active = " [yellow]<[/yellow]" if cat == current_cat else ""
                cat_lines.append(f"  {ci} {cat[:14]:<14} {cd['p']:>2}/{ct:<2} {mini_bar}{is_active}")
            cat_text = "\n".join(cat_lines[-8:]) if cat_lines else ""

            # Siradaki testler (her zaman goster)
            next_lines = []
            ci = active_test_idx[0] + 1
            for t in tests[ci:ci+3]:
                next_lines.append(f"  [dim]{t.get('name','')[:45]}[/dim]")
            if ci + 3 < total:
                next_lines.append(f"  [dim]...ve {total - ci - 3} test daha[/dim]")
            next_text = "\n".join(next_lines) if next_lines else "  [dim]Son testler calisiyor[/dim]"

            return Panel(
                f"  {bar}  {completed}/{total} ({pct:.0f}%)  [dim]{elapsed:.0f}s[/dim]\n"
                f"  [green]{passed} gecti[/green]  [red]{failed} kaldi[/red]  [dim]{rate:.0f}%[/dim]\n\n"
                f"[bold]Aktif:[/bold]\n{active_line}\n\n"
                f"[bold]Son:[/bold]\n{recent_text}\n\n"
                f"[bold]Kategoriler:[/bold]\n{cat_text}\n\n"
                f"[bold]Siradaki:[/bold]\n{next_text}",
                title="[bold cyan]NAZAR CANLI[/bold cyan]",
                border_style="cyan",
            )

        import threading

        try:
            with Live(build_live_with_spinner(), console=self.console, refresh_per_second=4, transient=True) as live:
                for i, test in enumerate(tests):
                    test_cat = test.get("type", "other")
                    current_cat = test_cat
                    active_test_name = test.get("name", "?")
                    active_test_start = time.time()
                    active_test_idx[0] = i
                    if test_cat not in cat_results:
                        cat_results[test_cat] = {"p": 0, "f": 0}

                    result_holder = [None]
                    test_done = threading.Event()

                    def run_test(t=test):
                        result_holder[0] = orchestrator._run_test(t)
                        test_done.set()

                    thread = threading.Thread(target=run_test, daemon=True)
                    thread.start()

                    while not test_done.is_set():
                        live.update(build_live_with_spinner())
                        test_done.wait(timeout=0.25)

                    result = result_holder[0]
                    self.results.append(result)

                    if result["passed"]:
                        passed += 1
                        cat_results[test_cat]["p"] += 1
                    else:
                        failed += 1
                        cat_results[test_cat]["f"] += 1

                    current_cat = ""
                    active_test_name = ""
                    live.update(build_live_with_spinner())
        except KeyboardInterrupt:
            self.console.print("\n[dim]Tarama iptal edildi.[/dim]")

        total_dur = time.time() - start_time
        rate = (passed / len(self.results) * 100) if self.results else 0
        grade = _grade(rate)
        gs = "green" if rate >= 80 else "yellow" if rate >= 60 else "red"

        self.console.print()
        self.console.print(Panel(
            f"[bold {gs}]Not: {grade} ({rate:.0f}%)[/bold {gs}]  |  "
            f"[green]{passed} passed[/green]  |  [red]{failed} failed[/red]  |  "
            f"[dim]{len(self.results)} test  |  {total_dur:.1f}s[/dim]",
            title="[bold cyan]SONUC[/bold cyan]", border_style="cyan",
        ))

        cats = {}
        for r in self.results:
            cat = r.get("type", "other")
            cats.setdefault(cat, {"passed": 0, "failed": 0})
            cats[cat]["passed" if r["passed"] else "failed"] += 1

        self.console.print()
        for cat, d in cats.items():
            total = d["passed"] + d["failed"]
            cr = (d["passed"] / total * 100) if total > 0 else 0
            filled = int(15 * d["passed"] / max(total, 1))
            bar = "[green]" + "█" * filled + "[/green][dim]" + "░" * (15 - filled) + "[/dim]"
            icon = "[green]+[/green]" if cr >= 80 else "[yellow]![/yellow]" if cr >= 50 else "[red]-[/red]"
            rs = f"[green]{cr:.0f}%[/green]" if cr >= 80 else f"[yellow]{cr:.0f}%[/yellow]" if cr >= 50 else f"[red]{cr:.0f}%[/red]"
            self.console.print(f"  {icon} {cat.upper():<16} {d['passed']:>3}/{total:<3} {rs:>6}  {bar}")

        fl = [r for r in self.results if not r["passed"]]
        if fl:
            self.console.print(f"\n[bold]{len(fl)} BASARISIZ TEST:[/bold]")
            for i, r in enumerate(fl[:10], 1):
                pri = r.get("priority", "medium")
                ps = {"critical": "bold red", "high": "bold yellow", "medium": "cyan", "low": "dim"}.get(pri, "dim")
                self.console.print(f"  [dim]#{i:>2}[/dim] [{ps}]{pri.upper():<8}[/{ps}] {r['name'][:50]}")
                self.console.print(f"       [dim]{r['detail'][:60]}[/dim]")
            if len(fl) > 10:
                self.console.print(f"  [dim]...ve {len(fl)-10} daha. /report failed[/dim]")
        self.console.print(f"\n[dim]/report, /detail <no>, /guide <no>, /export html[/dim]")

    def _report(self, filt):
        if not self.results:
            self.console.print("[yellow]Once tarama yapin: /scan <yol>[/yellow]")
            return
        if filt == "failed":
            tests = [r for r in self.results if not r["passed"]]
        elif filt == "passed":
            tests = [r for r in self.results if r["passed"]]
        elif filt and filt != "all":
            tests = [r for r in self.results if r.get("type") == filt]
        else:
            tests = [r for r in self.results if not r["passed"]]
        if not tests:
            self.console.print("[green]Sonuc yok![/green]")
            return
        table = Table(title=f"Sonuclar ({len(tests)})", box=box.ROUNDED)
        table.add_column("#", width=4, style="dim")
        table.add_column("Oncelik", width=8)
        table.add_column("Test", ratio=3)
        table.add_column("Sonuc", width=7)
        table.add_column("Guven", width=6)
        table.add_column("Detay", ratio=2, style="dim")
        for i, r in enumerate(tests, 1):
            pri = r.get("priority", "medium")
            ps = {"critical":"bold red","high":"yellow","medium":"cyan","low":"dim"}.get(pri,"dim")
            st = "[green]PASSED[/green]" if r["passed"] else "[red]FAILED[/red]"
            table.add_row(str(i), f"[{ps}]{pri.upper()}[/{ps}]", r["name"][:45], st, f"{r.get('confidence','?')}%", r.get("detail","")[:35])
        self.console.print(table)

    def _detail(self, num):
        if not self.results:
            self.console.print("[yellow]Once tarama yapin.[/yellow]")
            return
        try:
            idx = int(num) - 1
        except (ValueError, TypeError):
            self.console.print("[red]/detail 1 seklinde girin.[/red]")
            return
        fl = [r for r in self.results if not r["passed"]]
        if idx < 0 or idx >= len(fl):
            self.console.print(f"[red]1-{len(fl)} arasi girin.[/red]")
            return
        r = fl[idx]
        self.console.print(Panel(f"[bold]{r['name']}[/bold]\n\nOncelik: [bold]{r.get('priority','').upper()}[/bold] | Guven: [bold]{r.get('confidence','?')}%[/bold]\nKategori: {r.get('type','').upper()}\n\n[bold]Detay:[/bold] {r.get('detail','')}", title=f"[bold cyan]#{idx+1}[/bold cyan]", border_style="cyan"))
        detail = r.get("detail", "")
        m = re.search(r'([a-zA-Z0-9_/\-\.()]+\.[a-zA-Z]+):(\d+)', detail)
        if m and self.project_path:
            fp, ln = m.group(1), int(m.group(2))
            full = os.path.join(self.project_path, fp)
            if os.path.exists(full):
                try:
                    lines = open(full, errors="ignore").readlines()
                    s, e = max(0, ln-3), min(len(lines), ln+3)
                    code = "".join(lines[s:e])
                    lang = "typescript" if fp.endswith((".ts",".tsx")) else "python" if fp.endswith(".py") else "javascript"
                    self.console.print(Panel(Syntax(code, lang, theme="monokai", line_numbers=True, start_line=s+1, highlight_lines={ln}), title=f"[bold]{fp}[/bold]", border_style="red"))
                except Exception:
                    pass
        self.console.print(f"\n[dim]Rehber: /guide {idx+1}[/dim]")

    def _guide(self, num):
        if not self.results:
            self.console.print("[yellow]Once tarama yapin.[/yellow]")
            return
        try:
            idx = int(num) - 1
        except (ValueError, TypeError):
            self.console.print("[red]/guide 1 seklinde girin.[/red]")
            return
        fl = [r for r in self.results if not r["passed"]]
        if idx < 0 or idx >= len(fl):
            self.console.print(f"[red]1-{len(fl)} arasi girin.[/red]")
            return
        r = fl[idx]
        guide = r.get("guide")
        if not guide:
            fix = r.get("how_to_fix")
            if fix:
                self.console.print(f"\n[bold red]SORUN:[/bold red] {fix.get('sorun','')}")
                self.console.print(f"[bold green]COZUM:[/bold green] {fix.get('cozum','')}")
                self.console.print(f"[bold cyan]QUICK FIX:[/bold cyan] {fix.get('quick_fix','')}")
            else:
                self.console.print("[yellow]Bu test icin rehber yok.[/yellow]")
            return
        ct = Text()
        ct.append(f"\n  RISK: ", style="bold red")
        ct.append(f"{guide['risk']}\n\n")
        ct.append(f"  Ne Oluyor: ", style="bold")
        ct.append(f"{guide['what']}\n")
        ct.append(f"  Neden Onemli: ", style="bold")
        ct.append(f"{guide['why']}\n")
        self.console.print(Panel(ct, title=f"[bold yellow]{guide['title']}[/bold yellow]", border_style="yellow"))
        steps = guide.get("steps", [])
        if steps:
            self.console.print("\n[bold]  ADIM ADIM:[/bold]")
            for i, s in enumerate(steps, 1):
                self.console.print(f"  [cyan]{i}.[/cyan] {s}")
        before, after = guide.get("before", ""), guide.get("after", "")
        if before and after:
            self.console.print()
            self.console.print(Panel(before, title="[red]ONCE[/red]", border_style="red"))
            self.console.print(Panel(after, title="[green]SONRA[/green]", border_style="green"))
        if guide.get("warning"):
            self.console.print(f"\n[yellow]  UYARI: {guide['warning']}[/yellow]")
        if guide.get("tools"):
            self.console.print(f"[dim]  Onerilen: {', '.join(guide['tools'])}[/dim]")
        self.console.print()

    def _export(self, fmt_str):
        if not self.results:
            self.console.print("[yellow]Once tarama yapin.[/yellow]")
            return
        parts = fmt_str.split(None, 1)
        fmt = parts[0] if parts else "html"
        out = parts[1] if len(parts) > 1 else None
        if fmt == "html":
            out = out or "nazar-report.html"
            from nazar.reporter.html_reporter import HTMLReporter
            HTMLReporter().generate(self.results, self.plan_data or {}, out)
        elif fmt == "json":
            out = out or "nazar-report.json"
            from nazar.reporters.json_reporter import JSONReporter
            JSONReporter().generate(self.results, self.plan_data or {}, out)
        elif fmt == "sarif":
            out = out or "nazar-report.sarif"
            from nazar.reporters.sarif_reporter import SARIFReporter
            SARIFReporter().generate(self.results, self.plan_data or {}, out)
        elif fmt == "markdown":
            out = out or "nazar-report.md"
            from nazar.reporters.markdown_reporter import MarkdownReporter
            MarkdownReporter().generate(self.results, self.plan_data or {}, out)
        else:
            self.console.print(f"[red]Format: html/json/sarif/markdown[/red]")
            return
        self.console.print(f"[green]Rapor olusturuldu: {out}[/green]")

    def _categories(self):
        table = Table(title="Nazar v4.0 Kategorileri", box=box.ROUNDED)
        table.add_column("Kategori", style="cyan", width=18)
        table.add_column("Kontrol", justify="center", width=8)
        table.add_column("Aciklama", ratio=3)
        cats = [
            ("Security", "63", "50+ secret, OWASP, crypto, supply chain"),
            ("App Store", "32", "Privacy manifest, IAP, Sign in with Apple"),
            ("Play Store", "10", "targetSdk, exported, ProGuard, permissions"),
            ("SCA", "7", "npm/pip/go audit, typosquatting, lisans"),
            ("AST Analysis", "6", "Python AST: eval, bare except, mutable default"),
            ("Taint Tracking", "5", "SQL injection, XSS, command injection akisi"),
            ("Code Quality", "16", "Complexity, dead code, smells"),
            ("UI Component", "10", "a11y, touch target, dark mode"),
            ("UX Text", "8", "Yazim, tutarlilik, i18n"),
            ("Cross-File", "7", "Dead export, orphan, circular import"),
            ("API", "4", "Erisilebilirlik, response"),
            ("Git", "4", "gitignore, buyuk dosya"),
            ("YAML Rules", "3", "Semgrep benzeri ozel kural motoru"),
            ("Type Safety", "3", "any, ts-ignore"),
            ("Error Handling", "3", "Bos catch, async"),
            ("Performance", "3", "Buyuk dosya/gorsel"),
            ("Documentation", "3", "README, CHANGELOG"),
            ("Naming", "3", "Dosya isimleri"),
            ("Dependency", "3", "Vulnerability"),
            ("Accessibility", "2", "testID, label"),
            ("Docker", "2", "Image, secret"),
        ]
        for n, c, d in cats:
            table.add_row(n, c, d)
        table.add_row("[bold]TOPLAM[/bold]", "[bold]158+[/bold]", "")
        self.console.print(table)

    # === Profil Secim Sistemi ===

    def _select_profile(self, tech: str, prev_scan: dict) -> str:
        """Kullaniciya profil secim menusu goster."""
        from nazar.planner.profiles import TEST_PROFILES

        self.console.print()
        self.console.print("  [bold]Ne test etmek istiyorsun?[/bold]")
        self.console.print()

        options = []
        idx = 1

        # 1. Tam tarama (her zaman)
        options.append(("full", "Tam tarama", "Tum kategoriler", "~5-10dk"))
        self.console.print(f"  [bold cyan][{idx}][/bold cyan] Tam tarama              [dim]Tum kategoriler (~5-10dk)[/dim]")
        idx += 1

        # 2-3. Hizli/karsilastirmali (onceki tarama varsa)
        if prev_scan:
            options.append(("incremental", "Hizli tarama", "Sadece degisen dosyalar", "~1dk"))
            self.console.print(f"  [bold cyan][{idx}][/bold cyan] Hizli tarama            [dim]Sadece degisen dosyalar (~1dk)[/dim]")
            idx += 1

            options.append(("diff", "Karsilastirmali", "Onceki sonucla diff", "~5-10dk"))
            self.console.print(f"  [bold cyan][{idx}][/bold cyan] Karsilastirmali         [dim]Onceki sonucla diff (~5-10dk)[/dim]")
            idx += 1

        # 4. Frontend
        options.append(("frontend", "Frontend / UI", "UX, UI, accessibility, renk, form", "~2-3dk"))
        self.console.print(f"  [bold cyan][{idx}][/bold cyan] Frontend / UI           [dim]UX, renk, form, accessibility (~2-3dk)[/dim]")
        idx += 1

        # 5. Backend
        options.append(("backend", "Backend / API", "Security, API, taint, code quality", "~3-4dk"))
        self.console.print(f"  [bold cyan][{idx}][/bold cyan] Backend / API           [dim]Security, taint, code quality (~3-4dk)[/dim]")
        idx += 1

        # 6. Guvenlik
        options.append(("security", "Guvenlik", "63 guvenlik + SCA + taint + AST", "~4-5dk"))
        self.console.print(f"  [bold cyan][{idx}][/bold cyan] Guvenlik                [dim]OWASP, SCA, taint tracking (~4-5dk)[/dim]")
        idx += 1

        # 7. Mobil (sadece mobil projeler)
        if tech in ("react-native", "flutter", "ios-native", "android-native"):
            options.append(("mobile", "Mobil uyumluluk", "App Store + Play Store", "~3-4dk"))
            self.console.print(f"  [bold cyan][{idx}][/bold cyan] Mobil uyumluluk         [dim]App Store + Play Store (~3-4dk)[/dim]")
            idx += 1

        # 8. CI/CD
        options.append(("ci", "CI/CD (hizli)", "Sadece kritik testler", "~1dk"))
        self.console.print(f"  [bold cyan][{idx}][/bold cyan] CI/CD (hizli)           [dim]Sadece kritik testler (~1dk)[/dim]")
        idx += 1

        self.console.print()

        try:
            choice = self.session.prompt(HTML('<style fg="#6366f1"><b>sec</b></style><style fg="#475569"> (1-' + str(len(options)) + ')&gt; </style>'))
            choice = choice.strip()
            ci = int(choice) - 1
            if 0 <= ci < len(options):
                selected = options[ci]
                self.console.print(f"  [green]Secildi: {selected[1]}[/green]\n")
                return selected[0]
        except (ValueError, KeyboardInterrupt, EOFError):
            pass

        self.console.print("  [dim]Iptal edildi.[/dim]\n")
        return None

    # === Proje Dizini Teyit Sistemi ===

    PROJECT_MARKERS = [
        "package.json", "pyproject.toml", "setup.py", "requirements.txt",
        "pubspec.yaml", "go.mod", "Cargo.toml", "composer.json",
        "Gemfile", "build.gradle", "pom.xml", "Makefile",
        "app.json", "next.config.js", "nuxt.config.js", "vite.config.ts",
        "manage.py", "settings.py", "tsconfig.json", ".gitignore",
    ]

    def _verify_project_path(self, path: Path) -> Path:
        """Proje dizinini teyit et. Yanlis dizinse oner, kullanici secsin."""
        # 1. Proje dosyasi var mi kontrol et
        markers_found = [m for m in self.PROJECT_MARKERS if (path / m).exists()]

        if markers_found:
            # Proje bulundu, teyit goster
            self.console.print(f"\n  [green]Proje bulundu:[/green] {path.name}/")
            self.console.print(f"  [dim]Belirtecler: {', '.join(markers_found[:4])}[/dim]")
            return path

        # 2. Proje dosyasi yok - belki ust dizin secilmis
        # Alt dizinlerde proje var mi?
        sub_projects = []
        try:
            for child in sorted(path.iterdir()):
                if child.is_dir() and not child.name.startswith("."):
                    child_markers = [m for m in self.PROJECT_MARKERS if (child / m).exists()]
                    if child_markers:
                        sub_projects.append({"name": child.name, "path": child, "markers": child_markers})
        except PermissionError:
            pass

        if not sub_projects:
            self.console.print(f"\n  [yellow]Bu dizinde proje bulunamadi: {path}[/yellow]")
            self.console.print("  [dim]package.json, pyproject.toml gibi dosyalar yok.[/dim]")
            self.console.print("  [dim]Dogrudan proje kokunu secin.[/dim]\n")
            return None

        # 3. Alt dizinlerde proje bulundu - kullaniciya sor
        self.console.print(f"\n  [yellow]'{path.name}/' proje koku degil, ama alt dizinlerde proje bulundu:[/yellow]\n")
        for i, sp in enumerate(sub_projects[:9], 1):
            markers_str = ", ".join(sp["markers"][:3])
            self.console.print(f"  [{i}] {sp['name']}/  [dim]({markers_str})[/dim]")
        self.console.print(f"  [0] Yine de '{path.name}/' dizinini tara")
        self.console.print()

        try:
            choice = self.session.prompt(HTML('<style fg="#6366f1"><b>sec</b></style><style fg="#475569">&gt; </style>'))
            choice = choice.strip()
            if choice == "0":
                return path
            idx = int(choice) - 1
            if 0 <= idx < len(sub_projects):
                selected = sub_projects[idx]
                self.console.print(f"  [green]Secildi: {selected['name']}/[/green]")
                return selected["path"]
        except (ValueError, KeyboardInterrupt, EOFError):
            pass

        self.console.print("  [dim]Iptal edildi.[/dim]\n")
        return None

    def _check_update_on_start(self):
        """Acilista sessizce guncelleme kontrol et."""
        try:
            import urllib.request, json
            from nazar import __version__
            resp = urllib.request.urlopen("https://pypi.org/pypi/nazar/json", timeout=5)
            data = json.loads(resp.read())
            latest = data["info"]["version"]
            if latest != __version__:
                self.console.print(f"\n  [bold yellow]Guncelleme mevcut: v{__version__} -> v{latest}[/bold yellow]")
                self.console.print(f"  [dim]/update yazarak guncelleyebilirsiniz.[/dim]")
        except Exception:
            pass

    def _update(self):
        """Nazar'i son versiyona guncelle."""
        import subprocess as _sp
        self.console.print("\n  [bold cyan]Guncelleme kontrol ediliyor...[/bold cyan]")
        try:
            from nazar import __version__
            current = __version__
        except (ImportError, AttributeError):
            current = "?"
        try:
            import urllib.request, json
            resp = urllib.request.urlopen("https://pypi.org/pypi/nazar/json", timeout=10)
            data = json.loads(resp.read())
            latest = data["info"]["version"]
        except Exception:
            latest = "?"
        if current == latest and current != "?":
            self.console.print(f"  [green]Zaten guncel: v{current}[/green]\n")
            return
        if latest != "?":
            self.console.print(f"  Mevcut: v{current}  ->  Yeni: v{latest}")
        try:
            r = _sp.run(["pipx", "upgrade", "nazar"], capture_output=True, text=True, timeout=120)
            if r.returncode == 0:
                self.console.print(f"  [green]Guncellendi! v{latest}[/green]\n")
                return
        except (FileNotFoundError, _sp.TimeoutExpired):
            pass
        try:
            r = _sp.run(["pip3", "install", "--upgrade", "nazar"], capture_output=True, text=True, timeout=120)
            if r.returncode == 0:
                self.console.print(f"  [green]Guncellendi! v{latest}[/green]\n")
                return
        except (FileNotFoundError, _sp.TimeoutExpired):
            pass
        self.console.print("  [red]Otomatik guncelleme basarisiz.[/red]")
        self.console.print("  [dim]Manuel: pipx upgrade nazar[/dim]\n")

    def _clear(self):
        self._show_header()

    def _stats(self):
        from nazar.guides.registry import GuideRegistry
        from nazar.runners.confidence import CONFIDENCE_SCORES
        table = Table(title="Nazar v4.0", box=box.ROUNDED)
        table.add_column("Metrik", style="cyan")
        table.add_column("Deger", style="green")
        table.add_row("Kontrol", "158+")
        table.add_row("Kategori", "22")
        table.add_row("Guide", str(len(GuideRegistry.get_all())))
        table.add_row("Confidence", str(len(CONFIDENCE_SCORES)))
        table.add_row("Framework", "15+")
        table.add_row("Format", "5 (HTML, JSON, SARIF, Markdown, JUnit)")
        table.add_row("Moduller", "SCA, AST, Taint, YAML Rules, App/Play Store")
        if self.results:
            p = sum(1 for r in self.results if r["passed"])
            f = len(self.results) - p
            table.add_row("", "")
            table.add_row("[bold]Son Tarama[/bold]", f"[bold]{self.project_path}[/bold]")
            table.add_row("Gecen/Kalan", f"[green]{p}[/green] / [red]{f}[/red]")
        self.console.print(table)
