#!/usr/bin/env python3
"""
Unbound Blocklist Configuration Generator (Python version)

- Downloads the BlacklistedDomains.txt list from GitHub.
- Converts each domain into an Unbound `local-zone` entry.
- Writes the result to `unboundadblock.conf`.
- Removes the temporary file and prints a summary.
"""

import urllib.request
import sys
from pathlib import Path
from datetime import datetime

# ----------------------------------------------------------------------
# Configuration
# ----------------------------------------------------------------------
BLOCKLIST_URL = (
    "https://raw.githubusercontent.com/bongochong/CombinedPrivacyBlockLists/"
    "master/NoFormatting/BlacklistedDomains.txt"
)
SCRIPT_DIR = Path(__file__).resolve().parent
OUTPUT_FILE = SCRIPT_DIR / "unboundadblock.conf"
TEMP_FILE = SCRIPT_DIR / "blacklisted_domains.txt"


def download_blocklist(url: str, dest: Path) -> None:
    """Download the blocklist to ``dest``."""
    print("Step 1: Downloading blocklist from GitHub...")
    print(f"URL: {url}\n")
    try:
        with urllib.request.urlopen(url) as resp, dest.open("wb") as out:
            out.write(resp.read())
    except Exception as exc:
        print(f"ERROR: Failed to download the blocklist – {exc}")
        sys.exit(1)

    if not dest.is_file():
        print(f"ERROR: Downloaded file not found at {dest}")
        sys.exit(1)

    print(f"SUCCESS: Blocklist downloaded to {dest}\n")


def process_blocklist(src: Path, dst: Path) -> int:
    """Read domains from ``src`` and write Unbound config entries to ``dst``.
    Returns the number of processed domains."""
    print("Step 2: Processing the downloaded file...")
    print("Converting domains into Unbound configuration format...\n")

    header_lines = [
        "# Unbound Blocklist Configuration",
        f"# Generated from: {BLOCKLIST_URL}",
        f"# Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
        f"# Generated by: {Path(__file__).name}",
        "",
    ]

    dst.write_text("\n".join(header_lines) + "\n")

    processed = 0
    with src.open("r", encoding="utf-8") as fin, dst.open("a", encoding="utf-8") as fout:
        for line in fin:
            domain = line.strip()
            # Skip empty lines and comment lines
            if not domain or domain.startswith("#"):
                continue

            # Write the Unbound entry
            fout.write(f'local-zone: "{domain}" static\n')
            # If you also want an A‑record pointing to 0.0.0.0, uncomment:
            # fout.write(f'local-data: "{domain} A 0.0.0.0"\n')
            processed += 1

            if processed % 100 == 0:
                print(f"Processed {processed} domains...")

    return processed


def cleanup(temp_path: Path) -> None:
    """Remove the temporary file."""
    print("\nStep 3: Cleaning up temporary files...")
    try:
        temp_path.unlink()
        print("Temporary file removed.")
    except FileNotFoundError:
        print("Temporary file already gone.")
    except Exception as exc:
        print(f"Warning: could not delete temporary file – {exc}")


def main() -> None:
    print("=" * 45)
    print("Unbound Blocklist Configuration Generator")
    print("=" * 45, "\n")

    download_blocklist(BLOCKLIST_URL, TEMP_FILE)
    count = process_blocklist(TEMP_FILE, OUTPUT_FILE)
    cleanup(TEMP_FILE)

    print("\n" + "=" * 45)
    print("Configuration Generation Complete!")
    print("=" * 45)
    print(f"Output file: {OUTPUT_FILE}")
    print(f"Total domains processed: {count}")
    print(f"Total configuration entries created: {count * 1}")  # one entry per domain
    print("\nTo use this file, add the following line to your unbound.conf:")
    print(f"include: {OUTPUT_FILE}\n")


if __name__ == "__main__":
    main()
