import time
import requests
from flask import current_app
from ..models.territorial import BairroZona

class CEPCache:
    """Abstração de Cache: utiliza Redis em produção e Dicionário em memória em desenvolvimento"""
    def __init__(self):
        self._local_cache = {}
        self._redis_client = None

    def _get_redis(self):
        if self._redis_client is None:
            try:
                redis_url = current_app.config.get('REDIS_URL')
                if redis_url:
                    import redis
                    self._redis_client = redis.from_url(redis_url)
            except Exception:
                self._redis_client = False
        return self._redis_client if self._redis_client else None

    def get(self, cep):
        r = self._get_redis()
        if r:
            try:
                import json
                val = r.get(f"cep:{cep}")
                if val:
                    return json.loads(val)
            except Exception:
                pass
        
        # Local Memory Fallback
        entry = self._local_cache.get(cep)
        if entry:
            data, exp = entry
            if time.time() < exp:
                return data
            else:
                del self._local_cache[cep]
        return None

    def set(self, cep, data, ttl=604800): # 7 Dias
        r = self._get_redis()
        if r:
            try:
                import json
                r.setex(f"cep:{cep}", ttl, json.dumps(data))
                return
            except Exception:
                pass

        self._local_cache[cep] = (data, time.time() + ttl)

cep_cache = CEPCache()

def consultar_cep(cep_raw):
    """
    Pipeline Completo de CEP com Cache Abstraído (Redis / Memória):
    CEP -> Cache -> ViaCEP -> logradouro, bairro, cidade, UF -> BairroZona -> Zona Urbana -> Lat/Lng
    """
    cep_clean = ''.join(filter(str.isdigit, str(cep_raw or '')))
    if len(cep_clean) != 8:
        return {'sucesso': False, 'erro': 'CEP inválido (deve conter 8 dígitos)'}

    # 1. Tentar ler do Cache
    cached = cep_cache.get(cep_clean)
    if cached:
        return cached

    try:
        url = f"https://viacep.com.br/ws/{cep_clean}/json/"
        response = requests.get(url, timeout=4)
        if response.status_code == 200:
            data = response.json()
            if data.get('erro'):
                return {'sucesso': False, 'erro': 'CEP não encontrado na base ViaCEP'}

            bairro = data.get('bairro', '').strip() or 'Centro'
            municipio = data.get('localidade', 'Manaus')
            uf = data.get('uf', 'AM')
            rua = data.get('logradouro', '')

            # Resolver Zona Urbana
            zona, lat, lng = BairroZona.obter_zona_por_bairro(bairro)

            resultado = {
                'sucesso': True,
                'cep': f"{cep_clean[:5]}-{cep_clean[5:]}",
                'rua': rua,
                'bairro': bairro,
                'zona': zona,
                'municipio': municipio,
                'uf': uf,
                'lat': lat,
                'lng': lng
            }
            cep_cache.set(cep_clean, resultado)
            return resultado
    except Exception as e:
        print(f"[CEP Service Error] {e}")

    fallback_res = {
        'sucesso': True,
        'cep': f"{cep_clean[:5]}-{cep_clean[5:]}" if len(cep_clean) == 8 else cep_raw,
        'rua': '',
        'bairro': 'Centro',
        'zona': 'Zona Norte',
        'municipio': 'Manaus',
        'uf': 'AM',
        'lat': -3.1316,
        'lng': -60.0232
    }
    cep_cache.set(cep_clean, fallback_res)
    return fallback_res
