#!/usr/bin/env python3
"""
LandingForge — Complete Python Static Landing Page Generator
Generates a production-ready, SEO-optimized static landing page from config.yaml
"""

import argparse
import logging
import os
import sys
from pathlib import Path

import yaml

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    datefmt="%H:%M:%S",
)
logger = logging.getLogger("landingforge")


def load_config(config_path: str) -> dict:
    """Load and validate the YAML configuration file."""
    config_file = Path(config_path)
    if not config_file.exists():
        logger.error("Configuration file not found: %s", config_path)
        sys.exit(1)
    with open(config_file, "r", encoding="utf-8") as f:
        cfg = yaml.safe_load(f)
    if not isinstance(cfg, dict):
        logger.error("Invalid configuration file: must be a YAML mapping.")
        sys.exit(1)
    # Validate required keys
    for required in ("site", "keywords", "design", "content"):
        if required not in cfg:
            logger.error("Missing required config section: '%s'", required)
            sys.exit(1)
    return cfg


def create_directory_structure(output_dir: str, languages: list, default_lang: str) -> None:
    """Create all required directories in the output path."""
    dirs = [
        "assets/css",
        "assets/js",
        "assets/fonts/inter-v13-latin",
        "assets/fonts/jetbrains-mono",
        "assets/images",
        "assets/webfonts",
        "includes",
        "deploy",
    ]
    for lang in languages:
        code = lang.get("code", "en")
        if code != default_lang:
            dirs.append(f"lang/{code}")

    for d in dirs:
        full = os.path.join(output_dir, d)
        os.makedirs(full, exist_ok=True)
        logger.debug("Created directory: %s", full)


def write_file(output_dir: str, relative_path: str, content, mode: str = "w") -> int:
    """Write content to a file and return the number of bytes written."""
    full_path = os.path.join(output_dir, relative_path)
    os.makedirs(os.path.dirname(full_path), exist_ok=True)
    if mode == "wb":
        with open(full_path, "wb") as f:
            f.write(content)
        return len(content)
    else:
        encoded = content.encode("utf-8") if isinstance(content, str) else content
        with open(full_path, "w", encoding="utf-8") as f:
            f.write(content if isinstance(content, str) else content.decode("utf-8"))
        return len(encoded)


def format_size(size_bytes: int) -> str:
    """Format a byte count as a human-readable string."""
    if size_bytes < 1024:
        return f"{size_bytes} B"
    if size_bytes < 1024 * 1024:
        return f"{size_bytes / 1024:.1f} KB"
    return f"{size_bytes / (1024 * 1024):.2f} MB"


def main():
    parser = argparse.ArgumentParser(
        description="LandingForge — Static Landing Page Generator",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  python landingforge.py
  python landingforge.py --config my-config.yaml --output /var/www/mysite
  python landingforge.py --skip-deploy --skip-assets
        """,
    )
    parser.add_argument(
        "--config",
        default="config.yaml",
        help="Path to YAML configuration file (default: config.yaml)",
    )
    parser.add_argument(
        "--output",
        default=None,
        help="Output directory (default: deployment.output_dir from config, or ./)",
    )
    parser.add_argument(
        "--skip-deploy",
        action="store_true",
        help="Skip generating Apache/Certbot deployment files",
    )
    parser.add_argument(
        "--skip-assets",
        action="store_true",
        help="Skip downloading fonts and icons (use fallbacks)",
    )
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="Enable verbose/debug logging",
    )
    args = parser.parse_args()

    if args.verbose:
        logging.getLogger().setLevel(logging.DEBUG)

    # ── Load configuration ────────────────────────────────────────────────
    logger.info("Loading configuration from: %s", args.config)
    config = load_config(args.config)

    deployment_cfg = config.get("deployment", {})
    output_dir = args.output or deployment_cfg.get("output_dir", "./")
    output_dir = os.path.abspath(output_dir)
    os.makedirs(output_dir, exist_ok=True)
    logger.info("Output directory: %s", output_dir)

    languages_cfg = config.get("languages", {})
    supported_langs = languages_cfg.get("supported", [{"code": "en", "name": "English"}])
    default_lang = languages_cfg.get("default", "en")

    # ── Create directory structure ────────────────────────────────────────
    logger.info("Creating directory structure...")
    create_directory_structure(output_dir, supported_langs, default_lang)

    # Track generated files for summary
    generated_files = []

    def track_write(rel_path: str, content, mode: str = "w") -> None:
        size = write_file(output_dir, rel_path, content, mode=mode)
        generated_files.append((rel_path, size))
        logger.info("  ✓ %-45s %s", rel_path, format_size(size))

    # ── Instantiate generators ────────────────────────────────────────────
    from generators.html_generator import HTMLGenerator  # noqa: PLC0415
    from generators.css_generator import CSSGenerator    # noqa: PLC0415
    from generators.js_generator import JSGenerator      # noqa: PLC0415
    from generators.php_generator import PHPGenerator    # noqa: PLC0415
    from generators.seo_generator import SEOGenerator    # noqa: PLC0415
    from generators.asset_generator import AssetGenerator  # noqa: PLC0415
    from generators.deploy_generator import DeployGenerator  # noqa: PLC0415

    html_gen   = HTMLGenerator(config)
    css_gen    = CSSGenerator(config)
    js_gen     = JSGenerator(config)
    php_gen    = PHPGenerator(config)
    seo_gen    = SEOGenerator(config)
    asset_gen  = AssetGenerator(config)
    deploy_gen = DeployGenerator(config)

    # ── Generate HTML pages ───────────────────────────────────────────────
    logger.info("Generating HTML pages...")
    track_write("index.html", html_gen.generate_index())
    track_write("about.html", html_gen.generate_about())
    track_write("privacy.html", html_gen.generate_privacy())
    track_write("terms.html", html_gen.generate_terms())
    track_write("cookies.html", html_gen.generate_cookies())

    # ── Generate language versions ────────────────────────────────────────
    logger.info("Generating multi-language pages...")
    for lang in supported_langs:
        code = lang.get("code", "en")
        if code != default_lang:
            track_write(f"lang/{code}/index.html", html_gen.generate_index(lang=code, is_lang_version=True))

    # ── Generate PHP files ────────────────────────────────────────────────
    logger.info("Generating PHP files...")
    track_write("index.php", php_gen.generate_index_php())
    track_write("includes/detect-language.php", php_gen.generate_language_detection_php())
    track_write("includes/redirect.php", php_gen.generate_redirect_php())

    # ── Generate CSS ──────────────────────────────────────────────────────
    logger.info("Generating CSS files...")
    track_write("assets/css/main.css", css_gen.generate_main_css())
    track_write("assets/css/responsive.css", css_gen.generate_responsive_css())
    track_write("assets/css/animations.css", css_gen.generate_animations_css())

    # ── Generate JavaScript ───────────────────────────────────────────────
    logger.info("Generating JavaScript files...")
    track_write("assets/js/main.js", js_gen.generate_main_js())
    track_write("assets/js/hero-animations.js", js_gen.generate_hero_js())
    track_write("assets/js/language-switcher.js", js_gen.generate_language_switcher_js())
    track_write("assets/js/cookie-consent.js", js_gen.generate_cookie_consent_js())
    track_write("assets/js/wow.min.js", js_gen.generate_wow_js())

    # ── Generate SEO files ────────────────────────────────────────────────
    logger.info("Generating SEO files...")
    track_write("sitemap.xml", seo_gen.generate_sitemap())
    track_write("robots.txt", seo_gen.generate_robots())
    track_write(".htaccess", seo_gen.generate_htaccess())
    track_write("manifest.json", seo_gen.generate_manifest())
    track_write("browserconfig.xml", seo_gen.generate_browserconfig())

    # ── Generate assets ───────────────────────────────────────────────────
    logger.info("Generating image assets...")
    # OG image
    og_image_data = asset_gen.generate_og_image()
    track_write("assets/images/og-default.jpg", og_image_data, mode="wb")

    # Favicons
    favicons = asset_gen.generate_favicon()
    for fname, data in favicons.items():
        track_write(f"assets/images/{fname}", data, mode="wb")

    # Placeholder SVGs
    svgs = asset_gen.generate_placeholder_svgs()
    for fname, svg_content in svgs.items():
        track_write(f"assets/images/{fname}", svg_content)

    # Fonts (download or fallback)
    if not args.skip_assets:
        logger.info("Downloading/bundling fonts...")
        try:
            asset_gen.download_google_fonts(output_dir)
            logger.info("  ✓ Fonts processed (see assets/fonts/)")
            generated_files.append(("assets/fonts/", 0))
        except Exception as exc:
            logger.warning("Font download failed: %s — using fallback CSS.", exc)
            # Write fallback CSS so pages still render
            fallback_inter = asset_gen._inter_css_fallback()
            fallback_jb = asset_gen._jetbrains_css_fallback()
            write_file(output_dir, "assets/fonts/inter-v13-latin/inter-v13-latin.css", fallback_inter)
            write_file(output_dir, "assets/fonts/jetbrains-mono/jetbrains-mono.css", fallback_jb)

        logger.info("Bundling Font Awesome...")
        try:
            fa_css = asset_gen.bundle_fontawesome(output_dir)
            track_write("assets/css/fontawesome.min.css", fa_css)
        except Exception as exc:
            logger.warning("Font Awesome bundle failed: %s — using fallback.", exc)
            fa_css = asset_gen._fontawesome_fallback_css()
            track_write("assets/css/fontawesome.min.css", fa_css)
    else:
        logger.info("Skipping asset downloads (--skip-assets).")
        # Write fallback font CSS
        write_file(output_dir, "assets/fonts/inter-v13-latin/inter-v13-latin.css",
                   asset_gen._inter_css_fallback())
        write_file(output_dir, "assets/fonts/jetbrains-mono/jetbrains-mono.css",
                   asset_gen._jetbrains_css_fallback())
        fa_css = asset_gen._fontawesome_fallback_css()
        track_write("assets/css/fontawesome.min.css", fa_css)

    # ── Generate deployment files ─────────────────────────────────────────
    if not args.skip_deploy:
        logger.info("Generating deployment files...")
        track_write("deploy/apache-vhost.conf", deploy_gen.generate_apache_vhost())
        ssl_script = deploy_gen.generate_ssl_setup()
        track_write("deploy/setup-ssl.sh", ssl_script)
        # Make SSL script executable
        ssl_path = os.path.join(output_dir, "deploy", "setup-ssl.sh")
        os.chmod(ssl_path, 0o755)
    else:
        logger.info("Skipping deployment files (--skip-deploy).")

    # ── Print summary ─────────────────────────────────────────────────────
    total_size = sum(size for _, size in generated_files)
    print("\n" + "=" * 60)
    print("  LandingForge — Generation Complete")
    print("=" * 60)
    print(f"  Output directory : {output_dir}")
    print(f"  Files generated  : {len(generated_files)}")
    print(f"  Total size       : {format_size(total_size)}")
    print("=" * 60)
    print()

    # ── Deployment prompt ─────────────────────────────────────────────────
    apache_cfg = deployment_cfg.get("apache", {})
    certbot_cfg = deployment_cfg.get("certbot", {})
    if (
        not args.skip_deploy
        and apache_cfg.get("enabled", False)
        and certbot_cfg.get("enabled", False)
    ):
        domain = config["site"]["domain"]
        doc_root = apache_cfg.get("document_root", f"/var/www/{domain}")
        print(f"  Next steps:")
        print(f"  1. Copy site files to server: rsync -avz {output_dir}/ root@{domain}:{doc_root}/")
        print(f"  2. Copy vhost config:         cp {output_dir}/deploy/apache-vhost.conf /etc/apache2/sites-available/{domain}.conf")
        print(f"  3. Run SSL setup:             sudo bash {output_dir}/deploy/setup-ssl.sh")
        print()

    logger.info("Done! 🚀")


if __name__ == "__main__":
    main()
