#!/usr/bin/env python3
"""
Descarga boletines de Tierra del Fuego desde Google Drive.

Estructura en Drive: Año → Mes (01 - Enero, 02 - Febrero...) → B.O. XXXX.pdf
La fecha se extrae del contenido del PDF con pdfplumber.

Uso:
    python descargar_tierrafuego.py
    python descargar_tierrafuego.py --anio 2026
    python descargar_tierrafuego.py --anio 2026 --mes 6
    python descargar_tierrafuego.py --limit 5
    python descargar_tierrafuego.py --dry-run
"""

import argparse
import datetime
import io
import os
import re
import shutil
import sys
import tempfile
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent.parent))
from helpers.db_resumen import guardar_dia_faltante

try:
    from google.auth.transport.requests import Request
    from google.oauth2.credentials import Credentials
    from google_auth_oauthlib.flow import InstalledAppFlow
    from googleapiclient.discovery import build
    from googleapiclient.http import MediaIoBaseDownload
except ImportError:
    print("Faltan dependencias. Ejecutá:")
    print("  pip install google-auth-oauthlib google-auth-httplib2 google-api-python-client")
    sys.exit(1)

try:
    import pdfplumber
except ImportError:
    print("Falta pdfplumber. Ejecutá: pip install pdfplumber")
    sys.exit(1)

_ROOT = Path(__file__).resolve().parent.parent.parent.parent
CREDENTIALS_PATH = Path(__file__).parent / "credentials.json"
TOKEN_PATH = Path(__file__).parent / "tierrafuego_token.json"
DIRECTORIO = str(_ROOT / "files" / "boletines" / "tierra_del_fuego" / "sin_procesar")
FOLDER_ID = "12GrKybtm4cWyS6Ib_DnbwKAQ6JvQHCU6"

SCOPES = ["https://www.googleapis.com/auth/drive.readonly"]

PATRON_FECHA_TEXTO = re.compile(
    r'(\d{1,2})\s+[Dd][Ee]\s+(\w+)\s+[Dd][Ee]\s+(\d{4})',
    re.IGNORECASE
)
PATRON_FECHA_NUM = re.compile(r'(\d{2})[/\-\.](\d{2})[/\-\.](\d{4})')

MESES_ES = {
    'enero': '01', 'febrero': '02', 'marzo': '03', 'abril': '04',
    'mayo': '05', 'junio': '06', 'julio': '07', 'agosto': '08',
    'septiembre': '09', 'octubre': '10', 'noviembre': '11', 'diciembre': '12',
}


def autenticar():
    creds = None
    if TOKEN_PATH.exists():
        creds = Credentials.from_authorized_user_file(str(TOKEN_PATH), SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            if not CREDENTIALS_PATH.exists():
                print(f"ERROR: No se encontró {CREDENTIALS_PATH}")
                sys.exit(1)
            flow = InstalledAppFlow.from_client_secrets_file(str(CREDENTIALS_PATH), SCOPES)
            creds = flow.run_local_server(port=0)
        with open(TOKEN_PATH, "w") as f:
            f.write(creds.to_json())
        print(f"Token guardado en {TOKEN_PATH}")
    return creds


def listar_carpetas(drive, parent_id):
    items = []
    page_token = None
    while True:
        resp = drive.files().list(
            q=f"'{parent_id}' in parents and trashed=false and mimeType='application/vnd.google-apps.folder'",
            fields="nextPageToken, files(id, name)",
            pageSize=500,
            pageToken=page_token,
        ).execute()
        items.extend(resp.get("files", []))
        page_token = resp.get("nextPageToken")
        if not page_token:
            break
    return items


def listar_pdfs(drive, parent_id):
    items = []
    page_token = None
    while True:
        resp = drive.files().list(
            q=f"'{parent_id}' in parents and trashed=false and mimeType='application/pdf'",
            fields="nextPageToken, files(id, name)",
            pageSize=500,
            pageToken=page_token,
        ).execute()
        items.extend(resp.get("files", []))
        page_token = resp.get("nextPageToken")
        if not page_token:
            break
    return items


def extraer_fecha_pdf(ruta_pdf):
    try:
        with pdfplumber.open(ruta_pdf) as pdf:
            for page in pdf.pages[:3]:
                texto = page.extract_text() or ""

                m = PATRON_FECHA_TEXTO.search(texto)
                if m:
                    dia, mes_nombre, anio = m.groups()
                    mes = MESES_ES.get(mes_nombre.lower())
                    if mes:
                        return f"{anio}-{mes}-{dia.zfill(2)}"

                m = PATRON_FECHA_NUM.search(texto)
                if m:
                    dia, mes, anio = m.groups()
                    return f"{anio}-{mes}-{dia}"
    except Exception as e:
        print(f"  [PDF] Error leyendo: {e}")
    return None


def descargar_archivo(drive, file_id, ruta_destino):
    request = drive.files().get_media(fileId=file_id)
    buffer = io.BytesIO()
    downloader = MediaIoBaseDownload(buffer, request)
    done = False
    while not done:
        _, done = downloader.next_chunk()
    with open(ruta_destino, "wb") as f:
        f.write(buffer.getvalue())


def ya_existe(fecha_iso, directorio):
    provincia_dir = Path(directorio).parent
    nombre = f"boletin_{fecha_iso}.pdf"
    return any(f.name == nombre for f in provincia_dir.rglob("*.pdf"))


def main():
    parser = argparse.ArgumentParser(description="Descarga boletines de Tierra del Fuego desde Google Drive")
    parser.add_argument("--anio", type=int, default=None)
    parser.add_argument("--mes", type=int, default=None)
    parser.add_argument("--limit", type=int, default=None)
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("--directorio", type=str, default=DIRECTORIO)
    args = parser.parse_args()

    directorio = args.directorio
    os.makedirs(directorio, exist_ok=True)

    print("Autenticando con Google Drive...")
    creds = autenticar()
    drive = build("drive", "v3", credentials=creds)

    hoy = datetime.date.today()
    anio_filtro = args.anio or hoy.year
    mes_filtro = args.mes or hoy.month

    # Listar carpetas de año
    carpetas_anio = listar_carpetas(drive, FOLDER_ID)
    carpetas_anio = [c for c in carpetas_anio if c["name"].strip() == str(anio_filtro)]
    print(f"Años encontrados: {[c['name'] for c in carpetas_anio]}")

    descargados = 0
    errores = 0
    omitidos = 0

    for carpeta_anio in sorted(carpetas_anio, key=lambda x: x["name"]):
        print(f"\n── {carpeta_anio['name']} ──")

        carpetas_mes = listar_carpetas(drive, carpeta_anio["id"])
        prefijo = f"{mes_filtro:02d}"
        carpetas_mes = [c for c in carpetas_mes if c["name"].startswith(prefijo)]

        for carpeta_mes in sorted(carpetas_mes, key=lambda x: x["name"]):
            print(f"  {carpeta_mes['name']}")
            pdfs = listar_pdfs(drive, carpeta_mes["id"])

            for f in sorted(pdfs, key=lambda x: x["name"]):
                nombre = f["name"]

                if args.dry_run:
                    print(f"    [DRY-RUN] {nombre}")
                    continue

                with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
                    tmp_path = tmp.name

                fecha_iso = None
                try:
                    descargar_archivo(drive, f["id"], tmp_path)
                    fecha_iso = extraer_fecha_pdf(tmp_path)

                    if not fecha_iso:
                        print(f"    [AVISO] No se pudo extraer fecha de '{nombre}' — omitido")
                        errores += 1
                        continue

                    if ya_existe(fecha_iso, directorio):
                        print(f"    Ya existe: boletin_{fecha_iso}.pdf — saltando")
                        omitidos += 1
                        continue

                    nombre_final = f"boletin_{fecha_iso}.pdf"
                    ruta_final = os.path.join(directorio, nombre_final)
                    shutil.move(tmp_path, ruta_final)
                    print(f"    Guardado: {nombre_final}  (fuente: {nombre})")
                    descargados += 1

                    if args.limit and descargados >= args.limit:
                        print(f"\nLímite alcanzado ({args.limit})")
                        print(f"\nRESUMEN | TIERRA DEL FUEGO | descargados={descargados} omitidos={omitidos} errores={errores}")
                        return

                except Exception as e:
                    print(f"    [ERROR] {nombre}: {e}")
                    errores += 1
                    if fecha_iso:
                        guardar_dia_faltante("TIERRA DEL FUEGO", fecha_iso, 'error_descarga')
                finally:
                    if os.path.exists(tmp_path):
                        os.unlink(tmp_path)

    print(f"\nRESUMEN | TIERRA DEL FUEGO | descargados={descargados} omitidos={omitidos} errores={errores}")


if __name__ == "__main__":
    main()
