#!/usr/bin/env python3
"""
postar_semana.py — Publica os posts da semana no Instagram via Graph API.

Uso:
    python3 postar_semana.py --dia 1 --post 1          # Posta 1 post específico
    python3 postar_semana.py --dia 1                    # Posta todos os 5 posts do dia
    python3 postar_semana.py --dia 1 --post 1 --simulacao  # Simula sem postar
    python3 postar_semana.py --proximo                  # Posta o próximo post pendente
    python3 postar_semana.py --status                   # Mostra status de todos os posts
"""

import argparse
import json
import sys
import time
import urllib.request
import urllib.parse
import urllib.error
from datetime import datetime, timedelta
from pathlib import Path

SCRIPT_DIR = Path(__file__).parent.resolve()
CONFIG_PATH = SCRIPT_DIR / "config.json"
LOG_PATH = SCRIPT_DIR / "log-semana.json"

BASE_URL = "https://gateway.saraiva.ai/insta-public/semana"

TEMPLATES = {1: "atencao", 2: "autoridade", 3: "educativo", 4: "bastidor", 5: "conversao"}

# Horários de postagem (config.json: 07:00, 10:00, 13:00, 17:00, 20:00)
HORARIOS = ["07:00", "10:00", "13:00", "17:00", "20:00"]


def carregar_config():
    with open(CONFIG_PATH, "r", encoding="utf-8") as f:
        return json.load(f)


def carregar_log():
    if LOG_PATH.exists():
        with open(LOG_PATH, "r", encoding="utf-8") as f:
            try:
                return json.load(f)
            except json.JSONDecodeError:
                return {"postados": [], "erros": []}
    return {"postados": [], "erros": []}


def salvar_log(log):
    with open(LOG_PATH, "w", encoding="utf-8") as f:
        json.dump(log, f, ensure_ascii=False, indent=2)


def carregar_captions(dia_num):
    # Tenta path local (desenvolvimento) e path servidor
    candidatos = [
        SCRIPT_DIR / "imagens" / "semana" / f"dia-{dia_num:02d}" / "captions.json",
        SCRIPT_DIR / f"dia-{dia_num:02d}" / "captions.json",
    ]
    for captions_path in candidatos:
        if captions_path.exists():
            with open(captions_path, "r", encoding="utf-8") as f:
                return json.load(f)
    print(f"[ERRO] Captions não encontrados para dia {dia_num}", file=sys.stderr)
    return []


def url_imagem(dia_num, post_num):
    template = TEMPLATES.get(post_num, "atencao")
    return f"{BASE_URL}/dia-{dia_num:02d}/post-{post_num}-{template}.png"


def ja_postado(log, dia_num, post_num):
    for p in log["postados"]:
        if p["dia"] == dia_num and p["post"] == post_num:
            return True
    return False


def postar_graph_api(image_url, caption, config):
    access_token = config.get("instagram_access_token", "")
    account_id = config.get("instagram_business_account_id", "")

    if not access_token or not account_id:
        return False, "Graph API não configurada em config.json"

    # Passo 1: Criar container
    try:
        params = urllib.parse.urlencode({
            "image_url": image_url,
            "caption": caption,
            "access_token": access_token
        })
        url = f"https://graph.facebook.com/v18.0/{account_id}/media?{params}"
        req = urllib.request.Request(url, method="POST")
        with urllib.request.urlopen(req, timeout=30) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            container_id = data.get("id")

        if not container_id:
            return False, f"Falha ao criar container: {data}"
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")
        return False, f"Erro HTTP container: {e.code} - {body}"
    except Exception as e:
        return False, f"Erro container: {e}"

    # Aguardar processamento do container
    import time as _time
    for attempt in range(6):
        _time.sleep(10)
        try:
            status_url = f"https://graph.facebook.com/v18.0/{container_id}?fields=status_code&access_token={access_token}"
            req_s = urllib.request.Request(status_url)
            with urllib.request.urlopen(req_s, timeout=15) as resp_s:
                status_data = json.loads(resp_s.read().decode("utf-8"))
                status_code = status_data.get("status_code", "")
                if status_code == "FINISHED":
                    break
                print(f"    Container status: {status_code} (tentativa {attempt+1}/6)")
        except Exception:
            pass

    # Passo 2: Publicar
    try:
        params = urllib.parse.urlencode({
            "creation_id": container_id,
            "access_token": access_token
        })
        url = f"https://graph.facebook.com/v18.0/{account_id}/media_publish?{params}"
        req = urllib.request.Request(url, method="POST")
        with urllib.request.urlopen(req, timeout=30) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            media_id = data.get("id")

        if media_id:
            return True, f"Media ID: {media_id}"
        else:
            return False, f"Resposta inesperada: {data}"
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")
        return False, f"Erro HTTP publish: {e.code} - {body}"
    except Exception as e:
        return False, f"Erro publish: {e}"


def postar_um(dia_num, post_num, config, log, simulacao=False):
    captions = carregar_captions(dia_num)
    if not captions:
        return False

    post_data = None
    for c in captions:
        if c["post"] == post_num:
            post_data = c
            break

    if not post_data:
        print(f"[ERRO] Post {post_num} não encontrado nos captions do dia {dia_num}")
        return False

    image_url = url_imagem(dia_num, post_num)
    caption = post_data["caption"]

    print(f"\n  Dia {dia_num} | Post {post_num} ({post_data['tipo']})")
    print(f"  Imagem: {image_url}")
    print(f"  Caption: {caption[:80]}...")

    if simulacao:
        print(f"  [SIMULAÇÃO] Post simulado com sucesso")
        return True

    sucesso, detalhes = postar_graph_api(image_url, caption, config)

    registro = {
        "dia": dia_num,
        "post": post_num,
        "tipo": post_data["tipo"],
        "frase": post_data["frase"],
        "timestamp": datetime.now().isoformat(),
        "detalhes": detalhes
    }

    if sucesso:
        log["postados"].append(registro)
        salvar_log(log)
        print(f"  [OK] Publicado! {detalhes}")
    else:
        registro["erro"] = detalhes
        log["erros"].append(registro)
        salvar_log(log)
        print(f"  [FALHA] {detalhes}")

    return sucesso


def mostrar_status(log):
    print(f"\n{'='*60}")
    print(f"  STATUS DA SEMANA — @saraiva.ai")
    print(f"{'='*60}")

    for dia in range(1, 8):
        captions = carregar_captions(dia)
        if not captions:
            continue
        print(f"\n  Dia {dia}:")
        for c in captions:
            postado = ja_postado(log, dia, c["post"])
            status = "✅" if postado else "⬜"
            print(f"    {status} Post {c['post']} ({c['tipo']}): {c['frase'][:50]}...")

    total = len(log["postados"])
    print(f"\n  Total postados: {total}/35")
    print(f"  Erros: {len(log['erros'])}")
    print(f"{'='*60}")


def proximo_pendente(log):
    """Encontra o próximo post não postado."""
    for dia in range(1, 8):
        captions = carregar_captions(dia)
        for c in captions:
            if not ja_postado(log, dia, c["post"]):
                return dia, c["post"]
    return None, None


def main():
    parser = argparse.ArgumentParser(description="Postar semana @saraiva.ai no Instagram")
    parser.add_argument("--dia", "-d", type=int, help="Dia (1-7)")
    parser.add_argument("--post", "-p", type=int, help="Post específico (1-5)")
    parser.add_argument("--proximo", action="store_true", help="Posta o próximo pendente")
    parser.add_argument("--status", action="store_true", help="Mostra status")
    parser.add_argument("--simulacao", action="store_true", help="Simula sem postar")
    parser.add_argument("--intervalo", type=int, default=30, help="Segundos entre posts (default: 30)")

    args = parser.parse_args()
    config = carregar_config()
    log = carregar_log()

    if args.status:
        mostrar_status(log)
        return

    if args.proximo:
        dia, post = proximo_pendente(log)
        if dia is None:
            print("Todos os 35 posts já foram publicados!")
            return
        print(f"Próximo pendente: Dia {dia}, Post {post}")
        postar_um(dia, post, config, log, args.simulacao)
        return

    if args.dia and args.post:
        if ja_postado(log, args.dia, args.post):
            print(f"Dia {args.dia}, Post {args.post} já foi postado. Use --status para ver.")
            return
        postar_um(args.dia, args.post, config, log, args.simulacao)
        return

    if args.dia:
        print(f"\nPostando todos os posts do Dia {args.dia}...")
        for post_num in range(1, 6):
            if ja_postado(log, args.dia, post_num):
                print(f"  ⏭ Dia {args.dia}, Post {post_num} já postado, pulando...")
                continue
            sucesso = postar_um(args.dia, args.post if args.post else post_num, config, log, args.simulacao)
            if sucesso and post_num < 5:
                print(f"  Aguardando {args.intervalo}s...")
                time.sleep(args.intervalo)
        mostrar_status(log)
        return

    parser.print_help()


if __name__ == "__main__":
    main()
