"""Phone-based exam solver — bypasses all screen capture blocks.

Starts a local HTTP server. User scans QR code on phone, takes a photo
of the exam screen, and gets the AI answer displayed on the phone.

CSCA cannot block a physical camera pointed at the screen.
"""

from __future__ import annotations

import base64
import io
import json
import logging
import socket
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler

log = logging.getLogger(__name__)

_PHONE_HTML = """\
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>MuraveyChina</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, sans-serif; background: #111; color: #eee;
       display: flex; flex-direction: column; align-items: center;
       min-height: 100vh; padding: 16px; }
h1 { font-size: 20px; margin: 12px 0; }
#capture-btn { width: 90%; max-width: 400px; padding: 20px; font-size: 22px;
               background: #2563eb; color: white; border: none; border-radius: 16px;
               cursor: pointer; margin: 16px 0; }
#capture-btn:active { background: #1d4ed8; }
#capture-btn:disabled { background: #555; }
#status { font-size: 16px; color: #aaa; margin: 8px 0; min-height: 24px; }
#answer-box { width: 90%; max-width: 400px; background: #1e293b;
              border-radius: 12px; padding: 16px; margin: 12px 0;
              font-size: 18px; line-height: 1.6; white-space: pre-wrap;
              display: none; min-height: 60px; }
#preview { max-width: 90%; max-height: 200px; border-radius: 8px;
           margin: 8px 0; display: none; }
input[type=file] { display: none; }
</style>
</head>
<body>
<h1>MuraveyChina</h1>
<img id="preview">
<button id="capture-btn" onclick="takePhoto()">📷 Сфоткать экран</button>
<div id="status"></div>
<div id="answer-box"></div>
<input type="file" id="file-input" accept="image/*" capture="environment">

<script>
const btn = document.getElementById('capture-btn');
const status = document.getElementById('status');
const answerBox = document.getElementById('answer-box');
const preview = document.getElementById('preview');
const fileInput = document.getElementById('file-input');

function takePhoto() {
    fileInput.click();
}

fileInput.addEventListener('change', async (e) => {
    const file = e.target.files[0];
    if (!file) return;

    // Show preview
    const url = URL.createObjectURL(file);
    preview.src = url;
    preview.style.display = 'block';

    btn.disabled = true;
    status.textContent = 'Анализирую...';
    answerBox.style.display = 'none';

    try {
        // Convert to base64
        const reader = new FileReader();
        const b64 = await new Promise((resolve) => {
            reader.onload = () => resolve(reader.result.split(',')[1]);
            reader.readAsDataURL(file);
        });

        // Send to server
        const resp = await fetch('/solve', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ image: b64 })
        });

        const data = await resp.json();
        if (data.answer) {
            answerBox.textContent = data.answer;
            answerBox.style.display = 'block';
            status.textContent = 'Готово!';
        } else {
            status.textContent = 'Ошибка: ' + (data.error || 'нет ответа');
        }
    } catch (err) {
        status.textContent = 'Ошибка: ' + err.message;
    }

    btn.disabled = false;
    fileInput.value = '';
});
</script>
</body>
</html>
"""


class _Handler(BaseHTTPRequestHandler):
    """HTTP handler for phone solver."""

    def log_message(self, format, *args):
        log.debug("[phone-solver] %s", format % args)

    def do_GET(self):
        if self.path == "/" or self.path == "/index.html":
            self.send_response(200)
            self.send_header("Content-Type", "text/html; charset=utf-8")
            self.end_headers()
            self.wfile.write(_PHONE_HTML.encode("utf-8"))
        else:
            self.send_error(404)

    def do_POST(self):
        if self.path == "/solve":
            try:
                length = int(self.headers.get("Content-Length", 0))
                body = self.rfile.read(length)
                data = json.loads(body)
                img_b64 = data.get("image", "")

                if not img_b64:
                    self._json_response({"error": "no image"}, 400)
                    return

                # Get config from server instance
                config = self.server.config

                # Call vision AI
                answer = _solve_image(config, img_b64)
                self._json_response({"answer": answer})

            except Exception as exc:
                log.error("[phone-solver] Error: %s", exc, exc_info=True)
                self._json_response({"error": str(exc)}, 500)
        else:
            self.send_error(404)

    def _json_response(self, data: dict, code: int = 200):
        self.send_response(code)
        self.send_header("Content-Type", "application/json")
        self.send_header("Access-Control-Allow-Origin", "*")
        self.end_headers()
        self.wfile.write(json.dumps(data, ensure_ascii=False).encode("utf-8"))


def _solve_image(config, img_b64: str) -> str:
    """Send image to Vision AI and return the answer."""
    from .ai.vision_adapter import VisionAdapter

    adapter = VisionAdapter(config)

    prompt = (
        "Look at this exam question photo. Extract the question and all answer options. "
        "Then determine the correct answer. Reply with ONLY the correct answer letter "
        "and brief explanation in the language of the question. "
        "Format: ANSWER: <letter>\\n<brief explanation>"
    )

    result = adapter.analyze(img_b64, prompt, max_tokens=512)
    if result:
        return result
    return "Не удалось получить ответ от AI"


def _get_local_ip() -> str:
    """Get the local IP address for LAN access."""
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"


def start_phone_solver(config, port: int = 8089, allow_lan: bool = False) -> str:
    """Start the phone solver HTTP server in a background thread.

    Args:
        config: Application config object.
        port: TCP port to listen on (default 8089).
        allow_lan: If True, bind to 0.0.0.0 so phones on the same LAN can
                   connect.  If False (default), bind to 127.0.0.1 only,
                   accepting local connections for security.

    Returns the URL to access from the phone.
    """
    bind_addr = "0.0.0.0" if allow_lan else "127.0.0.1"
    server = HTTPServer((bind_addr, port), _Handler)
    server.config = config

    thread = threading.Thread(target=server.serve_forever, daemon=True, name="phone-solver")
    thread.start()

    ip = _get_local_ip() if allow_lan else "127.0.0.1"
    url = f"http://{ip}:{port}"
    log.info("[phone-solver] Started at %s (bind=%s)", url, bind_addr)
    return url
