
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
from pathlib import Path
import re
from sqlalchemy import create_engine, text

# -------------------- Configuración de conexión --------------------
hostname_psql = "localhost"
username_psql = "postgres"
password_psql = "post3008"
database_psql = "postgres"

# ------------------------------- Logging -------------------------------
logging.basicConfig(
    filename="huella_telecom_load.log",
    filemode="a",
    format="%(asctime)s %(levelname)s %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    level=logging.INFO,
)

# --------------- Util: regex desde config.txt ---------------
def cargar_regex_desde_config(ruta: str = "config.txt") -> str:
    """
    Lee términos desde config.txt:
      - Líneas vacías o que comienzan con '#' se ignoran.
      - Si una línea comienza con 'regex:', el resto se toma como expresión regular.
      - En caso contrario, la línea se trata como literal y se escapa.
    Devuelve un patrón único que OR-ea todos los términos/regex.
    """
    path = Path(ruta)
    if not path.is_file():
        raise FileNotFoundError(f"No se encontró el archivo de configuración: {ruta}")

    patrones = []
    with path.open("r", encoding="utf-8") as f:
        for linea in f:
            s = linea.strip()
            if not s or s.startswith("#"):
                continue
            if s.startswith("regex:"):
                patrones.append(s[len("regex:"):])  # usar la regex tal cual
            else:
                patrones.append(re.escape(s))       # tratar como literal

    if not patrones:
        raise ValueError("config.txt no contiene términos válidos (una palabra por línea).")

    return "|".join(patrones)

REGEX = cargar_regex_desde_config("config.txt")

# -------- Helper: construir el UNION ALL (lógica integrada) --------
def _quote_ident(name: str) -> str:
    return '"' + name.replace('"', '""') + '"'

def _quote_literal(val: str) -> str:
    return "'" + val.replace("'", "''") + "'"

def build_union_sql(conn) -> str:
    rows = conn.execute(text("""
        SELECT p.proy_name
        FROM giscloud.proyectos p
        WHERE p.proy_name IS NOT NULL
          AND (p.proy_name LIKE 'gpon%' OR p.proy_name LIKE 'lineales%' OR p.proy_name LIKE 'postes%')
          AND to_regclass(format('giscloud.%I', p.proy_name)) IS NOT NULL
    """)).fetchall()

    parts = []
    for (proy_name,) in rows:
        parts.append(f"""
        SELECT
          {_quote_literal(proy_name)}::text AS proy_name,
          fid, "_created", "_modified",
          comentario::text AS comentario,
          geom::geometry(Point,4326) AS geom
        FROM giscloud.{_quote_ident(proy_name)}
        """.strip())

    if not parts:
        return "SELECT NULL::text AS proy_name WHERE false"

    return " UNION ALL ".join(parts)

# --------------------- SQL: DDL de la tabla destino ---------------------
DDL = """
CREATE TABLE IF NOT EXISTS giscloud.huella_telecom (
  proy_name text NOT NULL,
  fid integer,
  _created timestamp without time zone,
  _modified timestamp without time zone,
  comentario text,
  ageom text, -- WKT

  -- Desde cm.municipio
  partido text,
  provincia text,
  tli text,
  gpon1 text,
  gpon2 text,
  gpon3 text,
  tendidos text,
  permisotli text,
  permisogpo text,
  permisomun text,
  entidad text,
  objeto text,
  fna text,
  gna text,
  sag text,
  fdc text,
  in1 text,
  shape_star double precision,
  shape_stle double precision,

  hubname text,
  hubdist double precision,
  geom geometry(Point,4326)
);

/* Asegura la columna si la tabla ya existía */
ALTER TABLE giscloud.huella_telecom
  ADD COLUMN IF NOT EXISTS upload_date text;

-- Índices recomendados
CREATE INDEX IF NOT EXISTS idx_huella_telecom_geom ON giscloud.huella_telecom USING GIST (geom);
CREATE INDEX IF NOT EXISTS idx_huella_telecom_proy_fid ON giscloud.huella_telecom (proy_name, fid);
-- Permisos (mantengo los existentes)
GRANT SELECT ON TABLE giscloud.huella_telecom TO om_read, jibanez;
GRANT USAGE ON SCHEMA giscloud TO om_read, jibanez;
"""

# ------------- INSERT (plantilla; inyecta UNION en el JOIN) -------------
INSERT_SQL_TEMPLATE = """
WITH eventos_filtrados AS (
  SELECT *
  FROM giscloud.huella_comentario(:p_regex) -- proy_name, fid, _created, _modified, comentario, geom
)
INSERT INTO giscloud.huella_telecom (
  proy_name, fid, _created, _modified,
  comentario, ageom,
  partido, provincia,
  tli, gpon1, gpon2, gpon3, tendidos,
  permisotli, permisogpo, permisomun, entidad, objeto,
  fna, gna, sag, fdc, in1, shape_star, shape_stle,
  hubname, hubdist,
  geom, upload_date
)
SELECT
  e.proy_name, e.fid, e._created, e._modified,
  e.comentario,
  ST_AsText(e.geom) AS ageom,
  m.nam AS partido,
  m.provincia,
  m.tli, m.gpon1, m.gpon2, m.gpon3, m.tendidos,
  m.permisotli, m.permisogpo, m.permisomun, m.entidad, m.objeto,
  m.fna, m.gna, m.sag, m.fdc, m.in1, m.shape_star, m.shape_stle,
  m.hubname, m.hubdist,
  e.geom AS geom, to_char(CURRENT_DATE, 'MM-DD-YYYY') AS upload_date
FROM eventos_filtrados e
LEFT JOIN (
  {UNION_SQL}
) t
  ON t.fid = e.fid AND t.proy_name = e.proy_name
LEFT JOIN cm.municipio m
  ON ST_Covers(m.geom, e.geom)
WHERE e.geom IS NOT NULL;
"""

# ---------------------------------- Runner ----------------------------------
def main():
    logging.info("Inicio carga giscloud.huella_telecom ")
    engine = create_engine(
        f"postgresql://{username_psql}:{password_psql}@{hostname_psql}:5432/{database_psql}"
    )
    with engine.begin() as conn:
        # 0) Construir el UNION ALL inline
        union_sql = build_union_sql(conn)

        # 1) Crear tabla + índices + permisos
        conn.execute(text(DDL))

        # 2) Limpiar contenido actual
        conn.execute(text("DELETE FROM giscloud.huella_telecom;"))

        # 3) Insertar datos (inyectando el UNION ALL)
        insert_sql = INSERT_SQL_TEMPLATE.format(UNION_SQL=union_sql)
        conn.execute(text(insert_sql), {"p_regex": REGEX})
# --------- Bloque de logueo agregado (fuera del with) ----------
    def log_final_en_postgres():
        cnx = engine.raw_connection()
        cursor = cnx.cursor()
        cursor.execute("""
            INSERT INTO z_procesos_python.scripts_ejecutados (nombre_script, ultima_ejecucion)
            VALUES ('HuellaTelecom', CURRENT_TIMESTAMP AT TIME ZONE 'America/Argentina/Buenos_Aires');
        """)
        cnx.commit()
        cursor.close()
        cnx.close()
    log_final_en_postgres()
    logging.info("Carga finalizada OK")

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        logging.exception(f"Fallo en carga: {e}")
        raise
