#!/usr/bin/env python3
"""
SEO Audit: Image Alt Text Checker
Extracts all images from pages and checks for missing/empty alt text.
Machine-verified — no AI interpretation.

Usage: python3 images.py <domain> <sitemap_url> <output_dir>
"""
import xml.etree.ElementTree as ET
import urllib.request
import ssl
import sys
import csv
import time
import re
import json
import os


def fetch_url(url, timeout=15):
    ctx = ssl.create_default_context()
    req = urllib.request.Request(url, headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    })
    try:
        resp = urllib.request.urlopen(req, timeout=timeout, context=ctx)
        return resp.getcode(), resp.read().decode('utf-8', errors='replace')
    except:
        return 0, ''


def get_sitemap_urls(sitemap_url):
    try:
        req = urllib.request.Request(sitemap_url, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
        ctx = ssl.create_default_context()
        resp = urllib.request.urlopen(req, timeout=15, context=ctx)
        content = resp.read().decode('utf-8')
        content = re.sub(r'\sxmlns="[^"]+"', '', content, count=1)
        root = ET.fromstring(content)
        urls = []
        for sitemap in root.findall('.//sitemap/loc'):
            urls.extend(get_sitemap_urls(sitemap.text.strip()))
        for url_elem in root.findall('.//url/loc'):
            urls.append(url_elem.text.strip())
        return urls
    except:
        return []


def extract_images(html, page_url):
    """Extract all img tags with their alt text and src."""
    imgs = re.findall(r'<img\s([^>]*?)/?>', html, re.DOTALL)
    results = []
    for img_attrs in imgs:
        src = re.search(r'src="([^"]*)"', img_attrs)
        alt = re.search(r'alt="([^"]*)"', img_attrs)
        src_val = src.group(1) if src else ''

        # Skip tracking pixels, SVGs, data URIs
        if any(x in src_val.lower() for x in ['1x1', 'pixel', '.svg', 'data:image', 'beacon', 'spacer']):
            continue

        has_alt = alt is not None
        alt_val = alt.group(1).strip() if alt else None
        alt_empty = has_alt and alt_val == ''

        status = 'good' if has_alt and not alt_empty else ('empty' if alt_empty else 'missing')

        results.append({
            'page_url': page_url,
            'image_src': src_val[:200],
            'alt_text': alt_val if alt_val else '',
            'alt_status': status,
        })
    return results


def main():
    if len(sys.argv) < 4:
        print("Usage: python3 images.py <domain> <sitemap_url> <output_dir>", file=sys.stderr)
        sys.exit(1)

    domain = sys.argv[1]
    sitemap_url = sys.argv[2]
    output_dir = sys.argv[3]
    os.makedirs(output_dir, exist_ok=True)

    print(f"\n=== Image Alt Text Audit: {domain} ===", file=sys.stderr)

    sitemap_urls = get_sitemap_urls(sitemap_url)
    print(f"Found {len(sitemap_urls)} pages to scan", file=sys.stderr)

    all_images = []
    page_summaries = []

    for i, url in enumerate(sitemap_urls):
        status, html = fetch_url(url)
        if status != 200:
            continue

        images = extract_images(html, url)
        all_images.extend(images)

        total = len(images)
        good = sum(1 for img in images if img['alt_status'] == 'good')
        empty = sum(1 for img in images if img['alt_status'] == 'empty')
        missing = sum(1 for img in images if img['alt_status'] == 'missing')

        page_summaries.append({
            'url': url, 'total_images': total,
            'good_alt': good, 'empty_alt': empty, 'missing_alt': missing,
            'pct_missing': round((empty + missing) / total * 100, 1) if total > 0 else 0
        })

        if (i + 1) % 20 == 0:
            print(f"  Scanned {i + 1}/{len(sitemap_urls)} pages...", file=sys.stderr)
        time.sleep(0.3)

    # Write detailed CSV
    with open(os.path.join(output_dir, f'{domain}_images.csv'), 'w', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=['page_url', 'image_src', 'alt_text', 'alt_status'])
        writer.writeheader()
        writer.writerows(all_images)

    # Write page summary
    with open(os.path.join(output_dir, f'{domain}_images_summary.csv'), 'w', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=['url', 'total_images', 'good_alt', 'empty_alt', 'missing_alt', 'pct_missing'])
        writer.writeheader()
        writer.writerows(page_summaries)

    total = len(all_images)
    good = sum(1 for img in all_images if img['alt_status'] == 'good')
    empty = sum(1 for img in all_images if img['alt_status'] == 'empty')
    missing = sum(1 for img in all_images if img['alt_status'] == 'missing')

    print(f"\n  Total images: {total} | Good alt: {good} | Empty: {empty} | Missing: {missing}", file=sys.stderr)

    summary = {
        'domain': domain, 'total_images': total,
        'good_alt': good, 'empty_alt': empty, 'missing_alt': missing,
        'pages_scanned': len(sitemap_urls),
        'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')
    }
    with open(os.path.join(output_dir, f'{domain}_images_stats.json'), 'w') as f:
        json.dump(summary, f, indent=2)


if __name__ == '__main__':
    main()
