#!/usr/bin/env python3
"""
postar_instagram.py — Publica uma imagem no Instagram.

Uso:
    python3 postar_instagram.py --imagem /caminho/imagem.png --caption "Texto do post"
    python3 postar_instagram.py --imagem /caminho/imagem.png --caption "Texto" --metodo graph_api
    python3 postar_instagram.py --imagem /caminho/imagem.png --caption "Texto" --metodo simulacao

Metodos disponiveis:
    graph_api  - Instagram Graph API (requer access_token e business_account_id em config.json)
    simulacao  - Apenas simula e registra no log (para testes)
"""

import argparse
import json
import os
import sys
import urllib.request
import urllib.parse
import urllib.error
from datetime import datetime
from pathlib import Path

SCRIPT_DIR = Path(__file__).parent.resolve()
CONFIG_PATH = SCRIPT_DIR / "config.json"


def carregar_config():
    if not CONFIG_PATH.exists():
        print(f"[ERRO] Arquivo de configuracao nao encontrado: {CONFIG_PATH}")
        sys.exit(1)
    with open(CONFIG_PATH, "r", encoding="utf-8") as f:
        return json.load(f)


def carregar_log(log_path):
    if os.path.exists(log_path):
        with open(log_path, "r", encoding="utf-8") as f:
            try:
                return json.load(f)
            except json.JSONDecodeError:
                return []
    return []


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


def registrar_postagem(log_path, imagem, caption, metodo, sucesso, detalhes=""):
    registros = carregar_log(log_path)
    registro = {
        "timestamp": datetime.now().isoformat(),
        "imagem": str(imagem),
        "caption": caption[:100] + "..." if len(caption) > 100 else caption,
        "metodo": metodo,
        "sucesso": sucesso,
        "detalhes": detalhes
    }
    registros.append(registro)
    salvar_log(log_path, registros)
    return registro


def postar_graph_api(imagem, caption, config):
    """
    Publica via Instagram Graph API (Container + Publish).
    Requer:
      - instagram_access_token em config.json
      - instagram_business_account_id em config.json
      - A imagem precisa estar acessivel por URL publico
    """
    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 nao configurada. "
            "Preencha 'instagram_access_token' e 'instagram_business_account_id' em config.json. "
            "Para testes, use --metodo simulacao"
        )

    # A Graph API exige URL publica da imagem.
    # Se a imagem for local, o usuario precisa fazer upload para um servidor primeiro.
    if not imagem.startswith("http"):
        return False, (
            f"A Graph API requer URL publica da imagem. "
            f"Imagem local detectada: {imagem}. "
            f"Faca upload para um servidor e passe a URL, ou use --metodo simulacao."
        )

    # Passo 1: Criar container de midia
    try:
        params_container = urllib.parse.urlencode({
            "image_url": imagem,
            "caption": caption,
            "access_token": access_token
        })
        url_container = f"https://graph.facebook.com/v18.0/{account_id}/media?{params_container}"

        req = urllib.request.Request(url_container, 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 ao criar container: {e.code} - {body}"
    except Exception as e:
        return False, f"Erro ao criar container: {e}"

    # Passo 2: Publicar o container
    try:
        params_publish = urllib.parse.urlencode({
            "creation_id": container_id,
            "access_token": access_token
        })
        url_publish = f"https://graph.facebook.com/v18.0/{account_id}/media_publish?{params_publish}"

        req = urllib.request.Request(url_publish, 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"Publicado com sucesso! 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 ao publicar: {e.code} - {body}"
    except Exception as e:
        return False, f"Erro ao publicar: {e}"


def postar_simulacao(imagem, caption, config):
    """Simula a postagem sem enviar nada. Util para testes."""
    print(f"  [SIMULACAO] Postagem simulada com sucesso")
    print(f"  [SIMULACAO] Imagem: {imagem}")
    print(f"  [SIMULACAO] Caption: {caption[:80]}...")
    print(f"  [SIMULACAO] Usuario: {config.get('instagram_username', 'N/A')}")
    return True, "Postagem simulada (modo teste)"


METODOS = {
    "graph_api": postar_graph_api,
    "simulacao": postar_simulacao,
}


def main():
    parser = argparse.ArgumentParser(
        description="Publica uma imagem no Instagram"
    )
    parser.add_argument(
        "--imagem", required=True,
        help="Caminho da imagem ou URL publica"
    )
    parser.add_argument(
        "--caption", required=True,
        help="Texto/legenda do post"
    )
    parser.add_argument(
        "--metodo", default=None,
        choices=list(METODOS.keys()),
        help="Metodo de postagem (default: valor em config.json)"
    )
    parser.add_argument(
        "--config", default=None,
        help="Caminho para config.json alternativo"
    )

    args = parser.parse_args()

    # Carregar config
    global CONFIG_PATH
    if args.config:
        CONFIG_PATH = Path(args.config)
    config = carregar_config()

    log_path = config.get("log_file", str(SCRIPT_DIR / "log-postagens.json"))
    metodo = args.metodo or config.get("metodo_postagem", "simulacao")

    # Validar imagem local
    if not args.imagem.startswith("http") and not os.path.exists(args.imagem):
        print(f"[ERRO] Imagem nao encontrada: {args.imagem}")
        registrar_postagem(log_path, args.imagem, args.caption, metodo, False, "Imagem nao encontrada")
        sys.exit(1)

    print(f"{'='*60}")
    print(f"  POSTAR INSTAGRAM - @{config.get('instagram_username', 'N/A')}")
    print(f"{'='*60}")
    print(f"  Metodo:  {metodo}")
    print(f"  Imagem:  {args.imagem}")
    print(f"  Caption: {args.caption[:60]}{'...' if len(args.caption) > 60 else ''}")
    print(f"{'='*60}")

    # Executar postagem
    func = METODOS.get(metodo)
    if not func:
        print(f"[ERRO] Metodo desconhecido: {metodo}")
        sys.exit(1)

    sucesso, detalhes = func(args.imagem, args.caption, config)

    # Registrar no log
    registro = registrar_postagem(log_path, args.imagem, args.caption, metodo, sucesso, detalhes)

    if sucesso:
        print(f"\n  [OK] Postagem realizada com sucesso!")
        print(f"  [OK] {detalhes}")
    else:
        print(f"\n  [FALHA] Postagem falhou!")
        print(f"  [FALHA] {detalhes}")

    print(f"\n  Log salvo em: {log_path}")
    print(f"{'='*60}")

    sys.exit(0 if sucesso else 1)


if __name__ == "__main__":
    main()
