#!/usr/bin/env python3
"""
Script para descargar boletines oficiales de Jujuy.

El sitio usa un calendario mensual. Se scrapea la página para obtener
los links PDF de cada día.

URL base: https://boletinoficial.jujuy.gob.ar/?page_id=2017

Uso:
    python descargar_jujuy.py                          # Descarga el boletín del día actual
    python descargar_jujuy.py --anio 2024              # Descarga todo el año 2024
    python descargar_jujuy.py --anio 2024 --mes 5      # Descarga todo mayo de 2024
    python descargar_jujuy.py --anio 2024 --mes 5 --dia 15  # Descarga el 15 de mayo de 2024
"""

import os
import requests
import datetime
import argparse
import calendar
from bs4 import BeautifulSoup
from base import ya_existe_en_provincia

BASE_URL = "https://boletinoficial.jujuy.gob.ar"
PAGE_ID = "2017"


MESES_EN = [
    "jan", "feb", "mar", "apr", "may", "jun",
    "jul", "aug", "sep", "oct", "nov", "dec",
]


def obtener_links_mes(anio, mes, session):
    """
    Scrapea el calendario del mes y devuelve un dict {fecha: url_pdf}.

    El sitio usa ?month=jan&yr=2026 para navegar entre meses.
    Cada celda del calendario tiene clase 'spiffy-day-N' donde N es el día,
    y 'day-with-date' para los días que pertenecen al mes actual.
    """
    import re
    mes_nombre = MESES_EN[mes - 1]
    url = f"{BASE_URL}/?page_id={PAGE_ID}&month={mes_nombre}&yr={anio}"

    try:
        response = session.get(url, timeout=20)
        response.raise_for_status()
    except requests.RequestException as e:
        print(f"  ❌ Error al acceder al calendario {anio}/{mes:02d}: {e}")
        return {}

    soup = BeautifulSoup(response.text, "html.parser")
    links_por_fecha = {}

    # Solo procesar celdas del mes actual (tienen 'day-with-date')
    for td in soup.find_all("td", class_=lambda c: c and "day-with-date" in c):
        classes = td.get("class", [])

        # Extraer número de día de la clase 'spiffy-day-N'
        dia = None
        for cls in classes:
            m = re.match(r"spiffy-day-(\d+)$", cls)
            if m:
                dia = int(m.group(1))
                break

        if dia is None:
            continue

        # Buscar el primer link PDF en la celda (evitar duplicados)
        for a in td.find_all("a", href=True):
            href = a["href"]
            if ".pdf" not in href.lower():
                continue
            if "Boletines" not in href and "boletines" not in href:
                continue

            try:
                fecha = datetime.date(anio, mes, dia)
            except ValueError:
                break

            url_pdf = href if href.startswith("http") else BASE_URL + href
            if fecha not in links_por_fecha:
                links_por_fecha[fecha] = url_pdf
            break  # Solo el primer PDF por celda

    return links_por_fecha


def descargar_pdf(url, fecha, directorio_destino, session):
    """Descarga un PDF desde una URL y lo guarda con nombre estándar."""
    archivo_path = os.path.join(directorio_destino, f"boletin_{fecha.strftime('%Y-%m-%d')}.pdf")

    try:
        response = session.get(url, timeout=60)
        response.raise_for_status()

        # Verificar que sea un PDF real
        content_type = response.headers.get("Content-Type", "")
        if "pdf" not in content_type.lower() and not response.content[:4] == b"%PDF":
            print(f"  ⚠️  El contenido no parece un PDF (Content-Type: {content_type})")
            return False

        with open(archivo_path, "wb") as f:
            f.write(response.content)

        print(f"  ✅ Descargado: {archivo_path}")
        return True

    except requests.RequestException as e:
        print(f"  ❌ Error al descargar el PDF: {e}")
        return False
    except Exception as e:
        print(f"  ❌ Error al guardar el archivo: {e}")
        return False


def calcular_meses(anio=None, mes=None, dia=None):
    """
    Devuelve lista de (anio, mes) a procesar y opcionalmente el día específico.
    No incluye meses futuros (más allá del mes actual).
    """
    hoy = datetime.date.today()

    if anio is None:
        return [(hoy.year, hoy.month)], hoy.day
    if mes is None:
        meses = [
            (anio, m) for m in range(1, 13)
            if datetime.date(anio, m, 1) <= hoy.replace(day=1)
        ]
        return meses, None
    # Validar que no sea un mes futuro
    if datetime.date(anio, mes, 1) > hoy.replace(day=1):
        return [], dia
    return [(anio, mes)], dia


def main():
    parser = argparse.ArgumentParser(
        description="Descarga boletines oficiales de Jujuy",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Ejemplos de uso:
  %(prog)s                                 # Boletín del día actual
  %(prog)s --anio 2024                     # Todo el año 2024
  %(prog)s --anio 2024 --mes 5             # Mayo de 2024
  %(prog)s --anio 2024 --mes 5 --dia 15    # 15 de mayo de 2024
        """
    )
    parser.add_argument("--anio", type=int, help="Año a descargar")
    parser.add_argument("--mes", type=int, help="Mes a descargar (1-12)")
    parser.add_argument("--dia", type=int, help="Día específico (1-31)")
    parser.add_argument("--directorio", type=str, default="pendientes/jujuy",
                        help="Directorio de destino (por defecto: pendientes/jujuy)")

    args = parser.parse_args()

    if args.mes is not None and (args.mes < 1 or args.mes > 12):
        parser.error("El mes debe estar entre 1 y 12")
    if args.dia is not None and (args.dia < 1 or args.dia > 31):
        parser.error("El día debe estar entre 1 y 31")
    if args.dia is not None and args.mes is None:
        parser.error("Si especificás un día, debés especificar también el mes")
    if args.mes is not None and args.anio is None:
        parser.error("Si especificás un mes, debés especificar también el año")

    meses, dia_especifico = calcular_meses(args.anio, args.mes, args.dia)

    if not meses:
        parser.error(f"{args.anio}/{args.mes:02d} es un mes futuro, todavía no hay boletines publicados.")

    print("=" * 70)
    print("  DESCARGA DE BOLETINES OFICIALES - JUJUY")
    print("=" * 70)
    print()

    os.makedirs(args.directorio, exist_ok=True)
    print(f"📁 Directorio de destino: {args.directorio}")
    print(f"🌐 Sitio web: {BASE_URL}/?page_id={PAGE_ID}")
    print()

    session = requests.Session()
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                      "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Accept-Language": "es-ES,es;q=0.9",
    })

    total = 0
    descargados = 0
    no_disponibles = 0
    ya_existentes = 0

    for anio, mes in meses:
        print(f"📅 Procesando {anio}/{mes:02d}...")
        links = obtener_links_mes(anio, mes, session)

        if not links:
            print(f"  ⚠️  No se encontraron boletines para {anio}/{mes:02d}")
            continue

        # Filtrar por día específico si aplica
        if dia_especifico is not None:
            try:
                fecha_filtro = datetime.date(anio, mes, dia_especifico)
                links = {k: v for k, v in links.items() if k == fecha_filtro}
            except ValueError:
                pass

        for fecha in sorted(links):
            total += 1
            url_pdf = links[fecha]
            archivo_path = os.path.join(args.directorio, f"boletin_{fecha.strftime('%Y-%m-%d')}.pdf")

            print(f"[{total}] {fecha.strftime('%Y-%m-%d')}")

            if ya_existe_en_provincia(args.directorio, os.path.basename(archivo_path)):
                print(f"  ⏭️  Ya existe, saltando...")
                ya_existentes += 1
                continue

            if descargar_pdf(url_pdf, fecha, args.directorio, session):
                descargados += 1
            else:
                no_disponibles += 1

        print()

    print("=" * 70)
    print("  RESUMEN DE DESCARGA")
    print("=" * 70)
    print(f"📊 Total boletines encontrados: {total}")
    print(f"✅ Descargados: {descargados}")
    print(f"⏭️  Ya existían: {ya_existentes}")
    print(f"⚠️  No disponibles: {no_disponibles}")
    print(f"📁 Directorio: {args.directorio}")
    print()
    print("✨ Proceso completado!")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n⚠️  Descarga interrumpida por el usuario")
        exit(130)
    except Exception as e:
        print(f"\n❌ Error inesperado: {e}")
        import traceback
        traceback.print_exc()
        exit(1)
