#!/usr/bin/env python3
"""
Descarga boletines de Formosa desde Google Drive.

La carpeta compartida contiene archivos "BOLETIN XXXXX.pdf".
La fecha se extrae del contenido del PDF con pdfplumber.

Uso:
    python descargar_formosa.py
    python descargar_formosa.py --limit 5
    python descargar_formosa.py --dry-run
"""

import argparse
import io
import os
import re
import sys
import shutil
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 / "formosa_token.json"
DIRECTORIO = str(_ROOT / "files" / "boletines" / "formosa" / "sin_procesar")
FOLDER_ID = "1pJtSYuFDlAe__7uDRf969Gbxjjx5iiyt"

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_archivos(drive):
    archivos = []
    page_token = None
    while True:
        resp = drive.files().list(
            q=f"'{FOLDER_ID}' in parents and trashed=false and mimeType='application/pdf'",
            fields="nextPageToken, files(id, name)",
            pageSize=500,
            pageToken=page_token,
        ).execute()
        archivos.extend(resp.get("files", []))
        page_token = resp.get("nextPageToken")
        if not page_token:
            break
    return archivos


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):
    destino = Path(DIRECTORIO).parent
    nombre = f"boletin_{fecha_iso}.pdf"
    return any(f.name == nombre for f in destino.rglob("*.pdf"))


def main():
    parser = argparse.ArgumentParser(description="Descarga boletines de Formosa desde Google Drive")
    parser.add_argument("--limit", type=int, default=None, help="Máximo de archivos a descargar")
    parser.add_argument("--dry-run", action="store_true", help="Muestra qué descargaría sin bajar nada")
    parser.add_argument("--directorio", type=str, default=DIRECTORIO, help="Carpeta destino de los PDFs")
    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)

    print(f"Listando archivos en Drive...")
    archivos = listar_archivos(drive)
    print(f"Archivos encontrados: {len(archivos)}")

    descargados = 0
    errores = 0
    omitidos = 0

    for f in archivos:
        nombre = f["name"]
        file_id = f["id"]

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

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

            # Descarga temporal para leer la fecha
            descargar_archivo(drive, file_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):
                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})")
                break

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

    print(f"\nRESUMEN | FORMOSA | descargados={descargados} omitidos={omitidos} errores={errores}")


if __name__ == "__main__":
    main()
