from __future__ import annotations

import os
import queue
import sys
import threading
import traceback
import webbrowser
from datetime import datetime
from pathlib import Path
import tkinter as tk
from tkinter import BOTH, END, LEFT, RIGHT, X, Y, BooleanVar, StringVar, messagebox
from tkinter import ttk

from config_manager import load_settings, save_settings
from report_builder import save_csv_report, save_html_report, save_json_report, save_pdf_report
from seo_engine import analyze_site, analyze_url
from updater import check_for_update

APP_NAME = "Tamer SEO Analyzer"
APP_VERSION = "1.4.2"
APP_COPYRIGHT = "Copyright © 2026 tamerserbes.com"
APP_WEBSITE = "https://tamerserbes.com"
DEFAULT_SCAN_URL = APP_WEBSITE
APP_DEVELOPER = "Tamer Serbes"

# Modern arayüz renkleri
BG = "#07111f"
PANEL = "#0d1b2e"
PANEL_2 = "#101f34"
CARD = "#111f33"
CARD_2 = "#12243a"
BORDER = "#26384f"
TEXT = "#eef6ff"
MUTED = "#9caec4"
BLUE = "#1687ff"
BLUE_2 = "#075eea"
TEAL = "#24e3d1"
GREEN = "#5ee15a"
YELLOW = "#ffbd2f"
RED = "#ff5252"
PURPLE = "#7c3aed"


def get_base_dir() -> Path:
    if getattr(sys, "frozen", False):
        return Path(sys.executable).resolve().parent
    return Path(__file__).resolve().parent


BASE_DIR = get_base_dir()
REPORTS_DIR = BASE_DIR / "reports"
ASSETS_DIR = BASE_DIR / "assets"
SETTINGS_FILE = BASE_DIR / "settings.json"
ICON_PATH = ASSETS_DIR / "tamer_seo_analyzer.ico"
LICENSE_PATH = BASE_DIR / "LICENSE.txt"
HELP_PATH = BASE_DIR / "docs" / "troubleshooting.md"
UPDATE_INFO_PATH = BASE_DIR / "update_info.json"


class TamerSEOAnalyzerApp(tk.Tk):
    def __init__(self) -> None:
        super().__init__()
        self.title(f"{APP_NAME} V{APP_VERSION}")
        self.geometry("1380x860")
        self.minsize(1140, 720)
        self.configure(bg=BG)
        if ICON_PATH.exists():
            try:
                self.iconbitmap(str(ICON_PATH))
            except Exception:
                pass

        self.result: dict | None = None
        self.worker_queue: queue.Queue = queue.Queue()
        self.history_paths: list[Path] = []
        self.settings = load_settings(SETTINGS_FILE)
        self.analysis_started_at: datetime | None = None

        self.mode_var = StringVar(value=str(self.settings.get("mode", "site")))
        self.check_links_var = BooleanVar(value=bool(self.settings.get("check_links", True)))
        self.auto_save_var = BooleanVar(value=bool(self.settings.get("auto_save_reports", True)))
        self.use_sitemap_var = BooleanVar(value=bool(self.settings.get("use_sitemap", True)))
        self.max_links_var = tk.IntVar(value=int(self.settings.get("max_links", 20)))
        self.max_pages_var = tk.IntVar(value=int(self.settings.get("max_pages", 10)))

        self.summary_card_labels: dict[str, tk.Label] = {}
        self.summary_card_subs: dict[str, tk.Label] = {}
        self.nav_buttons: dict[str, tk.Button] = {}

        self._apply_style()
        self._build_ui()
        self.refresh_report_history()
        self.after(150, self._poll_queue)
        if not bool(self.settings.get("license_seen", False)):
            self.after(650, self.show_license)

    # -------------------------
    # UI
    # -------------------------
    def _apply_style(self) -> None:
        style = ttk.Style(self)
        try:
            style.theme_use("clam")
        except Exception:
            pass
        style.configure("Modern.Treeview", background=CARD, foreground=TEXT, fieldbackground=CARD, rowheight=30, font=("Segoe UI", 9), bordercolor=BORDER, borderwidth=0)
        style.configure("Modern.Treeview.Heading", background="#1b2b42", foreground="#dbeafe", font=("Segoe UI", 9, "bold"), relief="flat")
        style.map("Modern.Treeview", background=[("selected", "#1f4268")], foreground=[("selected", "#ffffff")])
        style.configure("Modern.TCombobox", fieldbackground="#0b1525", background="#0b1525", foreground=TEXT)
        style.configure("Horizontal.TProgressbar", background=TEAL, troughcolor="#132338", bordercolor=BORDER, lightcolor=TEAL, darkcolor=TEAL)
        style.configure("TSpinbox", fieldbackground="#0b1525", background="#0b1525", foreground=TEXT, arrowcolor=TEXT)

    def _build_ui(self) -> None:
        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(0, weight=1)

        self.sidebar = tk.Frame(self, bg="#061223", width=245, highlightthickness=1, highlightbackground="#14243a")
        self.sidebar.grid(row=0, column=0, sticky="ns")
        self.sidebar.grid_propagate(False)

        self.main = tk.Frame(self, bg=BG)
        self.main.grid(row=0, column=1, sticky="nsew")
        self.main.grid_columnconfigure(0, weight=1)
        self.main.grid_rowconfigure(6, weight=1)

        self._build_sidebar()
        self._build_header()
        self._build_input_bar()
        self._build_summary_cards()
        self._build_mid_dashboard()
        self._build_action_bar()
        self._build_pages_table()
        self._build_footer()
        self._set_nav_active("Ana Panel")

        self.url_entry.bind("<Return>", lambda _event: self.start_analysis())
        self.max_links_spin.bind("<FocusOut>", lambda _event: self._save_current_settings())
        self.max_pages_spin.bind("<FocusOut>", lambda _event: self._save_current_settings())

    def _build_sidebar(self) -> None:
        logo_area = tk.Frame(self.sidebar, bg="#061223")
        logo_area.pack(fill=X, padx=16, pady=(18, 14))
        logo = tk.Canvas(logo_area, width=50, height=50, bg="#061223", highlightthickness=0)
        logo.pack(side=LEFT)
        logo.create_polygon(8, 36, 8, 25, 17, 22, 17, 36, fill=BLUE, outline="")
        logo.create_polygon(21, 36, 21, 17, 30, 14, 30, 36, fill=TEAL, outline="")
        logo.create_polygon(34, 36, 34, 10, 43, 7, 43, 36, fill=GREEN, outline="")
        logo.create_line(7, 16, 21, 9, 31, 12, 44, 3, fill=TEAL, width=3, arrow=tk.LAST)
        text_area = tk.Frame(logo_area, bg="#061223")
        text_area.pack(side=LEFT, padx=(10, 0))
        tk.Label(text_area, text="Tamer", bg="#061223", fg="#ffffff", font=("Segoe UI", 15, "bold")).pack(anchor="w")
        tk.Label(text_area, text="SEO Analyzer", bg="#061223", fg="#dbeafe", font=("Segoe UI", 10, "bold")).pack(anchor="w")

        nav_items = [
            ("⌂", "Ana Panel", self.show_dashboard),
            ("＋", "Yeni Analiz", self.focus_new_analysis),
            ("▥", "Sonuçlar", self.show_results_area),
            ("▤", "Raporlar", self.show_reports_window),
            ("⚙", "Ayarlar", self.show_settings_window),
            ("ⓘ", "Hakkında", self.show_about),
        ]
        for icon, text, command in nav_items:
            btn = tk.Button(
                self.sidebar,
                text=f"  {icon}   {text}",
                command=command,
                anchor="w",
                relief="flat",
                bd=0,
                bg="#07192c",
                fg="#ffffff",
                activebackground="#0b58a3",
                activeforeground="#ffffff",
                font=("Segoe UI", 12, "bold"),
                padx=14,
                pady=13,
                cursor="hand2",
            )
            btn.pack(fill=X, padx=12, pady=4)
            self.nav_buttons[text] = btn

        tk.Frame(self.sidebar, bg="#12304f", height=1).pack(fill=X, padx=18, pady=(16, 10))
        self.sidebar_status = tk.Label(self.sidebar, text="Hazır", bg="#061223", fg="#cbd5e1", font=("Segoe UI", 10, "bold"), wraplength=195, justify="left")
        self.sidebar_status.pack(fill=X, padx=18, pady=(0, 20))

        art = tk.Canvas(self.sidebar, width=205, height=150, bg="#061223", highlightthickness=0)
        art.pack(side=tk.BOTTOM, padx=15, pady=(0, 18))
        art.create_oval(30, 55, 105, 130, outline="#2d7ad3", width=3)
        art.create_line(89, 112, 135, 145, fill="#2d7ad3", width=6)
        for i, h in enumerate([28, 48, 70, 95]):
            x = 86 + i * 20
            art.create_rectangle(x, 130 - h, x + 12, 130, fill="#0d57a2", outline="#1b89e8")
        art.create_line(74, 105, 100, 82, 119, 90, 150, 45, fill=TEAL, width=2, arrow=tk.LAST)
        art.create_text(96, 18, text="SEO", fill="#165b9f", font=("Segoe UI", 16, "bold"))

    def _build_header(self) -> None:
        header = tk.Frame(self.main, bg=BG)
        header.grid(row=0, column=0, sticky="ew", padx=16, pady=(14, 8))
        header.grid_columnconfigure(1, weight=1)

        title_line = tk.Frame(header, bg=BG)
        title_line.grid(row=0, column=0, sticky="w")
        tk.Label(title_line, text=APP_NAME, bg=BG, fg=TEXT, font=("Segoe UI", 23, "bold")).pack(side=LEFT)
        tk.Label(title_line, text=f" V{APP_VERSION} ", bg="#062d4b", fg=TEAL, font=("Segoe UI", 9, "bold"), padx=8, pady=3).pack(side=LEFT, padx=(12, 0))

        self.header_hint = tk.Label(header, text="Modern yayın arayüzü • Varsayılan tarama: tamerserbes.com", bg=BG, fg=MUTED, font=("Segoe UI", 9))
        self.header_hint.grid(row=1, column=0, sticky="w", pady=(2, 0))

        top_actions = tk.Frame(header, bg=BG)
        top_actions.grid(row=0, column=1, rowspan=2, sticky="e")
        self._modern_button(top_actions, "Güncelleme", self.check_updates, bg="#0d2741", fg="#dbeafe", width=12).pack(side=LEFT, padx=(0, 8))
        self._modern_button(top_actions, "Siteyi Aç ↗", self.open_website, bg=BLUE_2, fg="#ffffff", width=13).pack(side=LEFT)

    def _build_input_bar(self) -> None:
        card = self._panel(self.main, radius=False)
        card.grid(row=1, column=0, sticky="ew", padx=16, pady=(0, 10))
        card.grid_columnconfigure(1, weight=1)

        icon = tk.Label(card, text="◎", bg="#13253c", fg="#dbeafe", font=("Segoe UI", 19), width=3)
        icon.grid(row=0, column=0, rowspan=2, padx=(14, 10), pady=13, sticky="ns")

        self.url_entry = tk.Entry(card, bg="#081321", fg=TEXT, insertbackground=TEXT, relief="flat", font=("Segoe UI", 13), highlightthickness=1, highlightbackground="#2e4058", highlightcolor=TEAL)
        self.url_entry.grid(row=0, column=1, sticky="ew", ipady=9, pady=(13, 5))
        self.url_entry.insert(0, DEFAULT_SCAN_URL)

        opt = tk.Frame(card, bg=PANEL)
        opt.grid(row=1, column=1, sticky="ew", pady=(0, 12))
        tk.Radiobutton(opt, text="Tek sayfa", value="single", variable=self.mode_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT, font=("Segoe UI", 9)).pack(side=LEFT)
        tk.Radiobutton(opt, text="Tüm site / çoklu sayfa", value="site", variable=self.mode_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT, font=("Segoe UI", 9)).pack(side=LEFT, padx=(8, 0))
        tk.Label(opt, text="Sayfa:", bg=PANEL, fg=MUTED, font=("Segoe UI", 9)).pack(side=LEFT, padx=(14, 4))
        self.max_pages_spin = tk.Spinbox(opt, from_=1, to=100, width=4, textvariable=self.max_pages_var, command=self._save_current_settings, bg="#081321", fg=TEXT, buttonbackground="#13253c", relief="flat")
        self.max_pages_spin.pack(side=LEFT)
        tk.Checkbutton(opt, text="Sitemap", variable=self.use_sitemap_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT, font=("Segoe UI", 9)).pack(side=LEFT, padx=(10, 0))
        tk.Checkbutton(opt, text="Kırık link", variable=self.check_links_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT, font=("Segoe UI", 9)).pack(side=LEFT, padx=(10, 0))
        tk.Label(opt, text="Link:", bg=PANEL, fg=MUTED, font=("Segoe UI", 9)).pack(side=LEFT, padx=(10, 4))
        self.max_links_spin = tk.Spinbox(opt, from_=1, to=100, width=4, textvariable=self.max_links_var, command=self._save_current_settings, bg="#081321", fg=TEXT, buttonbackground="#13253c", relief="flat")
        self.max_links_spin.pack(side=LEFT)
        tk.Checkbutton(opt, text="Otomatik rapor", variable=self.auto_save_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT, font=("Segoe UI", 9)).pack(side=LEFT, padx=(10, 0))

        self.analyze_button = self._modern_button(card, "⌕  Analiz Et", self.start_analysis, bg=BLUE, fg="#ffffff", width=16, big=True)
        self.analyze_button.grid(row=0, column=2, rowspan=2, padx=14, pady=13, sticky="nsew")

    def _build_summary_cards(self) -> None:
        wrap = tk.Frame(self.main, bg=BG)
        wrap.grid(row=2, column=0, sticky="ew", padx=16, pady=(0, 10))
        for i in range(4):
            wrap.grid_columnconfigure(i, weight=1)
        cards = [
            ("SEO Puanı", "--", "Analiz bekleniyor", GREEN, "↗"),
            ("Kırık Link", "--", "Tespit bekleniyor", RED, "🔗"),
            ("Alt Etiketi Eksik", "--", "Tespit bekleniyor", YELLOW, "▧"),
            ("Yüklenme Süresi", "--", "Analiz bekleniyor", TEAL, "◴"),
        ]
        for idx, (title, value, sub, color, icon) in enumerate(cards):
            c = tk.Frame(wrap, bg=CARD, highlightthickness=1, highlightbackground=BORDER)
            c.grid(row=0, column=idx, sticky="ew", padx=(0 if idx == 0 else 8, 0), ipady=8)
            inner = tk.Frame(c, bg=CARD)
            inner.pack(fill=BOTH, expand=True, padx=14, pady=8)
            tk.Label(inner, text=icon, bg=CARD, fg=color, font=("Segoe UI", 22)).pack(side=LEFT, padx=(0, 13))
            txt = tk.Frame(inner, bg=CARD)
            txt.pack(side=LEFT, fill=BOTH, expand=True)
            tk.Label(txt, text=title, bg=CARD, fg=TEXT, font=("Segoe UI", 11, "bold")).pack(anchor="w")
            val = tk.Label(txt, text=value, bg=CARD, fg=color, font=("Segoe UI", 25, "bold"))
            val.pack(anchor="w")
            desc = tk.Label(txt, text=sub, bg=CARD, fg=MUTED, font=("Segoe UI", 9))
            desc.pack(anchor="w")
            self.summary_card_labels[title] = val
            self.summary_card_subs[title] = desc

    def _build_mid_dashboard(self) -> None:
        mid = tk.Frame(self.main, bg=BG)
        mid.grid(row=3, column=0, sticky="nsew", padx=16, pady=(0, 10))
        mid.grid_columnconfigure(0, weight=1, minsize=270)
        mid.grid_columnconfigure(1, weight=2, minsize=380)
        mid.grid_columnconfigure(2, weight=2, minsize=380)
        mid.grid_rowconfigure(0, weight=1)

        score_panel = self._panel(mid)
        score_panel.grid(row=0, column=0, sticky="nsew", padx=(0, 8))
        tk.Label(score_panel, text="SEO PUANI", bg=PANEL, fg=TEXT, font=("Segoe UI", 11, "bold")).pack(anchor="w", padx=14, pady=(12, 0))
        self.gauge = tk.Canvas(score_panel, width=250, height=190, bg=PANEL, highlightthickness=0)
        self.gauge.pack(pady=(4, 0), fill=X)
        self.score_label = tk.Label(score_panel, text="--", bg=PANEL, fg=TEXT, font=("Segoe UI", 43, "bold"))
        self.score_label.place(in_=self.gauge, relx=0.5, rely=0.48, anchor="center")
        self.score_den_label = tk.Label(score_panel, text="/100", bg=PANEL, fg=MUTED, font=("Segoe UI", 17))
        self.score_den_label.place(in_=self.gauge, relx=0.5, rely=0.68, anchor="center")
        self.grade_label = tk.Label(score_panel, text="Analiz bekleniyor", bg=PANEL, fg=MUTED, font=("Segoe UI", 13, "bold"))
        self.grade_label.pack(pady=(0, 3))
        self.score_hint = tk.Label(score_panel, text="Sitenizin SEO performansı analiz sonrası burada gösterilir.", bg=PANEL, fg=MUTED, font=("Segoe UI", 9), wraplength=250, justify="center")
        self.score_hint.pack(padx=12, pady=(0, 12))
        self._draw_gauge(0)

        checks_panel = self._panel(mid)
        checks_panel.grid(row=0, column=1, sticky="nsew", padx=(0, 8))
        tk.Label(checks_panel, text="☷  SEO KONTROLLERİ", bg=PANEL, fg=TEXT, font=("Segoe UI", 11, "bold")).pack(anchor="w", padx=14, pady=(12, 6))
        self.tree = ttk.Treeview(checks_panel, columns=("name", "status", "detail"), show="headings", style="Modern.Treeview", height=9)
        self.tree.heading("name", text="Kontrol")
        self.tree.heading("status", text="Durum")
        self.tree.heading("detail", text="Detay")
        self.tree.column("name", width=160, stretch=False)
        self.tree.column("status", width=90, stretch=False)
        self.tree.column("detail", width=280, stretch=True)
        self.tree.tag_configure("success", foreground="#80ff92")
        self.tree.tag_configure("warning", foreground="#ffcf4f")
        self.tree.tag_configure("error", foreground="#ff7777")
        self.tree.tag_configure("info", foreground="#8fd1ff")
        self.tree.pack(fill=BOTH, expand=True, padx=12, pady=(0, 12))

        rec_panel = self._panel(mid)
        rec_panel.grid(row=0, column=2, sticky="nsew")
        tk.Label(rec_panel, text="💡  ÖNCELİKLİ ÖNERİLER", bg=PANEL, fg=TEXT, font=("Segoe UI", 11, "bold")).pack(anchor="w", padx=14, pady=(12, 6))
        self.recommendations_box = tk.Frame(rec_panel, bg=PANEL)
        self.recommendations_box.pack(fill=BOTH, expand=True, padx=12, pady=(0, 12))
        self._render_recommendation_cards([("info", "Analiz bekleniyor", "Site analizinden sonra öncelikli çözüm önerileri burada listelenecek.")])

    def _build_action_bar(self) -> None:
        bar = tk.Frame(self.main, bg=BG)
        bar.grid(row=4, column=0, sticky="ew", padx=16, pady=(0, 10))
        for label, command, color in [
            ("</>  HTML Rapor", self.save_html, BLUE_2),
            ("▣  PDF Rapor", self.save_pdf, "#8f1d1d"),
            ("{}  JSON", self.save_json, "#5127a7"),
            ("▦  CSV", self.save_csv, "#157247"),
        ]:
            self._modern_button(bar, label, command, bg=color, fg="#ffffff", width=18).pack(side=LEFT, padx=(0, 10))
        tk.Frame(bar, bg=BG).pack(side=LEFT, fill=X, expand=True)
        self._modern_button(bar, "Rapor Klasörü", self.open_reports_folder, bg="#0e2e4a", fg="#dbeafe", width=14).pack(side=LEFT, padx=(0, 10))
        self._modern_button(bar, "Siteyi Aç  ↗", self.open_website, bg=BLUE_2, fg="#ffffff", width=16).pack(side=LEFT)

    def _build_pages_table(self) -> None:
        panel = self._panel(self.main)
        panel.grid(row=5, column=0, rowspan=2, sticky="nsew", padx=16, pady=(0, 10))
        panel.grid_rowconfigure(1, weight=1)
        panel.grid_columnconfigure(0, weight=1)
        tk.Label(panel, text="SAYFA ANALİZ SONUÇLARI", bg=PANEL, fg=TEXT, font=("Segoe UI", 11, "bold")).grid(row=0, column=0, sticky="w", padx=14, pady=(10, 6))
        cols = ("no", "url", "score", "load", "broken", "alt", "status", "scan")
        self.pages_tree = ttk.Treeview(panel, columns=cols, show="headings", style="Modern.Treeview", height=8)
        headers = {
            "no": "#",
            "url": "URL",
            "score": "SEO Puanı",
            "load": "Yüklenme Süresi",
            "broken": "Kırık Link",
            "alt": "Alt Etiketi Eksik",
            "status": "Durum",
            "scan": "Son Tarama",
        }
        widths = {"no": 45, "url": 420, "score": 105, "load": 125, "broken": 95, "alt": 125, "status": 105, "scan": 145}
        for col in cols:
            self.pages_tree.heading(col, text=headers[col])
            self.pages_tree.column(col, width=widths[col], stretch=(col == "url"))
        self.pages_tree.tag_configure("success", foreground="#9cff93")
        self.pages_tree.tag_configure("warning", foreground="#ffd45a")
        self.pages_tree.tag_configure("error", foreground="#ff7b7b")
        self.pages_tree.tag_configure("info", foreground="#dbeafe")
        y_scroll = ttk.Scrollbar(panel, orient="vertical", command=self.pages_tree.yview)
        self.pages_tree.configure(yscrollcommand=y_scroll.set)
        self.pages_tree.grid(row=1, column=0, sticky="nsew", padx=(12, 0), pady=(0, 12))
        y_scroll.grid(row=1, column=1, sticky="ns", pady=(0, 12), padx=(0, 12))
        self.pages_tree.bind("<<TreeviewSelect>>", self._page_selected)

    def _build_footer(self) -> None:
        footer = tk.Frame(self.main, bg="#061223", height=58, highlightthickness=1, highlightbackground="#14243a")
        footer.grid(row=7, column=0, sticky="ew")
        footer.grid_propagate(False)
        footer.grid_columnconfigure(1, weight=1)

        self.status_label = tk.Label(footer, text="● Hazır", bg="#061223", fg="#cbd5e1", font=("Segoe UI", 9))
        self.status_label.grid(row=0, column=0, sticky="w", padx=14, pady=(4, 0))

        self.footer_metrics = tk.Label(
            footer,
            text="Son tarama: -   |   Toplam sayfa: -   |   Süre: -",
            bg="#061223",
            fg=MUTED,
            font=("Segoe UI", 9),
        )
        self.footer_metrics.grid(row=0, column=1, sticky="w", pady=(4, 0))

        self.progress = ttk.Progressbar(footer, mode="indeterminate", length=120)
        self.progress.grid(row=0, column=2, padx=(0, 14), sticky="e", pady=(4, 0))

        brand = tk.Frame(footer, bg="#061223")
        brand.grid(row=1, column=0, columnspan=3, sticky="ew", padx=14, pady=(2, 4))
        brand.grid_columnconfigure(0, weight=1)
        brand_inner = tk.Frame(brand, bg="#061223")
        brand_inner.grid(row=0, column=0, sticky="e")
        tk.Label(
            brand_inner,
            text=f"{APP_COPYRIGHT} • {APP_DEVELOPER} • {APP_NAME} V{APP_VERSION} • ",
            bg="#061223",
            fg="#cbd5e1",
            font=("Segoe UI", 9),
        ).pack(side=LEFT)
        link = tk.Label(
            brand_inner,
            text=APP_WEBSITE,
            bg="#061223",
            fg="#38bdf8",
            font=("Segoe UI", 9, "underline"),
            cursor="hand2",
        )
        link.pack(side=LEFT)
        link.bind("<Button-1>", lambda _event: self.open_website())

    def _panel(self, parent: tk.Widget, radius: bool = True) -> tk.Frame:
        # Tkinter native frame, görseldeki kart/panel görünümü için border + koyu zemin.
        return tk.Frame(parent, bg=PANEL, highlightthickness=1, highlightbackground=BORDER)

    def _modern_button(self, parent: tk.Widget, text: str, command, bg: str = BLUE_2, fg: str = "#ffffff", width: int = 12, big: bool = False) -> tk.Button:
        return tk.Button(
            parent,
            text=text,
            command=command,
            bg=bg,
            fg=fg,
            activebackground=bg,
            activeforeground=fg,
            relief="flat",
            bd=0,
            padx=12,
            pady=10 if big else 7,
            width=width,
            font=("Segoe UI", 11 if big else 9, "bold"),
            cursor="hand2",
        )

    def _set_nav_active(self, name: str) -> None:
        for label, btn in self.nav_buttons.items():
            if label == name:
                btn.configure(bg="#0b65c9", fg="#ffffff", activebackground="#0b65c9", font=("Segoe UI", 12, "bold"))
            else:
                btn.configure(bg="#07192c", fg="#f1f7ff", activebackground="#113d72", font=("Segoe UI", 12, "bold"))

    def _draw_gauge(self, score: int) -> None:
        self.gauge.delete("gauge")
        x0, y0, x1, y1 = 36, 30, 214, 208
        self.gauge.create_arc(x0, y0, x1, y1, start=210, extent=-240, style=tk.ARC, width=18, outline="#24364b", tags="gauge")
        score = max(0, min(int(score), 100))
        color = GREEN if score >= 80 else YELLOW if score >= 60 else RED
        self.gauge.create_arc(x0, y0, x1, y1, start=210, extent=-(240 * score / 100), style=tk.ARC, width=18, outline=color, tags="gauge")
        self.gauge.create_oval(109, 103, 141, 135, fill="#0a1524", outline="#24364b", width=2, tags="gauge")

    def _render_recommendation_cards(self, items: list[tuple[str, str, str]]) -> None:
        for child in self.recommendations_box.winfo_children():
            child.destroy()
        color_map = {"error": RED, "warning": YELLOW, "success": GREEN, "info": TEAL}
        for status, title, desc in items[:5]:
            row = tk.Frame(self.recommendations_box, bg=CARD_2, highlightthickness=1, highlightbackground="#20344f")
            row.pack(fill=X, pady=(0, 8))
            tk.Label(row, text="●", bg=CARD_2, fg=color_map.get(status, TEAL), font=("Segoe UI", 13)).pack(side=LEFT, padx=(10, 8), pady=9)
            text = tk.Frame(row, bg=CARD_2)
            text.pack(side=LEFT, fill=X, expand=True, pady=7)
            tk.Label(text, text=title, bg=CARD_2, fg=TEXT, font=("Segoe UI", 9, "bold"), anchor="w", justify="left").pack(anchor="w")
            tk.Label(text, text=desc, bg=CARD_2, fg=MUTED, font=("Segoe UI", 8), anchor="w", justify="left", wraplength=330).pack(anchor="w")
            tk.Label(row, text="›", bg=CARD_2, fg="#dbeafe", font=("Segoe UI", 21)).pack(side=RIGHT, padx=10)

    # -------------------------
    # Navigation actions
    # -------------------------
    def show_dashboard(self) -> None:
        self._set_nav_active("Ana Panel")
        self.header_hint.configure(text="Ana panel aktif • URL girip analiz başlatabilirsiniz")

    def focus_new_analysis(self) -> None:
        self._set_nav_active("Yeni Analiz")
        self.url_entry.focus_set()
        self.url_entry.selection_range(0, END)
        self.header_hint.configure(text="Yeni analiz için site adresini girin ve Analiz Et butonuna basın")

    def show_results_area(self) -> None:
        self._set_nav_active("Sonuçlar")
        self.pages_tree.focus_set()
        self.header_hint.configure(text="Sonuçlar alanı aktif • Sayfa seçerek SEO kontrollerini inceleyin")

    def show_reports_window(self) -> None:
        self._set_nav_active("Raporlar")
        self.refresh_report_history()
        win = tk.Toplevel(self)
        win.title("Rapor Geçmişi")
        win.geometry("760x460")
        win.configure(bg=BG)
        tk.Label(win, text="Rapor Geçmişi", bg=BG, fg=TEXT, font=("Segoe UI", 18, "bold")).pack(anchor="w", padx=18, pady=(16, 8))
        lb = tk.Listbox(win, bg=CARD, fg=TEXT, selectbackground="#1f4268", relief="flat", font=("Consolas", 10))
        lb.pack(fill=BOTH, expand=True, padx=18, pady=(0, 12))
        if not self.history_paths:
            lb.insert(END, "Henüz rapor yok.")
        else:
            for path in self.history_paths:
                size_kb = max(1, int(path.stat().st_size / 1024))
                lb.insert(END, f"{path.name}  •  {size_kb} KB")
        buttons = tk.Frame(win, bg=BG)
        buttons.pack(fill=X, padx=18, pady=(0, 16))
        self._modern_button(buttons, "Seçili Raporu Aç", lambda: self._open_history_from_list(lb), width=18).pack(side=LEFT)
        self._modern_button(buttons, "Klasörü Aç", self.open_reports_folder, bg="#0e2e4a", width=14).pack(side=LEFT, padx=8)

    def _open_history_from_list(self, lb: tk.Listbox) -> None:
        selection = lb.curselection()
        if not selection or not self.history_paths:
            return
        idx = selection[0]
        if idx < len(self.history_paths):
            self._open_path(self.history_paths[idx])

    def show_settings_window(self) -> None:
        self._set_nav_active("Ayarlar")
        win = tk.Toplevel(self)
        win.title("Ayarlar")
        win.geometry("560x380")
        win.configure(bg=BG)
        tk.Label(win, text="Ayarlar", bg=BG, fg=TEXT, font=("Segoe UI", 18, "bold")).pack(anchor="w", padx=18, pady=(16, 8))
        body = tk.Frame(win, bg=PANEL, highlightthickness=1, highlightbackground=BORDER)
        body.pack(fill=BOTH, expand=True, padx=18, pady=(0, 18))
        for widget in [
            tk.Radiobutton(body, text="Varsayılan: tek sayfa analizi", value="single", variable=self.mode_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT),
            tk.Radiobutton(body, text="Varsayılan: tüm site / çoklu sayfa analizi", value="site", variable=self.mode_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT),
            tk.Checkbutton(body, text="Sitemap kullan", variable=self.use_sitemap_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT),
            tk.Checkbutton(body, text="Kırık link kontrolü", variable=self.check_links_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT),
            tk.Checkbutton(body, text="Analiz sonunda otomatik rapor kaydet", variable=self.auto_save_var, command=self._save_current_settings, bg=PANEL, fg=TEXT, selectcolor="#0a1727", activebackground=PANEL, activeforeground=TEXT),
        ]:
            widget.pack(anchor="w", padx=18, pady=8)
        self._modern_button(body, "Kaydet ve Kapat", lambda: (self._save_current_settings(), win.destroy()), width=18).pack(anchor="w", padx=18, pady=12)

    # -------------------------
    # Analysis
    # -------------------------
    def _save_current_settings(self) -> None:
        try:
            max_links = max(1, min(int(self.max_links_var.get()), 100))
        except Exception:
            max_links = 20
            self.max_links_var.set(max_links)
        try:
            max_pages = max(1, min(int(self.max_pages_var.get()), 100))
        except Exception:
            max_pages = 10
            self.max_pages_var.set(max_pages)
        save_settings(SETTINGS_FILE, {
            "last_url": DEFAULT_SCAN_URL,
            "check_links": self.check_links_var.get(),
            "max_links": max_links,
            "auto_save_reports": self.auto_save_var.get(),
            "mode": self.mode_var.get(),
            "max_pages": max_pages,
            "use_sitemap": self.use_sitemap_var.get(),
            "update_url": str(self.settings.get("update_url") or UPDATE_INFO_PATH),
            "license_seen": bool(self.settings.get("license_seen", False)),
        })

    def start_analysis(self) -> None:
        url = self.url_entry.get().strip()
        if not url:
            messagebox.showwarning("URL gerekli", "Lütfen analiz edilecek site adresini girin.")
            return
        self._set_nav_active("Yeni Analiz")
        self._save_current_settings()
        self.analysis_started_at = datetime.now()
        self.analyze_button.configure(state="disabled")
        self._set_status("Analiz başlatıldı...", running=True)
        self.progress.start(10)
        self.clear_result_views(keep_summary=False)

        def progress(message: str) -> None:
            self.worker_queue.put(("progress", message))

        def worker() -> None:
            try:
                if self.mode_var.get() == "site":
                    result = analyze_site(
                        url,
                        max_pages=int(self.max_pages_var.get()),
                        use_sitemap=self.use_sitemap_var.get(),
                        check_link_health=self.check_links_var.get(),
                        max_links_to_check=int(self.max_links_var.get()),
                        progress=progress,
                    )
                else:
                    progress("Tek sayfa analiz ediliyor...")
                    result = analyze_url(url, check_link_health=self.check_links_var.get(), max_links_to_check=int(self.max_links_var.get()))
                self.worker_queue.put(("done", result))
            except Exception as exc:  # noqa: BLE001
                self.worker_queue.put(("error", f"{exc}\n\n{traceback.format_exc()}"))

        threading.Thread(target=worker, daemon=True).start()

    def _poll_queue(self) -> None:
        try:
            while True:
                kind, payload = self.worker_queue.get_nowait()
                if kind == "progress":
                    self._set_status(str(payload), running=True)
                elif kind == "done":
                    self.progress.stop()
                    self.analyze_button.configure(state="normal")
                    self.result = payload
                    self.populate_result(payload)
                    self._set_status("Tarama tamamlandı", running=False, good=True)
                    if self.auto_save_var.get():
                        self._auto_save_reports()
                elif kind == "error":
                    self.progress.stop()
                    self.analyze_button.configure(state="normal")
                    self._set_status("Hata oluştu", running=False, error=True)
                    messagebox.showerror("Analiz hatası", str(payload)[:3500])
        except queue.Empty:
            pass
        self.after(150, self._poll_queue)

    def _set_status(self, text: str, running: bool = False, good: bool = False, error: bool = False) -> None:
        dot = "●"
        color = RED if error else GREEN if good else TEAL if running else "#cbd5e1"
        self.status_label.configure(text=f"{dot} {text}", fg=color)
        self.sidebar_status.configure(text=text, fg=color if (good or error or running) else MUTED)

    def clear_result_views(self, keep_summary: bool = True) -> None:
        for item in self.tree.get_children():
            self.tree.delete(item)
        for item in self.pages_tree.get_children():
            self.pages_tree.delete(item)
        self._render_recommendation_cards([("info", "Analiz devam ediyor" if not keep_summary else "Analiz bekleniyor", "Sonuçlar hazır olduğunda burada öncelikli öneriler gösterilecek.")])
        if not keep_summary:
            self._draw_gauge(0)
            self.score_label.configure(text="--")
            self.grade_label.configure(text="Analiz ediliyor...", fg=TEAL)
            self.score_hint.configure(text="Analiz çalışıyor. Lütfen sonuç ekranını takip edin.")
            self._update_summary_cards(score="--", broken="--", missing_alt="--", load="--")
            self.footer_metrics.configure(text="Son tarama: -   |   Toplam sayfa: -   |   Süre: -")

    def populate_result(self, result: dict) -> None:
        self.clear_result_views(keep_summary=False)
        score = int(result.get("score") or 0)
        self._draw_gauge(score)
        color = GREEN if score >= 80 else YELLOW if score >= 60 else RED
        self.score_label.configure(text=str(score), fg=TEXT)
        self.grade_label.configure(text=str(result.get("grade") or "-"), fg=color)

        if result.get("mode") == "site" or "pages" in result:
            self._populate_site_result(result)
        else:
            self._populate_single_result(result)
        self.refresh_report_history()
        self._set_nav_active("Sonuçlar")

    def _populate_site_result(self, result: dict) -> None:
        summary = result.get("summary") or {}
        pages = result.get("pages") or []
        ok_pages = summary.get("ok_pages") or 0
        total_pages = summary.get("total_pages") or len(pages)
        issue_counts = summary.get("issue_counts") or {}
        broken_total = self._sum_broken_links(pages)
        missing_total = self._sum_missing_alt(pages)
        avg_load = self._average_load_ms(pages)
        self._update_summary_cards(score=f"{result.get('score', 0)} /100", broken=str(broken_total), missing_alt=str(missing_total), load=self._format_load(avg_load))
        self.score_hint.configure(text=f"{ok_pages}/{total_pages} sayfa başarıyla analiz edildi. Ortalama puan: {summary.get('average_page_score', '-')}")

        for idx, page in enumerate(pages):
            score = int(page.get("score") or 0)
            tag = "success" if score >= 80 else "warning" if score >= 60 else "error"
            link_report = page.get("link_report") or {}
            scan_time = datetime.now().strftime("%d.%m.%Y %H:%M")
            self.pages_tree.insert("", END, iid=str(idx), values=(
                idx + 1,
                page.get("final_url") or page.get("url"),
                score,
                self._format_load(page.get("load_ms")),
                link_report.get("broken_count", 0),
                len(page.get("missing_alt_images") or []),
                "Başarılı" if score >= 80 else "Uyarı" if score >= 60 else "Kritik",
                scan_time,
            ), tags=(tag,))
        if pages:
            self.pages_tree.selection_set("0")
            self._show_page_checks(pages[0])
            self._set_recommendations_from_page(pages[0])
        else:
            self._render_recommendation_cards([("warning", "Sayfa bulunamadı", "Tarama sonucunda analiz edilecek sayfa bulunamadı.")])

        top_recs = []
        for item in summary.get("top_recommendations") or []:
            top_recs.append(("warning", f"{item.get('count')} sayfada sorun", str(item.get("recommendation") or "Kontrol edin.")))
        if top_recs:
            self._render_recommendation_cards(top_recs)
        self.footer_metrics.configure(text=self._footer_text(total_pages=total_pages))
        self.header_hint.configure(text=f"Analiz tamamlandı • Hata: {issue_counts.get('error', 0)} • Uyarı: {issue_counts.get('warning', 0)}")

    def _populate_single_result(self, result: dict) -> None:
        link_report = result.get("link_report") or {}
        missing_alt = len(result.get("missing_alt_images") or [])
        self._update_summary_cards(score=f"{result.get('score', 0)} /100", broken=str(link_report.get("broken_count", 0)), missing_alt=str(missing_alt), load=self._format_load(result.get("load_ms")))
        self.score_hint.configure(text=f"HTTP {result.get('status_code', '-')} • HTML boyutu: {int(result.get('raw_size', 0) / 1024)} KB")
        score = int(result.get("score") or 0)
        tag = "success" if score >= 80 else "warning" if score >= 60 else "error"
        self.pages_tree.insert("", END, iid="0", values=(
            1,
            result.get("final_url") or result.get("url"),
            score,
            self._format_load(result.get("load_ms")),
            link_report.get("broken_count", 0),
            missing_alt,
            "Başarılı" if score >= 80 else "Uyarı" if score >= 60 else "Kritik",
            datetime.now().strftime("%d.%m.%Y %H:%M"),
        ), tags=(tag,))
        self.pages_tree.selection_set("0")
        self._show_page_checks(result)
        self._set_recommendations_from_page(result)
        self.footer_metrics.configure(text=self._footer_text(total_pages=1))
        self.header_hint.configure(text=f"Analiz tamamlandı • {result.get('final_url') or result.get('url')}")

    def _page_selected(self, _event=None) -> None:
        if not self.result:
            return
        selection = self.pages_tree.selection()
        if not selection:
            return
        try:
            idx = int(selection[0])
        except Exception:
            return
        pages = self.result.get("pages") if (self.result.get("mode") == "site" or "pages" in self.result) else [self.result]
        if not pages or idx >= len(pages):
            return
        page = pages[idx]
        self._show_page_checks(page)
        self._set_recommendations_from_page(page)

    def _show_page_checks(self, page: dict) -> None:
        for item in self.tree.get_children():
            self.tree.delete(item)
        for check in page.get("checks", []) or []:
            status = check.get("status", "info")
            icon = "✓" if status == "success" else "!" if status == "warning" else "✕" if status == "error" else "•"
            self.tree.insert("", END, values=(
                f"{icon} {check.get('name')}",
                check.get("status_label"),
                check.get("detail"),
            ), tags=(status,))

    def _set_recommendations_from_page(self, page: dict) -> None:
        items: list[tuple[str, str, str]] = []
        for check in page.get("checks", []) or []:
            if check.get("status") in {"error", "warning"}:
                items.append((str(check.get("status")), str(check.get("name")), str(check.get("recommendation") or check.get("detail") or "Kontrol edin.")))
        if not items:
            items = [("success", "Kritik öneri bulunamadı", "Bu sayfa için öncelikli hata görünmüyor. Düzenli kontrole devam edin.")]
        self._render_recommendation_cards(items)

    def _update_summary_cards(self, score: str, broken: str, missing_alt: str, load: str) -> None:
        data = {
            "SEO Puanı": (score, "Genel analiz puanı"),
            "Kırık Link": (broken, "Tespit edildi" if broken not in {"--", "0"} else "Sorun yok / bekleniyor"),
            "Alt Etiketi Eksik": (missing_alt, "Tespit edildi" if missing_alt not in {"--", "0"} else "Sorun yok / bekleniyor"),
            "Yüklenme Süresi": (load, "Çok iyi" if load not in {"--", "-"} else "Analiz bekleniyor"),
        }
        for key, (value, desc) in data.items():
            if key in self.summary_card_labels:
                self.summary_card_labels[key].configure(text=value)
            if key in self.summary_card_subs:
                self.summary_card_subs[key].configure(text=desc)

    # -------------------------
    # Reports / helpers
    # -------------------------
    def _auto_save_reports(self) -> None:
        if not self.result:
            return
        try:
            html_path = save_html_report(self.result, REPORTS_DIR)
            json_path = save_json_report(self.result, REPORTS_DIR)
            if self.result.get("mode") == "site" or "pages" in self.result:
                save_csv_report(self.result, REPORTS_DIR)
            self._set_status(f"Rapor kaydedildi: {html_path.name}, {json_path.name}", good=True)
            self.refresh_report_history()
        except Exception as exc:  # noqa: BLE001
            self._set_status(f"Rapor kaydedilemedi: {exc}", error=True)

    def save_html(self) -> None:
        if not self._require_result():
            return
        path = save_html_report(self.result, REPORTS_DIR)  # type: ignore[arg-type]
        self.refresh_report_history()
        self._set_status(f"HTML rapor kaydedildi: {path.name}", good=True)
        self._open_path(path)

    def save_json(self) -> None:
        if not self._require_result():
            return
        path = save_json_report(self.result, REPORTS_DIR)  # type: ignore[arg-type]
        self.refresh_report_history()
        self._set_status(f"JSON kaydedildi: {path.name}", good=True)

    def save_csv(self) -> None:
        if not self._require_result():
            return
        path = save_csv_report(self.result, REPORTS_DIR)  # type: ignore[arg-type]
        self.refresh_report_history()
        self._set_status(f"CSV kaydedildi: {path.name}", good=True)
        self._open_path(path)

    def save_pdf(self) -> None:
        if not self._require_result():
            return
        try:
            path = save_pdf_report(self.result, REPORTS_DIR)  # type: ignore[arg-type]
            self.refresh_report_history()
            self._set_status(f"PDF kaydedildi: {path.name}", good=True)
            self._open_path(path)
        except Exception as exc:  # noqa: BLE001
            messagebox.showerror("PDF oluşturulamadı", str(exc))

    def _require_result(self) -> bool:
        if not self.result:
            messagebox.showinfo("Rapor yok", "Önce bir analiz çalıştırın.")
            return False
        return True

    def refresh_report_history(self) -> None:
        REPORTS_DIR.mkdir(exist_ok=True)
        self.history_paths = sorted(
            list(REPORTS_DIR.glob("*.html")) + list(REPORTS_DIR.glob("*.json")) + list(REPORTS_DIR.glob("*.csv")) + list(REPORTS_DIR.glob("*.pdf")),
            key=lambda p: p.stat().st_mtime,
            reverse=True,
        )[:100]

    def open_reports_folder(self) -> None:
        REPORTS_DIR.mkdir(exist_ok=True)
        self._open_path(REPORTS_DIR)

    def _open_path(self, path: Path) -> None:
        try:
            if sys.platform.startswith("win"):
                os.startfile(str(path))  # type: ignore[attr-defined]
            elif sys.platform == "darwin":
                os.system(f"open {str(path)!r}")
            else:
                os.system(f"xdg-open {str(path)!r}")
        except Exception:
            try:
                webbrowser.open(path.as_uri())
            except Exception:
                pass

    def open_website(self) -> None:
        try:
            webbrowser.open(APP_WEBSITE, new=2)
        except Exception as exc:  # noqa: BLE001
            messagebox.showerror("Site açılamadı", f"{APP_WEBSITE} açılamadı:\n{exc}")

    def show_license(self) -> None:
        text = "Tamer SEO Analyzer kişisel ve ticari projelerde analiz amacıyla kullanılabilir. Yazılım olduğu gibi sunulur; analiz sonuçları teknik kontrol niteliğindedir."
        try:
            if LICENSE_PATH.exists():
                text = LICENSE_PATH.read_text(encoding="utf-8")
        except Exception:
            pass
        messagebox.showinfo("Lisans ve Kullanım", text[:4000])
        self.settings["license_seen"] = True
        self._save_current_settings()

    def show_about(self) -> None:
        self._set_nav_active("Hakkında")
        messagebox.showinfo(
            "Tamer SEO Analyzer",
            f"{APP_NAME} V{APP_VERSION}\n\n"
            "Modern masaüstü SEO analiz ve raporlama programı.\n"
            "Özellikler: çoklu sayfa tarama, teknik SEO kontrolleri, HTML/PDF/CSV/JSON rapor, güncelleme kontrolü.\n\n"
            f"Geliştirici: {APP_DEVELOPER}\n"
            f"Website: {APP_WEBSITE}\n"
            f"{APP_COPYRIGHT}"
        )

    def check_updates(self) -> None:
        update_url = str(self.settings.get("update_url") or UPDATE_INFO_PATH)
        if not update_url.lower().startswith(("http://", "https://", "file://")):
            candidate = Path(update_url)
            if not candidate.is_absolute():
                update_url = str(BASE_DIR / candidate)
        try:
            info = check_for_update(APP_VERSION, update_url)
        except Exception as exc:  # noqa: BLE001
            messagebox.showerror("Güncelleme kontrolü", f"Güncelleme bilgisi okunamadı:\n{exc}")
            return
        if info.get("update_available"):
            messagebox.showinfo(
                "Yeni sürüm mevcut",
                f"Mevcut sürüm: {APP_VERSION}\n"
                f"Yeni sürüm: {info.get('latest_version')}\n\n"
                f"Notlar:\n{info.get('notes') or '-'}\n\n"
                f"İndirme: {info.get('download_url') or '-'}"
            )
        else:
            messagebox.showinfo("Güncelleme kontrolü", f"Program güncel görünüyor.\nMevcut sürüm: {APP_VERSION}")

    def _sum_broken_links(self, pages: list[dict]) -> int:
        return sum(int((p.get("link_report") or {}).get("broken_count") or 0) for p in pages)

    def _sum_missing_alt(self, pages: list[dict]) -> int:
        return sum(len(p.get("missing_alt_images") or []) for p in pages)

    def _average_load_ms(self, pages: list[dict]) -> int | None:
        loads = [int(p.get("load_ms") or 0) for p in pages if p.get("load_ms")]
        if not loads:
            return None
        return int(sum(loads) / len(loads))

    def _format_load(self, ms) -> str:
        try:
            if ms is None:
                return "-"
            return f"{int(ms) / 1000:.2f} sn"
        except Exception:
            return "-"

    def _footer_text(self, total_pages: int) -> str:
        now = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
        duration = "-"
        if self.analysis_started_at:
            seconds = int((datetime.now() - self.analysis_started_at).total_seconds())
            duration = f"00:{seconds // 60:02d}:{seconds % 60:02d}"
        return f"Son tarama: {now}   |   Toplam sayfa: {total_pages}   |   Süre: {duration}"


def main() -> None:
    REPORTS_DIR.mkdir(exist_ok=True)
    ASSETS_DIR.mkdir(exist_ok=True)
    app = TamerSEOAnalyzerApp()
    app.mainloop()


if __name__ == "__main__":
    main()
