"""Halal certification registry sync and supermarket matching."""
from __future__ import annotations

import json
import re
import urllib.parse
import urllib.request
from typing import Any, Optional

from app.db import execute, execute_returning, fetch_all, fetch_one, json_param

OVERPASS_URL = "https://overpass.kumi.systems/api/interpreter"

# Known halal-friendly retail brands (indicative — verified via certifier when possible)
HALAL_FRIENDLY_CHAINS = {
    "Spar": {"has_halal_section": True, "note": "chain policy varies by franchise"},
    "Ekoplaza": {"halal_certified": False, "has_halal_section": True},
}


def _fetch_overpass(query: str) -> list[dict[str, Any]]:
    data = urllib.parse.urlencode({"data": query}).encode()
    req = urllib.request.Request(OVERPASS_URL, data=data, method="POST")
    with urllib.request.urlopen(req, timeout=120) as resp:
        payload = json.loads(resp.read().decode())
    return payload.get("elements", [])


def sync_osm_halal_tags() -> dict[str, Any]:
    """Mark supermarkets with OSM diet:halal=yes and import certification records."""
    query = (
        '[out:json][timeout:120];area["ISO3166-1"="NL"]->.nl;'
        '(node["shop"="supermarket"]["diet:halal"="yes"](area.nl);'
        'way["shop"="supermarket"]["diet:halal"="yes"](area.nl););out tags center;'
    )
    elements = _fetch_overpass(query)
    matched = created = 0
    for el in elements:
        tags = el.get("tags") or {}
        external_id = f"osm:{el.get('type')}:{el.get('id')}"
        store = fetch_one("SELECT id, name FROM supermarkets WHERE external_id = %s", (external_id,))
        if not store:
            name = tags.get("name") or tags.get("brand") or "Unknown"
            store = fetch_one(
                "SELECT id, name FROM supermarkets WHERE name ILIKE %s LIMIT 1",
                (f"%{name[:40]}%",),
            )
        if not store:
            continue
        matched += 1
        execute(
            """UPDATE supermarkets SET halal_certified = TRUE, has_halal_section = TRUE,
               halal_certifier = COALESCE(halal_certifier, 'OSM diet:halal'),
               last_updated = NOW() WHERE id = %s""",
            (store["id"],),
        )
        existing = fetch_one(
            "SELECT id FROM halal_certifications WHERE supermarket_id = %s AND registry_source = 'osm'",
            (store["id"],),
        )
        if not existing:
            execute_returning(
                """INSERT INTO halal_certifications (
                    supermarket_id, certifier, business_name, status, registry_source,
                    matched_confidence, raw_data
                ) VALUES (%s, 'OSM', %s, 'active', 'osm', 0.85, %s) RETURNING id""",
                (store["id"], store["name"], json_param(tags)),
            )
            created += 1
    return {"osm_halal_elements": len(elements), "stores_matched": matched, "certs_created": created}


def sync_osm_contact_tags(limit: int = 500) -> dict[str, Any]:
    """Pull phone/email/website/operator from OSM for existing stores."""
    stores = fetch_all(
        """SELECT id, external_id, phone, email, website, manager_name
           FROM supermarkets WHERE external_id LIKE %s
           AND (phone IS NULL OR email IS NULL OR manager_name IS NULL)
           LIMIT %s""",
        ("osm:%", limit),
    )
    updated = contacts = 0
    for store in stores:
        parts = (store.get("external_id") or "").split(":")
        if len(parts) != 3:
            continue
        osm_type, osm_id = parts[1], parts[2]
        query = f'[out:json][timeout:30];{osm_type}({osm_id});out tags;'
        try:
            elements = _fetch_overpass(query)
        except Exception:
            continue
        if not elements:
            continue
        tags = elements[0].get("tags") or {}
        phone = tags.get("phone") or tags.get("contact:phone")
        email = tags.get("email") or tags.get("contact:email")
        website = tags.get("website") or tags.get("contact:website")
        operator = tags.get("operator") or tags.get("contact:name")
        manager = tags.get("manager") or tags.get("contact:manager") or operator

        sets, params = [], []
        if phone and not store.get("phone"):
            sets.append("phone = %s"); params.append(str(phone)[:20])
        if email and not store.get("email"):
            sets.append("email = %s"); params.append(str(email)[:255])
        if website and not store.get("website"):
            sets.append("website = %s"); params.append(str(website)[:255])
        if manager and not store.get("manager_name"):
            sets.append("manager_name = %s"); params.append(str(manager)[:255])
        if sets:
            params.append(store["id"])
            execute(f"UPDATE supermarkets SET {', '.join(sets)}, last_updated = NOW() WHERE id = %s", tuple(params))
            updated += 1

        if manager or phone or email:
            existing = fetch_one(
                "SELECT id FROM supermarket_contacts WHERE supermarket_id = %s AND source = 'osm' LIMIT 1",
                (store["id"],),
            )
            if not existing:
                execute(
                    """INSERT INTO supermarket_contacts (
                        supermarket_id, role, full_name, phone, email, source, confidence
                    ) VALUES (%s, 'manager', %s, %s, %s, 'osm', 0.6)""",
                    (store["id"], manager, phone, email),
                )
                contacts += 1
            execute(
                """INSERT INTO supermarket_profiles (supermarket_id, manager_name, manager_phone,
                   manager_email, web_data, last_scraped_at, data_completeness)
                   VALUES (%s,%s,%s,%s,%s,NOW(),0.4)
                   ON CONFLICT (supermarket_id) DO UPDATE SET
                     manager_name = COALESCE(EXCLUDED.manager_name, supermarket_profiles.manager_name),
                     manager_phone = COALESCE(EXCLUDED.manager_phone, supermarket_profiles.manager_phone),
                     manager_email = COALESCE(EXCLUDED.manager_email, supermarket_profiles.manager_email),
                     web_data = supermarket_profiles.web_data || EXCLUDED.web_data,
                     last_scraped_at = NOW()""",
                (store["id"], manager, phone, email, json_param({"osm_tags": tags})),
            )
    return {"scanned": len(stores), "stores_updated": updated, "contacts_added": contacts}


def list_halal_certified(limit: int = 500) -> list[dict[str, Any]]:
    return fetch_all(
        """
        SELECT s.*, h.certifier, h.certificate_number, h.expiry_date, h.registry_source,
               h.matched_confidence
        FROM supermarkets s
        LEFT JOIN halal_certifications h ON h.supermarket_id = s.id AND h.status = 'active'
        WHERE s.halal_certified = TRUE OR s.has_halal_section = TRUE OR h.id IS NOT NULL
        ORDER BY s.chain, s.city LIMIT %s
        """,
        (limit,),
    )
