#!/usr/bin/env python
"""General-purpose image analysis via Google Gemini.

Usage:
  py analyze_image.py screenshot.png
  py analyze_image.py screenshot.png "What products are shown?"
  py analyze_image.py screenshot.png --mode consent
  py analyze_image.py screenshot.png --mode cloudflare
  py analyze_image.py screenshot.png --mode login
  py analyze_image.py screenshot.png --mode content
  py analyze_image.py before.png after.png --mode compare
  py analyze_image.py before.png after.png "Did the cookie popup disappear?"

Modes:
  describe    General image description (default)
  consent     Cookie consent / privacy popup detection
  cloudflare  Bot-protection / Cloudflare / Akamai / CAPTCHA detection
  login       Login page / auth wall / paywall detection
  content     Page content quality: loaded, empty, error, skeleton, spinner
  compare     Compare two images (before/after), describe differences

Requires GEMINI_API_KEY in host environment variables.
"""
from __future__ import annotations

import argparse
import os
import sys
from pathlib import Path

from google import genai
from google.genai import types

DEFAULT_MODEL = "models/gemini-3.1-flash-lite-preview"

MIME_MAP = {
    ".png": "image/png",
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".webp": "image/webp",
    ".gif": "image/gif",
    ".bmp": "image/bmp",
    ".svg": "image/svg+xml",
}

MODES: dict[str, str] = {
    "describe": (
        "Describe this webpage screenshot in detail. Include:\n"
        "- Page type (homepage, product page, article, form, error page, etc.)\n"
        "- Visible text, headings, navigation elements\n"
        "- Layout structure, content areas, sidebar, footer\n"
        "- Any popups, overlays, modals, banners visible\n"
        "- Any cookie consent, bot-protection, login walls, or error states\n"
        "- Images and visual elements present\n"
        "Be thorough but concise."
    ),
    "consent": (
        "Analyze this screenshot for cookie consent / privacy popups.\n"
        "Answer these questions:\n"
        "1. VISIBLE: Is a cookie consent banner, modal, overlay, or privacy popup visible? (yes/no)\n"
        "2. BUTTON_TEXT: What is the exact text of the accept/allow button, if visible?\n"
        "3. BLOCKING: Does the popup block the page content behind it? (yes/no/partial)\n"
        "4. TYPE: What type is it? (banner_bottom, banner_top, modal_center, fullscreen, sidebar, none)\n"
        "5. PROVIDER: Recognized consent provider if identifiable (OneTrust, CookieBot, Usercentrics, unknown, none)\n"
        "6. OTHER_BUTTONS: List other visible buttons (reject, settings, customize, etc.)\n"
        "Start with a one-line summary, then answer each numbered question."
    ),
    "cloudflare": (
        "Analyze this screenshot for bot-protection or security challenge pages.\n"
        "Answer these questions:\n"
        "1. BLOCKED: Is the page showing a bot-protection / security challenge instead of normal content? (yes/no)\n"
        "2. PROVIDER: Which provider? (cloudflare, akamai, datadome, perimeterx, hcaptcha, recaptcha, other, none)\n"
        "3. CHALLENGE_TYPE: What type? (turnstile, captcha, interstitial, javascript_challenge, waiting_room, none)\n"
        "4. VISIBLE_TEXT: Quote the key visible security/challenge text on the page.\n"
        "5. BYPASSED: Does it look like the challenge was already solved and normal content is showing? (yes/no)\n"
        "6. CONFIDENCE: How confident are you? (high/medium/low)\n"
        "A normal page with a small Cloudflare footer link is NOT a challenge.\n"
        "A cookie consent popup is NOT a bot-protection challenge.\n"
        "Start with a one-line summary, then answer each numbered question."
    ),
    "login": (
        "Analyze this screenshot for login, authentication, or access walls.\n"
        "Answer these questions:\n"
        "1. LOGIN_WALL: Is a login form, auth wall, or paywall blocking the content? (yes/no)\n"
        "2. TYPE: What type? (login_form, registration, paywall, age_gate, geo_block, account_required, none)\n"
        "3. FIELDS: What input fields are visible? (username, password, email, etc.)\n"
        "4. BYPASSED: Does it look like the user is already logged in with content visible? (yes/no)\n"
        "5. CONTENT_BEHIND: Is real page content visible behind/around the login wall? (yes/no/partial)\n"
        "6. SOCIAL_LOGIN: Are social login options visible? (Google, Facebook, Apple, etc.)\n"
        "Start with a one-line summary, then answer each numbered question."
    ),
    "content": (
        "Analyze this webpage screenshot for content loading quality.\n"
        "Answer these questions:\n"
        "1. STATUS: Is the page fully loaded with real content? (loaded/partial/empty/error/loading)\n"
        "2. CONTENT_TYPE: What type of page is this? (product, article, listing, homepage, search, error, etc.)\n"
        "3. MAIN_CONTENT: Briefly describe the main content visible.\n"
        "4. PROBLEMS: Any issues? (blank areas, broken images, spinners, skeleton loaders, error messages, 404, 500)\n"
        "5. POPUPS: Any overlays blocking content? (cookie consent, login wall, newsletter signup, chat widget, none)\n"
        "6. SCROLLABLE: Does the page appear to have more content below the fold? (yes/no/unknown)\n"
        "Start with a one-line summary, then answer each numbered question."
    ),
    "compare": (
        "Compare these two webpage screenshots (Image 1 = before, Image 2 = after).\n"
        "Answer these questions:\n"
        "1. CHANGED: Did something visually change between the two images? (yes/no)\n"
        "2. POPUP_BEFORE: Was a popup/overlay/modal visible in the BEFORE image? (yes/no) What kind?\n"
        "3. POPUP_AFTER: Is a popup/overlay/modal still visible in the AFTER image? (yes/no) What kind?\n"
        "4. POPUP_RESOLVED: Was a popup dismissed or resolved between before and after? (yes/no)\n"
        "5. KEY_DIFFERENCES: List the main visual differences between the two images.\n"
        "6. PAGE_CONTENT: Is real page content now visible that wasn't before? (yes/no)\n"
        "Start with a one-line summary, then answer each numbered question."
    ),
}


def analyze(
    image_paths: list[str | Path],
    prompt: str,
    model: str = DEFAULT_MODEL,
    api_key: str | None = None,
) -> str:
    api_key = api_key or os.getenv("GEMINI_API_KEY", "")
    if not api_key:
        print("ERROR: GEMINI_API_KEY environment variable not set", file=sys.stderr)
        sys.exit(1)

    parts: list = [prompt]
    for i, p in enumerate(image_paths):
        p = Path(p)
        if not p.exists():
            print(f"ERROR: File not found: {p}", file=sys.stderr)
            sys.exit(1)
        mime_type = MIME_MAP.get(p.suffix.lower(), "image/png")
        if len(image_paths) > 1:
            parts.append(f"Image {i + 1} ({'before' if i == 0 else 'after'}):")
        parts.append(types.Part.from_bytes(data=p.read_bytes(), mime_type=mime_type))

    client = genai.Client(api_key=api_key)
    config = types.GenerateContentConfig(temperature=0.2)
    response = client.models.generate_content(
        model=model,
        contents=parts,
        config=config,
    )
    return response.text or ""


def main():
    p = argparse.ArgumentParser(
        description="Analyze images with Google Gemini",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="Modes: " + ", ".join(MODES.keys()),
    )
    p.add_argument("images", nargs="+", help="Image file path(s). Two images for compare mode.")
    p.add_argument("-m", "--mode", choices=MODES.keys(), default=None, help="Analysis preset (default: describe)")
    p.add_argument("-p", "--prompt", default=None, help="Custom prompt (overrides mode)")
    p.add_argument("--model", default=DEFAULT_MODEL, help=f"Gemini model (default: {DEFAULT_MODEL})")
    args = p.parse_args()

    images = []
    free_prompt = None
    for item in args.images:
        if Path(item).exists() or any(item.lower().endswith(ext) for ext in MIME_MAP):
            images.append(item)
        else:
            free_prompt = item

    if not images:
        print("ERROR: No image files provided", file=sys.stderr)
        sys.exit(1)

    if args.prompt:
        prompt = args.prompt
    elif free_prompt:
        prompt = free_prompt
    elif args.mode:
        prompt = MODES[args.mode]
    elif len(images) > 1:
        prompt = MODES["compare"]
    else:
        prompt = MODES["describe"]

    result = analyze(images, prompt=prompt, model=args.model)
    print(result)


if __name__ == "__main__":
    main()
