import os
import csv
import requests
import time
from datetime import datetime

class FirewallChecker:
    def __init__(self):
        self.csv_file = "./training_data_en.csv"
        self.results_dir = "./results"
        os.makedirs(self.results_dir, exist_ok=True)
        self.categories = []
        self.records = []
        self._load_csv()

    def _load_csv(self):
        if not os.path.exists(self.csv_file):
            return
        with open(self.csv_file, newline="", encoding="utf-8") as f:
            reader = csv.reader(f)
            for row in reader:
                if len(row) < 6:
                    continue
                url_raw     = row[2].strip().strip('"')
                category    = row[3].strip().strip('"')
                description = row[5].strip().strip('"')
                url = url_raw if url_raw.startswith(("http://","https://")) else "http://"+url_raw
                self.records.append({
                    "url": url,
                    "category": category,
                    "description": description
                })
                if category not in self.categories:
                    self.categories.append(category)
        self.categories.sort()

    def print_menu(self):
        print("\n" + "="*60)
        print("🔥 FIREWALL & WEBSITE ACCESSIBILITY CHECKER 🔥")
        print("="*60)
        print(f"Data file: {'✓ found' if os.path.exists(self.csv_file) else '✗ missing'}")
        print("="*60)
        print("1. 📋 Show Categories")
        print("2. 📂 List URLs in Category")
        print("3. 🌐 Test Category Accessibility")
        print("4. 🎯 Test Single URL")
        print("5. 📝 Show Description for a URL")
        print("6. 🚀 Test ALL URLs & Save Results")
        print("7. 🔍 Show CSV Structure")
        print("8. ❌ Exit")
        print("="*60)

    def show_categories(self):
        print("\n📋 AVAILABLE CATEGORIES")
        for i, cat in enumerate(self.categories,1):
            print(f"{i:3d}. {cat}")
        print(f"\nTotal: {len(self.categories)}")
        input("\nPress Enter to continue...")

    def list_urls(self, category):
        return [r["url"] for r in self.records if r["category"]==category]

    def _save_results(self, details, action_label):
        ts = datetime.now().strftime("%Y%m%d_%H%M%S")
        fname = os.path.join(self.results_dir, f"results_{action_label.split('/')[0]}_{ts}.txt")
        with open(fname, "w", encoding="utf-8") as f:
            for url, ok in details:
                status = "REACHABLE" if ok else "BLOCKED"
                f.write(f"{url}\t{status}\n")
        print(f"\n✅ Results saved to {fname}")

    def test_urls(self, urls, action_label):
        reachable=unreachable=0
        details=[]
        print(f"\nTesting {len(urls)} URLs...")
        for i,url in enumerate(urls,1):
            try:
                r = requests.get(url, timeout=5)
                ok = (r.status_code==200)
            except:
                ok = False
            sym = "✓" if ok else "✗"
            print(f"[{i:4d}/{len(urls):4d}] {sym} {url}")
            reachable += ok
            unreachable += not ok
            details.append((url, ok))
            time.sleep(0.1)
        total = reachable+unreachable
        pct = (reachable/total*100) if total else 0
        print("\n📊 SUMMARY")
        print(f"  Tested:      {total}")
        print(f"  Reachable:   {reachable}")
        print(f"  Unreachable: {unreachable}")
        print(f"  Success rate:{pct:.1f}%")
        self._save_results(details, action_label)
        input("\nPress Enter to continue...")

    def test_single(self):
        url = input("Enter URL: ").strip()
        if not url:
            print("❌ No URL."); input("\nEnter to continue..."); return
        if not url.startswith(("http://","https://")):
            url = "http://"+url
        print(f"\n▶ Testing {url}")
        try:
            start = time.time()
            r = requests.get(url, timeout=10)
            elapsed = (time.time()-start)*1000
            ok = (r.status_code==200)
            print(f"Status: {r.status_code} {r.reason}")
            print(f"Time:   {elapsed:.1f} ms")
            print(f"Length: {len(r.content)} bytes")
        except Exception as e:
            ok = False
            print(f"Error: {e}")
        self._save_results([(url, ok)], "single")
        input("\nPress Enter to continue...")

    def show_description(self):
        url = input("Enter URL: ").strip()
        rec = next((r for r in self.records if r["url"].rstrip("/")==url.rstrip("/")), None)
        if not rec:
            print("❌ URL not found.")
        else:
            print(f"\n🔖 Description:\n{rec['description']}")
        input("\nPress Enter to continue...")

    def show_csv_structure(self):
        with open(self.csv_file, newline="", encoding="utf-8") as f:
            reader = csv.reader(f)
            first = next(reader, None)
        print("\n🔍 CSV STRUCTURE")
        for i,col in enumerate(first or []):
            print(f" {i}: {col}")
        input("\nPress Enter to continue...")

    def test_all_and_save(self):
        urls = [r["url"] for r in self.records]
        self.test_urls(urls, "all")

    def run(self):
        if not os.path.exists(self.csv_file):
            print("❌ training_data_en.csv missing"); return
        while True:
            self.print_menu()
            c = input("Choose (1-8): ").strip()
            if c=="1": self.show_categories()
            elif c=="2":
                idx = int(input("Category #: ")) -1
                if 0<=idx<len(self.categories):
                    for u in self.list_urls(self.categories[idx]):
                        print(u)
                input("\nPress Enter to continue...")
            elif c=="3":
                idx = int(input("Category #: ")) -1
                if 0<=idx<len(self.categories):
                    self.test_urls(self.list_urls(self.categories[idx]),
                                   f"category_{self.categories[idx].replace(' ','_')}")
            elif c=="4": self.test_single()
            elif c=="5": self.show_description()
            elif c=="6": self.test_all_and_save()
            elif c=="7": self.show_csv_structure()
            elif c=="8": break
            else:
                print("❌ Invalid choice"); input("\nPress Enter to continue...")

if __name__=="__main__":
    FirewallChecker().run()
