#!/usr/bin/env python3
"""
SentinelScan - Modular Cybersecurity Scanner
Main entry point for the project.
"""

import argparse
import sys
import os
import json
import logging
import yaml
from sentinelscan.modules import port_scanner, subdomain, web_recon, vuln_checks

# ============================================================
# ASCII Banner
# ============================================================

BANNER = r"""
   ____            _        _        ____                 
  / ___|  ___ _ __(_)_ __  | |_ ___ |  _ \  ___  ___ _ __ 
  \___ \ / __| '__| | '_ \ | __/ _ \| | | |/ _ \/ _ \ '__|
   ___) | (__| |  | | |_) || || (_) | |_| |  __/  __/ |   
  |____/ \___|_|  |_| .__/  \__\___/|____/ \___|\___|_|   
                    |_|                                   
"""

# ============================================================
# Logging Setup
# ============================================================

def setup_logging():
    """Configure logging system."""
    ensure_directory("reports")
    log_file = os.path.join("reports", "scan.log")
    logging.basicConfig(
        filename=log_file,
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s - %(message)s",
    )
    logging.info("SentinelScan started.")


# ============================================================
# Helper Functions
# ============================================================

def print_banner():
    """Prints the ASCII banner."""
    print(BANNER)


def validate_port_range(port_range: str):
    """Validate and parse port range string."""
    try:
        start_port, end_port = map(int, port_range.split("-"))
        if start_port < 1 or end_port > 65535 or start_port > end_port:
            raise ValueError("Invalid port range")
        return start_port, end_port
    except Exception:
        print("[!] Error: Invalid port range format. Use start-end (e.g., 1-1000).")
        sys.exit(1)


def ensure_directory(path: str):
    """Ensure a directory exists, create if missing."""
    if not os.path.exists(path):
        os.makedirs(path)


def save_report(filename: str, content: str):
    """Save report content to file."""
    ensure_directory("reports")
    filepath = os.path.join("reports", filename)
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(content)
    print(f"[+] Report saved to {filepath}")
    logging.info(f"Report saved: {filepath}")


def load_config():
    """Load configuration from config.yaml if available."""
    config_file = "config.yaml"
    if os.path.exists(config_file):
        with open(config_file, "r", encoding="utf-8") as f:
            config = yaml.safe_load(f)
        logging.info("Config loaded from config.yaml")
        return config
    return {}


# ============================================================
# CLI Argument Parser
# ============================================================

def build_parser():
    """Builds the CLI parser."""
    parser = argparse.ArgumentParser(
        description="SentinelScan - Modular Cybersecurity Scanner"
    )

    parser.add_argument("-t", "--target", help="Target host/domain to scan")
    parser.add_argument("-p", "--ports", default="1-100", help="Port range (e.g., 1-1000)")
    parser.add_argument("--subdomains", action="store_true", help="Enable subdomain enumeration")
    parser.add_argument("--web", action="store_true", help="Enable web reconnaissance")
    parser.add_argument("--vuln", action="store_true", help="Enable basic vulnerability checks")
    parser.add_argument("--output", help="Output report filename (e.g., report.json)")
    parser.add_argument("--format", choices=["json", "txt", "html"], default="txt", help="Report format")
    parser.add_argument("--interactive", action="store_true", help="Run in interactive mode")

    return parser


# ============================================================
# Interactive Mode
# ============================================================

def interactive_mode():
    """Interactive menu-driven mode."""
    print("\n[Interactive Mode]")
    target = input("Enter target host/domain: ").strip()
    ports = input("Enter port range (e.g., 1-1000): ").strip() or "1-100"
    subdomains = input("Run subdomain scan? (y/n): ").lower() == "y"
    web = input("Run web recon? (y/n): ").lower() == "y"
    vuln = input("Run vulnerability checks? (y/n): ").lower() == "y"
    output = input("Output filename (leave blank for none): ").strip()
    fmt = input("Report format (txt/json/html): ").strip() or "txt"

    return argparse.Namespace(
        target=target,
        ports=ports,
        subdomains=subdomains,
        web=web,
        vuln=vuln,
        output=output if output else None,
        format=fmt,
        interactive=True,
    )


# ============================================================
# Reporting
# ============================================================

def generate_report(results, fmt="txt"):
    """Generate report in specified format."""
    if fmt == "txt":
        report_content = ""
        for section, data in results:
            report_content += f"\n=== {section} ===\n"
            for item in data:
                report_content += f"{item}\n"
        return report_content

    elif fmt == "json":
        return json.dumps({sec: dat for sec, dat in results}, indent=4)

    elif fmt == "html":
        html_content = "<html><body><h1>SentinelScan Report</h1>"
        for section, data in results:
            html_content += f"<h2>{section}</h2><ul>"
            for item in data:
                html_content += f"<li>{item}</li>"
            html_content += "</ul>"
        html_content += "</body></html>"
        return html_content

    return ""


# ============================================================
# Main Execution Flow
# ============================================================

def main():
    """Main function for SentinelScan."""
    print_banner()
    setup_logging()
    parser = build_parser()
    args = parser.parse_args()

    if args.interactive:
        args = interactive_mode()

    config = load_config()
    results = []

    # Port Scanner
    start_port, end_port = validate_port_range(args.ports)
    print(f"[*] Running Port Scanner on {args.target} ({start_port}-{end_port})...")
    port_results = port_scanner.scan_ports(args.target, start_port, end_port)
    results.append(("Ports", port_results))

    # Subdomain Finder
    if args.subdomains:
        print(f"[*] Running Subdomain Finder on {args.target}...")
        subdomain_results = subdomain.find_subdomains(args.target)
        results.append(("Subdomains", subdomain_results))

    # Web Recon
    if args.web:
        print(f"[*] Running Web Recon on {args.target}...")
        web_results = web_recon.analyze_headers(args.target)
        results.append(("Web Recon", web_results))

    # Vulnerability Checks
    if args.vuln:
        print(f"[*] Running Vulnerability Checks on {args.target}...")
        vuln_results = vuln_checks.run_checks(args.target)
        results.append(("Vulnerabilities", vuln_results))

    # Reporting
    if args.output:
        report_content = generate_report(results, args.format)
        save_report(args.output, report_content)

    print("[+] Scan complete.")
    logging.info("Scan complete.")


# ============================================================
# Entry Point
# ============================================================

if __name__ == "__main__":
    main()
cd