#!/usr/bin/env python3
"""
import_new_cartas.py

Importa las cartas de la semana nuevas de ew4r_content (Joomla prod, id > 9043)
al WordPress local (Docker), y luego asigna _carta_id a los artículos K2
correspondientes según la fecha (extra_field id 15).

Categorías WP según catid Joomla:
  catid 27 (Carta de la semana)  → WP: 6 + 21 + 71
  catid 40 (Cartas de otras sem) → WP: 21 + 71
  catid 41 (Carta semana pasada) → WP: 21 + 22 + 71
"""

import json
import subprocess
import sys
import re
from datetime import datetime

JOOMLA_SSH_HOST = "134.0.10.170"
JOOMLA_SSH_USER = "feadulta"
JOOMLA_SSH_PASS = "C6c2A!mAl3Wj.BQF"
JOOMLA_DB_HOST  = "127.0.0.1"
JOOMLA_DB_USER  = "fejoomla3"
JOOMLA_DB_PASS  = "5FF-}5^[>7^pK4W9"
JOOMLA_DB_NAME  = "fejoomla3"

WP_DOCKER  = "wordpress-mysql"
WP_DB_USER = "wordpress_user"
WP_DB_PASS = "wordpress_pass"
WP_DB_NAME = "wordpress_db"

LAST_CONTENT_ID = None  # se calcula dinámicamente en main(): MAX(_fgj2wp_old_content_id) en WP

# WP term_ids y sus term_taxonomy_ids (se cargan dinámicamente)
CAT_FEADULTA         = 71
CAT_CARTA_SEMANA     = 6
CAT_CARTAS_OTRAS     = 21
CAT_CARTA_PASADA     = 22

CATID_TO_WP = {
    27: [CAT_CARTA_SEMANA, CAT_CARTAS_OTRAS, CAT_FEADULTA],
    40: [CAT_CARTAS_OTRAS, CAT_FEADULTA],
    41: [CAT_CARTAS_OTRAS, CAT_CARTA_PASADA, CAT_FEADULTA],
}

DRY_RUN = '--dry-run' in sys.argv

# ── Helpers ────────────────────────────────────────────────────────────────────

def joomla_query(query: str) -> list[dict]:
    mysql_cmd = (f"mysql --skip-ssl -h {JOOMLA_DB_HOST} -u {JOOMLA_DB_USER} "
                 f"-p'{JOOMLA_DB_PASS}' {JOOMLA_DB_NAME} "
                 f"--default-character-set=utf8mb4 -B")
    cmd = ['sshpass', '-p', JOOMLA_SSH_PASS,
           'ssh', f'{JOOMLA_SSH_USER}@{JOOMLA_SSH_HOST}', mysql_cmd]
    result = subprocess.run(cmd, input=query, capture_output=True,
                            text=True, encoding='utf-8')
    if result.returncode != 0:
        print(f"[ERR SSH] {result.stderr[:300]}", file=sys.stderr)
        return []
    lines = result.stdout.strip().split('\n')
    if len(lines) < 2:
        return []
    headers = lines[0].split('\t')
    return [dict(zip(headers, line.split('\t'))) for line in lines[1:] if line]


def wp_mysql(query: str) -> list[dict]:
    cmd = ['docker', 'exec', WP_DOCKER,
           'mysql', '-u', WP_DB_USER, f'-p{WP_DB_PASS}', WP_DB_NAME,
           '--default-character-set=utf8mb4', '-B', '-e', query]
    result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
    if result.returncode != 0:
        return []
    lines = result.stdout.strip().split('\n')
    if len(lines) < 2:
        return []
    headers = lines[0].split('\t')
    return [dict(zip(headers, line.split('\t'))) for line in lines[1:] if line]


def wp_execute(sql: str):
    if DRY_RUN:
        print(f"  [DRY] {sql[:110]}")
        return None
    cmd = ['docker', 'exec', WP_DOCKER,
           'mysql', '-u', WP_DB_USER, f'-p{WP_DB_PASS}', WP_DB_NAME,
           '--default-character-set=utf8mb4', '-e', sql]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        err = result.stderr.replace('mysql: [Warning] Using a password on the command line interface can be insecure.\n', '')
        if err.strip():
            print(f"  [ERR] {err.strip()[:200]}", file=sys.stderr)


def esc(s: str) -> str:
    return s.replace('\\', '\\\\').replace("'", "\\'")


def unhex(val: str) -> str:
    if not val or val == 'NULL':
        return ''
    try:
        return bytes.fromhex(val).decode('utf-8', errors='replace')
    except Exception:
        return val


# ── Main ───────────────────────────────────────────────────────────────────────

def main():
    global LAST_CONTENT_ID
    # Detección dinámica del último ew4r_content (carta) ya importado
    r = wp_mysql("SELECT MAX(CAST(meta_value AS UNSIGNED)) m FROM wp_postmeta "
                 "WHERE meta_key='_fgj2wp_old_content_id'")
    LAST_CONTENT_ID = int(r[0]['m']) if r and r[0].get('m') and r[0]['m'] != 'NULL' else 9043
    print(f"=== Import nuevas cartas (ew4r_content id > {LAST_CONTENT_ID}) "
          f"{'[DRY RUN]' if DRY_RUN else '[LIVE]'} ===\n")

    # Cargar term_taxonomy_ids
    all_term_ids = [CAT_FEADULTA, CAT_CARTA_SEMANA, CAT_CARTAS_OTRAS, CAT_CARTA_PASADA]
    rows = wp_mysql(
        f"SELECT term_id, term_taxonomy_id FROM wp_term_taxonomy "
        f"WHERE term_id IN ({','.join(map(str,all_term_ids))}) AND taxonomy='category'"
    )
    tt_ids = {int(r['term_id']): int(r['term_taxonomy_id']) for r in rows}
    print(f"TT IDs: {tt_ids}")

    # Cargar Polylang ES
    pl_rows = wp_mysql(
        "SELECT tt.term_taxonomy_id FROM wp_terms t "
        "JOIN wp_term_taxonomy tt ON tt.term_id=t.term_id "
        "WHERE tt.taxonomy='language' AND t.slug='es' LIMIT 1"
    )
    pl_es_tt = int(pl_rows[0]['term_taxonomy_id']) if pl_rows else None
    print(f"Polylang ES tt_id: {pl_es_tt}")

    # Cargar user map
    user_rows = wp_mysql(
        "SELECT um.meta_value jid, u.ID wid FROM wp_users u "
        "JOIN wp_usermeta um ON um.user_id=u.ID "
        "WHERE um.meta_key='_fgj2wp_old_user_id'"
    )
    user_map = {}
    for r in user_rows:
        try:
            user_map[int(r['jid'])] = int(r['wid'])
        except ValueError:
            pass

    # Obtener cartas nuevas de Joomla (con HEX para texto)
    print("\nObteniendo cartas nuevas de Joomla...")
    query = (
        f"SELECT id, HEX(title) title, HEX(alias) alias, "
        f"HEX(introtext) introtext, HEX(`fulltext`) fulltext_col, "
        f"catid, created, created_by "
        f"FROM ew4r_content "
        f"WHERE state=1 AND id > {LAST_CONTENT_ID} AND catid IN (27,40,41) "
        f"ORDER BY id;"
    )
    items = joomla_query(query)
    print(f"Cartas a importar: {len(items)}")

    # Mapa fecha_carta → wp_id (para asignar _carta_id a artículos K2)
    fecha_a_wp_carta = {}

    for item in items:
        joomla_id  = int(item['id'])
        catid      = int(item['catid'])
        title      = unhex(item.get('title',''))
        alias      = unhex(item.get('alias',''))
        intro      = unhex(item.get('introtext',''))
        full       = unhex(item.get('fulltext_col',''))
        created    = item.get('created','') or datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        created_by = int(item.get('created_by', 0) or 0)

        content = intro + ('\n<!--more-->\n' + full if full.strip() else '')
        # La carta semanal SIEMPRE la firma Inma Calvo (WP user 1048 icalvotorre),
        # aunque en Joomla la cree el webmaster (José Chicharro / josek 1049).
        CARTA_AUTHOR = 1048
        wp_author = CARTA_AUTHOR
        wp_cats = CATID_TO_WP.get(catid, [CAT_CARTAS_OTRAS, CAT_FEADULTA])
        fecha_carta = created[:10]  # YYYY-MM-DD

        print(f"\n  [{joomla_id}] {title[:55]} | catid={catid} | fecha={fecha_carta}")
        print(f"    → WP cats: {wp_cats}")

        # INSERT post
        post_slug    = esc(alias[:200])
        post_title   = esc(title)
        post_content = esc(content)

        wp_execute(
            f"INSERT INTO wp_posts "
            f"(post_author, post_date, post_date_gmt, post_content, post_title, "
            f"post_excerpt, post_status, comment_status, ping_status, post_name, "
            f"post_type, post_modified, post_modified_gmt, comment_count, "
            f"to_ping, pinged, post_content_filtered) VALUES ("
            f"{wp_author}, '{created}', '{created}', '{post_content}', "
            f"'{post_title}', '', 'publish', 'open', 'open', '{post_slug}', "
            f"'post', '{created}', '{created}', 0, '', '', '')"
        )

        if DRY_RUN:
            fecha_a_wp_carta[fecha_carta] = f"DRY_WP_ID_for_{joomla_id}"
            continue

        new_id_rows = wp_mysql("SELECT MAX(ID) new_id FROM wp_posts")
        if not new_id_rows:
            print(f"  [ERR] No se pudo obtener ID del post", file=sys.stderr)
            continue
        new_wp_id = int(new_id_rows[0]['new_id'])
        print(f"    → WP post ID={new_wp_id}")

        fecha_a_wp_carta[fecha_carta] = new_wp_id

        # Metas
        wp_execute(f"INSERT INTO wp_postmeta (post_id, meta_key, meta_value) VALUES ({new_wp_id}, '_fgj2wp_old_content_id', '{joomla_id}')")
        wp_execute(f"INSERT INTO wp_postmeta (post_id, meta_key, meta_value) VALUES ({new_wp_id}, 'Idioma', '1')")

        # Categorías
        for term_id in wp_cats:
            tt_id = tt_ids.get(term_id)
            if tt_id:
                wp_execute(
                    f"INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id) "
                    f"VALUES ({new_wp_id}, {tt_id})"
                )

        # Polylang ES
        if pl_es_tt:
            wp_execute(
                f"INSERT IGNORE INTO wp_term_relationships (object_id, term_taxonomy_id) "
                f"VALUES ({new_wp_id}, {pl_es_tt})"
            )

    print(f"\nFecha→WP carta map: {fecha_a_wp_carta}")

    # ── Asignar _carta_id a los artículos K2 importados ──────────────────────
    if DRY_RUN or not fecha_a_wp_carta:
        print("\n[SKIP] Asignación _carta_id (dry-run o sin cartas importadas)")
        return

    print("\n=== Asignando _carta_id a artículos K2 ===")

    # Obtener los artículos K2 con su fecha (id 15), acotando por la fecha más
    # antigua de las cartas importadas en esta ejecución (evita recorrer todo).
    min_fecha = min(fecha_a_wp_carta.keys())
    k2_query = (
        f"SELECT id, HEX(extra_fields) ef "
        f"FROM ew4r_k2_items WHERE published=1 AND created >= '{min_fecha} 00:00:00' "
        f"ORDER BY id;"
    )
    k2_items = joomla_query(k2_query)
    print(f"Artículos K2 a procesar (desde {min_fecha}): {len(k2_items)}")

    assigned = 0
    for k2item in k2_items:
        k2_id  = int(k2item['id'])
        # wp_id REAL por meta (NO offset fijo, que pisaba metas en deltas sucesivos)
        wp_rows = wp_mysql(
            f"SELECT post_id FROM wp_postmeta WHERE meta_key='_fgj2wp_old_k2_id' "
            f"AND meta_value='{k2_id}' LIMIT 1"
        )
        if not wp_rows:
            continue
        wp_id  = int(wp_rows[0]['post_id'])
        ef_raw = unhex(k2item.get('ef',''))

        # Parsear fecha (id 15)
        fecha_art = None
        try:
            fields = json.loads(ef_raw)
            for f in fields:
                if str(f.get('id','')) == '15':
                    fecha_art = str(f.get('value',''))[:10]
                    break
        except Exception:
            pass

        if not fecha_art:
            continue

        carta_wp_id = fecha_a_wp_carta.get(fecha_art)
        if not carta_wp_id:
            continue

        # Verificar que el meta no existe ya
        existing = wp_mysql(
            f"SELECT meta_id FROM wp_postmeta WHERE post_id={wp_id} AND meta_key='_carta_id' LIMIT 1"
        )
        if existing:
            continue

        wp_execute(
            f"INSERT INTO wp_postmeta (post_id, meta_key, meta_value) "
            f"VALUES ({wp_id}, '_carta_id', '{carta_wp_id}')"
        )
        print(f"  K2 {k2_id} (WP {wp_id}) → _carta_id={carta_wp_id} [{fecha_art}]")
        assigned += 1

    print(f"\n_carta_id asignado a {assigned} artículos.")

    # Actualizar counts de categorías
    print("\nActualizando counts de categorías...")
    tt_str = ','.join(str(v) for v in tt_ids.values())
    wp_execute(
        f"UPDATE wp_term_taxonomy tt SET count = ("
        f"SELECT COUNT(*) FROM wp_term_relationships tr "
        f"WHERE tr.term_taxonomy_id=tt.term_taxonomy_id"
        f") WHERE tt.term_taxonomy_id IN ({tt_str})"
    )

    print("\nListo.")


if __name__ == '__main__':
    main()
