#!/usr/bin/env python3
import sys
import os
import urllib.request
import urllib.error
import re
from xml.etree import ElementTree
from urllib.parse import urlparse

SITE_URL = os.environ.get("SEO_TEST_BASE_URL", "http://127.0.0.1:3001").rstrip("/")
PROD_DOMAIN = "skylightchat.com"

TEST_ROUTES = [
    ("/ar", "ar", "منصة واتساب بزنس وأتمتة الذكاء الاصطناعي | سكاي لايت شات"),
    ("/en", "en", "WhatsApp Business API & AI Automation Platform | SkyLight Chat"),
    ("/ar/features", "ar", "مميزات واتساب بزنس وصندوق الوارد والأتمتة | سكاي لايت شات"),
    ("/en/features", "en", "WhatsApp Business Features, AI Inbox & Automation | SkyLight Chat"),
    ("/ar/pricing", "ar", "أسعار أتمتة واتساب بزنس بالريال والدولار | سكاي لايت شات"),
    ("/en/pricing", "en", "WhatsApp Business Automation Pricing (SAR & USD) | SkyLight Chat"),
    ("/ar/resources", "ar", "أدلة واتساب بزنس API وأتمتة الذكاء الاصطناعي | سكاي لايت شات"),
    ("/en/resources", "en", "WhatsApp Business API Guides & AI Automation Playbooks | SkyLight Chat"),
    ("/ar/resources/mena-ai-buyer-guide", "ar", "دليل شراء منصات الذكاء الاصطناعي وواتساب بزنس في الشرق الأوسط (قائمة 2026) | سكاي لايت شات"),
    ("/en/resources/mena-ai-buyer-guide", "en", "MENA AI & WhatsApp Business Platform Buyer Guide (2026 Checklist) | SkyLight Chat"),
    ("/en/resources/ai-quality-checklist", "en", "AI Quality Checklist | SkyLight Chat"),
]

NOINDEX_PATHS = [
    "/en/resources/compare-wati",
    "/en/resources/halla-voice",
    "/en/resources/rule-vs-ai",
    "/en/resources/best-free-ai-web-widget",
    "/en/changelog",
]

def make_request(path, headers=None, follow_redirect=True):
    url = f"{SITE_URL}{path}"
    req = urllib.request.Request(url, headers=headers or {})
    try:
        if not follow_redirect:
            class NoRedirectHandler(urllib.request.HTTPRedirectHandler):
                def redirect_request(self, req, fp, code, msg, hdrs, newurl):
                    return None
            opener = urllib.request.build_opener(NoRedirectHandler)
            res = opener.open(req)
        else:
            res = urllib.request.urlopen(req)
        return res.status, res.read().decode('utf-8', errors='ignore'), res.info()
    except urllib.error.HTTPError as e:
        return e.code, e.read().decode('utf-8', errors='ignore'), e.headers
    except Exception as e:
        return 500, str(e), {}

def test_robots():
    print("Testing robots.txt...")
    status, body, _ = make_request("/robots.txt")
    if status != 200:
        print(f"  [FAIL] robots.txt returned status {status}")
        return False
    if f"Sitemap: https://{PROD_DOMAIN}/sitemap.xml" not in body:
        print("  [FAIL] sitemap URL not found in robots.txt")
        return False
    if "Disallow: /api/" not in body:
        print("  [FAIL] API routes are not disallowed")
        return False
    if "Disallow: /_next/" in body:
        print("  [FAIL] Next.js assets are blocked, preventing crawler rendering")
        return False
    print("  [PASS] robots.txt is correct")
    return True

def test_sitemap():
    print("Testing sitemap.xml...")
    status, body, _ = make_request("/sitemap.xml")
    if status != 200:
        print(f"  [FAIL] sitemap.xml returned status {status}")
        return False
    try:
        # Validate canonical locale URLs and keep noindex comparisons out.
        if "docs.skylightchat.com" in body:
            print("  [WARN] docs.skylightchat.com is still in sitemap.xml (should be separate)")
        # Check alternates
        root = ElementTree.fromstring(body)
        urls = root.findall("{http://www.sitemaps.org/schemas/sitemap/0.9}url")
        if not urls:
            print("  [FAIL] No <url> entries in sitemap")
            return False
        locs = [
            item.findtext("{http://www.sitemaps.org/schemas/sitemap/0.9}loc", "")
            for item in urls
        ]
        invalid = [
            loc for loc in locs
            if not re.match(rf"^https://{re.escape(PROD_DOMAIN)}/(?:ar|en)(?:/|$)", loc)
        ]
        if invalid:
            print(f"  [FAIL] Non-localized sitemap URLs: {invalid[:5]}")
            return False
        if any("/resources/compare-" in loc for loc in locs):
            print("  [FAIL] noindex generated comparisons are present in sitemap")
            return False
        if any(any(loc.endswith(path) for loc in locs) for path in NOINDEX_PATHS):
            print("  [FAIL] a noindex URL is present in sitemap")
            return False
        if len(locs) != len(set(locs)):
            print("  [FAIL] duplicate sitemap URLs found")
            return False
        print(f"  [PASS] sitemap.xml is valid with {len(urls)} URLs")
        return True
    except Exception as e:
        print(f"  [FAIL] failed to parse sitemap.xml: {e}")
        return False

def test_routes():
    all_pass = True
    print("\nTesting localized routes...")
    for path, lang, expected_title in TEST_ROUTES:
        print(f"Checking {path} ({lang})...")
        status, body, headers = make_request(path)
        if status != 200:
            print(f"  [FAIL] Status is {status}")
            all_pass = False
            continue

        # Check lang attribute
        html_tag = re.search(r'<html[^>]*lang=["\']([^"\'\s]+)["\']', body)
        if not html_tag or html_tag.group(1) != lang:
            found_lang = html_tag.group(1) if html_tag else "not found"
            print(f"  [FAIL] Expected HTML lang='{lang}', found '{found_lang}'")
            all_pass = False

        # Check canonical
        canonical = re.search(r'<link[^>]*rel=["\']canonical["\'][^>]*href=["\']([^"\']+)["\']', body)
        if not canonical:
            canonical = re.search(r'href=["\']([^"\']+)["\'][^>]*rel=["\']canonical["\']', body)
        expected_canonical = f"https://{PROD_DOMAIN}{path}"
        if not canonical or canonical.group(1) != expected_canonical:
            found_canonical = canonical.group(1) if canonical else "not found"
            print(f"  [FAIL] Expected canonical '{expected_canonical}', found '{found_canonical}'")
            all_pass = False
        else:
            print(f"  [PASS] Canonical matches exactly: {expected_canonical}")

        # Check hreflangs
        hreflangs = []
        for match in re.finditer(r'<link[^>]+rel=["\']alternate["\'][^>]*>', body):
            link_tag = match.group(0)
            lang_match = re.search(r'hreflang=["\']([^"\']+)["\']', link_tag, re.IGNORECASE)
            href_match = re.search(r'href=["\']([^"\']+)["\']', link_tag, re.IGNORECASE)
            if lang_match and href_match:
                hreflangs.append((lang_match.group(1), href_match.group(1)))

        expected_ar = f"https://{PROD_DOMAIN}{path.replace('/en', '/ar') if lang == 'en' else path}"
        expected_en = f"https://{PROD_DOMAIN}{path.replace('/ar', '/en') if lang == 'ar' else path}"
        
        has_ar = any(h[0] == "ar-SA" and h[1] == expected_ar for h in hreflangs)
        has_en = any(h[0] == "en-US" and h[1] == expected_en for h in hreflangs)
        has_default = any(h[0] == "x-default" and h[1] == expected_ar for h in hreflangs)

        if not (has_ar and has_en and has_default):
            print(f"  [FAIL] hreflang cluster incomplete or incorrect on {path}")
            print(f"    found: {hreflangs}")
            print(f"    expected: ar-SA={expected_ar}, en-US={expected_en}, x-default={expected_ar}")
            all_pass = False
        else:
            print("  [PASS] hreflangs correctly configured")

        # Rendered internal links must already be localized, not rely on a 301.
        bare_links = []
        for href in re.findall(r'href=["\']([^"\']+)["\']', body):
            if not href.startswith("/"):
                continue
            if re.match(r"^/(?:ar|en)(?:/|[?#]|$)", href):
                continue
            if href.startswith(("/assets/", "/api/", "/_next/")):
                continue
            if href in ("/favicon.ico", "/manifest.webmanifest"):
                continue
            bare_links.append(href)
        if bare_links:
            print(f"  [FAIL] Bare internal links found: {sorted(set(bare_links))[:10]}")
            all_pass = False

    return all_pass

def redirect_path(path, headers=None):
    status, _, response_headers = make_request(
        path, headers=headers, follow_redirect=False
    )
    location = response_headers.get("Location", "")
    parsed = urlparse(location)
    return status, f"{parsed.path}{'?' + parsed.query if parsed.query else ''}"

def test_redirects():
    print("\nTesting deterministic one-hop redirects...")
    cases = [
        ("/", {}, "/ar"),
        ("/features", {}, "/ar/features"),
        ("/features", {"Cookie": "skylight_lang=en"}, "/ar/features"),
        ("/features?lang=en", {}, "/en/features"),
        ("/features/?lang=en", {}, "/en/features"),
        ("/ar/features?lang=en", {}, "/ar/features"),
        ("/en/features?lang=ar", {}, "/en/features"),
        ("/en/features/", {}, "/en/features"),
        ("/tools", {}, "/ar/tools/whatsapp-number-checker"),
        ("/tools?lang=en", {}, "/en/tools/whatsapp-number-checker"),
        ("/ar/tools", {}, "/ar/tools/whatsapp-number-checker"),
        ("/ar/tools/", {}, "/ar/tools/whatsapp-number-checker"),
        ("/en/tools", {}, "/en/tools/whatsapp-number-checker"),
        ("/archive", {}, "/ar/archive"),
    ]
    all_pass = True
    for path, headers, expected in cases:
        status, location = redirect_path(path, headers)
        if status != 301 or location != expected:
            print(f"  [FAIL] {path} -> {status} {location!r}; expected 301 {expected!r}")
            all_pass = False
        else:
            print(f"  [PASS] {path} -> {expected}")
    return all_pass

def test_canonical_origin():
    print("\nTesting one-hop canonical host and protocol redirects...")
    cases = [
        (
            "/en/features/?lang=ar",
            {"Host": "www.skylightchat.com", "X-Forwarded-Proto": "https"},
            "https://skylightchat.com/en/features",
        ),
        (
            "/features?lang=en",
            {"Host": "skylightchat.com", "X-Forwarded-Proto": "http"},
            "https://skylightchat.com/en/features",
        ),
    ]
    all_pass = True
    for path, headers, expected in cases:
        status, _, response_headers = make_request(
            path, headers=headers, follow_redirect=False
        )
        location = response_headers.get("Location", "")
        if status != 301 or location != expected:
            print(f"  [FAIL] {path} -> {status} {location!r}; expected {expected!r}")
            all_pass = False
        else:
            print(f"  [PASS] {path} -> {expected}")
    return all_pass

def test_quality_guards():
    print("\nTesting indexability and localized content guards...")
    all_pass = True

    for path in NOINDEX_PATHS:
        status, body, _ = make_request(path)
        robots = re.search(r'<meta[^>]*name=["\']robots["\'][^>]*content=["\']([^"\']+)', body)
        directives = robots.group(1).lower() if robots else ""
        if status != 200 or "noindex" not in directives or "follow" not in directives:
            print(f"  [FAIL] expected noindex,follow on {path}")
            all_pass = False
        else:
            print(f"  [PASS] noindex,follow on {path}")

    status, body, _ = make_request("/en/resources/ai-quality-checklist")
    robots = re.search(r'<meta[^>]*name=["\']robots["\'][^>]*content=["\']([^"\']+)', body)
    if status != 200 or (robots and "noindex" in robots.group(1).lower()):
        print("  [FAIL] reviewed article is unexpectedly noindex")
        all_pass = False
    else:
        print("  [PASS] reviewed article remains indexable")

    localized_markers = [
        ("/en/halla", "Halla AI voice and missed-call recovery"),
        ("/ar/halla", "هلا: نظام المكالمات الذكية"),
        ("/en/integrations/zid", "Connect Zid with WhatsApp Business"),
        ("/ar/integrations/zid", "ربط متجر زد مع واتساب"),
    ]
    for path, marker in localized_markers:
        status, body, _ = make_request(path)
        if status != 200 or marker not in body:
            print(f"  [FAIL] expected localized content missing on {path}")
            all_pass = False
        else:
            print(f"  [PASS] localized content rendered on {path}")

    return all_pass

if __name__ == "__main__":
    success = True
    success &= test_robots()
    success &= test_sitemap()
    success &= test_routes()
    success &= test_redirects()
    success &= test_canonical_origin()
    success &= test_quality_guards()
    if not success:
        print("\n[FAIL] Some SEO recovery smoke tests failed!")
        sys.exit(1)
    else:
        print("\n[SUCCESS] All SEO recovery smoke tests passed!")
