from __future__ import annotations

import json
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import parse_qs, urlparse

from .scraper import search_properties

PAGE = """<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Montpellier Immobilier Finder</title>
  <style>
    :root { color-scheme: dark; }
    body { font-family: system-ui, sans-serif; margin: 0; background: #0b1220; color: #e8edf7; }
    header { padding: 20px 24px; background: #111a2f; border-bottom: 1px solid #24304d; }
    main { max-width: 1200px; margin: 0 auto; padding: 24px; }
    .card { background: #121c31; border: 1px solid #25314d; border-radius: 14px; padding: 16px; box-shadow: 0 8px 30px rgba(0,0,0,.25); }
    .grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
    label { display: block; font-size: 13px; color: #9db0d0; margin-bottom: 6px; }
    input, select, button { width: 100%; box-sizing: border-box; border-radius: 10px; border: 1px solid #31405f; background: #0b1324; color: #e8edf7; padding: 12px; }
    button { cursor: pointer; background: linear-gradient(180deg, #2f86ff, #245fd0); border: none; font-weight: 700; }
    button:hover { filter: brightness(1.04); }
    .results { margin-top: 18px; display: grid; gap: 12px; }
    .result { border: 1px solid #283552; border-radius: 14px; padding: 14px; background: #0f1728; }
    .meta { display: flex; flex-wrap: wrap; gap: 10px; color: #9eb1d3; font-size: 13px; margin-bottom: 8px; }
    .pill { background: #1a2640; border: 1px solid #2a3960; padding: 4px 8px; border-radius: 999px; }
    .title { margin: 0 0 8px 0; font-size: 18px; }
    .snippet { margin: 0; color: #c7d2e6; line-height: 1.45; }
    a { color: #8cc2ff; text-decoration: none; }
    a:hover { text-decoration: underline; }
    .muted { color: #93a4c3; font-size: 13px; }
    .topbar { display:flex; justify-content: space-between; gap: 16px; align-items: center; margin-bottom: 20px; }
    .status { font-size: 13px; color: #9db0d0; }
    @media (max-width: 960px) { .grid { grid-template-columns: 1fr 1fr; } }
    @media (max-width: 640px) { .grid { grid-template-columns: 1fr; } }
  </style>
</head>
<body>
  <header>
    <strong>Montpellier Immobilier Finder</strong>
    <div class="muted">Recherche locale, max 20 km autour de Montpellier, budget max 400k</div>
  </header>
  <main>
    <div class="card">
      <div class="topbar">
        <div>
          <h1 style="margin:0 0 4px 0;">Chercher des maisons</h1>
          <div class="muted">Le moteur interroge Bing RSS puis trie les résultats par proximité et budget.</div>
        </div>
        <div class="status" id="status">Prêt.</div>
      </div>
      <form id="search-form">
        <div class="grid">
          <div>
            <label>Centre</label>
            <input name="center" value="Montpellier" />
          </div>
          <div>
            <label>Rayon km</label>
            <input name="radius_km" type="number" value="20" min="1" max="100" step="1" />
          </div>
          <div>
            <label>Budget max</label>
            <input name="max_price" type="number" value="400000" min="1" step="1000" />
          </div>
          <div>
            <label>Type</label>
            <select name="property_type">
              <option value="maison" selected>Maison</option>
              <option value="appartement">Appartement</option>
              <option value="terrain">Terrain</option>
            </select>
          </div>
        </div>
        <div style="margin-top: 12px; display:flex; gap: 12px; align-items:center; flex-wrap: wrap;">
          <button type="submit">Lancer la recherche</button>
          <span class="muted">Astuce: laisse le formulaire tel quel pour Montpellier + 20 km + 400k.</span>
        </div>
      </form>
    </div>

    <div id="results" class="results"></div>
  </main>

  <script>
    const form = document.getElementById('search-form');
    const results = document.getElementById('results');
    const status = document.getElementById('status');

    function esc(s) {
      return String(s || '').replace(/[&<>'"]/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
    }

    form.addEventListener('submit', async (e) => {
      e.preventDefault();
      status.textContent = 'Recherche en cours...';
      results.innerHTML = '';
      const params = new URLSearchParams(new FormData(form));
      const resp = await fetch('/api/search?' + params.toString());
      const data = await resp.json();
      status.textContent = `${data.count} résultats, ${data.elapsed_ms} ms`;
      if (data.error) {
        results.innerHTML = `<div class="result"><h3 class="title">Erreur</h3><p class="snippet">${esc(data.error)}</p></div>`;
        return;
      }
      if (!data.results.length) {
        results.innerHTML = `<div class="result"><h3 class="title">Aucun résultat</h3><p class="snippet">Essaie en élargissant le rayon ou le type de bien.</p></div>`;
        return;
      }
      results.innerHTML = data.results.map((r, idx) => `
        <div class="result">
          <div class="meta">
            <span class="pill">#${idx+1}</span>
            <span class="pill">Score ${esc(r.score)}</span>
            <span class="pill">Source ${esc(r.source)}</span>
            ${r.price ? `<span class="pill">${esc(r.price)} €</span>` : ''}
            ${r.distance_km !== null && r.distance_km !== undefined ? `<span class="pill">${esc(r.distance_km)} km</span>` : ''}
            ${r.town ? `<span class="pill">${esc(r.town)}</span>` : ''}
          </div>
          <h3 class="title"><a href="${esc(r.url)}" target="_blank" rel="noopener noreferrer">${esc(r.title)}</a></h3>
          <p class="snippet">${esc(r.snippet || 'Pas de snippet')}</p>
        </div>
      `).join('');
    });
  </script>
</body>
</html>"""


class Handler(BaseHTTPRequestHandler):
    def log_message(self, format: str, *args) -> None:  # noqa: A003
        return

    def _send(self, body: str, content_type: str = "text/html; charset=utf-8", code: int = 200) -> None:
        encoded = body.encode("utf-8")
        self.send_response(code)
        self.send_header("Content-Type", content_type)
        self.send_header("Content-Length", str(len(encoded)))
        self.end_headers()
        self.wfile.write(encoded)

    def do_GET(self):  # noqa: N802
        parsed = urlparse(self.path)
        if parsed.path in {"/", "/index.html"}:
            self._send(PAGE)
            return
        if parsed.path == "/health":
            self._send(json.dumps({"ok": True}), content_type="application/json; charset=utf-8")
            return
        if parsed.path == "/api/search":
            start = __import__("time").time()
            params = parse_qs(parsed.query)
            center = params.get("center", ["Montpellier"])[0]
            radius_km = float(params.get("radius_km", ["20"])[0])
            max_price = int(params.get("max_price", ["400000"])[0])
            property_type = params.get("property_type", ["maison"])[0]
            limit = int(params.get("limit", ["20"])[0])
            try:
                results = search_properties(
                    center=center,
                    radius_km=radius_km,
                    max_price=max_price,
                    property_type=property_type,
                    limit=limit,
                )
                payload = {
                    "center": center,
                    "radius_km": radius_km,
                    "max_price": max_price,
                    "property_type": property_type,
                    "count": len(results),
                    "elapsed_ms": round((__import__("time").time() - start) * 1000),
                    "results": [
                        {
                            "title": r.title,
                            "url": r.url,
                            "snippet": r.snippet,
                            "source": r.source,
                            "price": r.price,
                            "town": r.town,
                            "distance_km": r.distance_km,
                            "score": r.score,
                        }
                        for r in results
                    ],
                }
            except Exception as exc:  # pragma: no cover - surfaced in UI
                payload = {
                    "center": center,
                    "radius_km": radius_km,
                    "max_price": max_price,
                    "property_type": property_type,
                    "count": 0,
                    "elapsed_ms": round((__import__("time").time() - start) * 1000),
                    "error": f"{type(exc).__name__}: {exc}",
                    "results": [],
                }
            self._send(json.dumps(payload, ensure_ascii=False), content_type="application/json; charset=utf-8")
            return
        self._send("Not found", code=404)


def serve(host: str = "127.0.0.1", port: int = 8765) -> None:
    server = ThreadingHTTPServer((host, port), Handler)
    print(f"Serving on http://{host}:{port}")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.server_close()


if __name__ == "__main__":
    serve()
