#!/usr/bin/env python3
"""
Script para extrair lugares salvos do Apple Maps
Requer que o aplicativo Maps esteja fechado
"""

import sqlite3
import json
import os
import sys
from pathlib import Path
from datetime import datetime

# Caminhos dos bancos de dados do Maps
MAPS_DB_PATH = Path.home() / "Library/Containers/com.apple.geod/Data/Library/Caches/com.apple.geod/Vault/PDPlaceCache.db"
CLOUDKIT_DB_PATH = Path.home() / "Library/Containers/com.apple.Maps/Data/CloudKit/cloudd_db/db"

def check_maps_running():
    """Verifica se o Maps está rodando"""
    import subprocess
    result = subprocess.run(['ps', 'aux'], capture_output=True, text=True)
    return 'Maps.app' in result.stdout

def extract_places_from_pdcache():
    """Extrai lugares do PDPlaceCache.db"""
    if not MAPS_DB_PATH.exists():
        print(f"❌ Banco de dados não encontrado: {MAPS_DB_PATH}")
        return []

    try:
        conn = sqlite3.connect(str(MAPS_DB_PATH))
        cursor = conn.cursor()

        # Listar tabelas
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
        tables = cursor.fetchall()

        print(f"\n📊 Tabelas encontradas no PDPlaceCache.db:")
        for table in tables:
            print(f"  - {table[0]}")

        # Tentar extrair dados de cada tabela
        all_places = []
        for table in tables:
            table_name = table[0]
            try:
                cursor.execute(f"SELECT * FROM `{table_name}` LIMIT 5;")
                rows = cursor.fetchall()

                if rows:
                    # Obter nomes das colunas
                    cursor.execute(f"PRAGMA table_info(`{table_name}`);")
                    columns = [col[1] for col in cursor.fetchall()]

                    print(f"\n📋 Tabela: {table_name}")
                    print(f"   Colunas: {', '.join(columns)}")
                    print(f"   Total de registros: {len(rows)}")

                    # Converter para dict
                    for row in rows:
                        place = dict(zip(columns, row))
                        all_places.append({
                            'table': table_name,
                            'data': place
                        })
            except Exception as e:
                print(f"   ⚠️  Erro ao ler tabela {table_name}: {e}")

        conn.close()
        return all_places

    except sqlite3.OperationalError as e:
        if "database is locked" in str(e):
            print(f"\n❌ ERRO: O banco de dados está bloqueado!")
            print(f"   Por favor, feche o aplicativo Maps e tente novamente.")
            print(f"\n   Para fechar o Maps:")
            print(f"   $ killall Maps")
            return None
        else:
            print(f"❌ Erro ao acessar banco de dados: {e}")
            return None

def extract_from_cloudkit():
    """Extrai dados do CloudKit"""
    if not CLOUDKIT_DB_PATH.exists():
        print(f"❌ Banco CloudKit não encontrado: {CLOUDKIT_DB_PATH}")
        return []

    try:
        conn = sqlite3.connect(str(CLOUDKIT_DB_PATH))
        cursor = conn.cursor()

        # Verificar registros
        cursor.execute("SELECT COUNT(*) FROM '7';")
        count = cursor.fetchone()[0]

        if count == 0:
            print(f"\n📭 Nenhum registro encontrado no CloudKit")
            print(f"   (Pode ser que não esteja usando iCloud para sync do Maps)")
            return []

        cursor.execute("SELECT recordID, recordData, zoneIdentifier FROM '7';")
        records = cursor.fetchall()

        conn.close()
        return records

    except Exception as e:
        print(f"❌ Erro ao acessar CloudKit: {e}")
        return []

def save_to_json(data, filename):
    """Salva dados em JSON"""
    output_file = Path.home() / filename

    # Converter bytes para string (se houver)
    def convert_bytes(obj):
        if isinstance(obj, bytes):
            try:
                return obj.decode('utf-8')
            except:
                return str(obj)
        elif isinstance(obj, dict):
            return {k: convert_bytes(v) for k, v in obj.items()}
        elif isinstance(obj, list):
            return [convert_bytes(item) for item in obj]
        return obj

    data = convert_bytes(data)

    with open(output_file, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False, default=str)

    print(f"\n✅ Dados exportados para: {output_file}")
    print(f"   Total de registros: {len(data)}")

def main():
    print("=" * 70)
    print("🗺️  EXTRATOR DE LUGARES SALVOS DO APPLE MAPS")
    print("=" * 70)

    # Verificar se Maps está rodando
    if check_maps_running():
        print("\n⚠️  AVISO: O aplicativo Maps está aberto!")
        print("   Fechando o Maps automaticamente...")
        os.system('killall Maps')
        import time
        time.sleep(2)

    # Extrair dados do PDPlaceCache
    print("\n🔍 Extraindo dados do PDPlaceCache.db...")
    places = extract_places_from_pdcache()

    if places is None:
        sys.exit(1)

    if places:
        save_to_json(places, 'maps_places_pdcache.json')
    else:
        print("   📭 Nenhum lugar encontrado no PDPlaceCache")

    # Extrair dados do CloudKit
    print("\n🔍 Extraindo dados do CloudKit...")
    cloudkit_data = extract_from_cloudkit()

    if cloudkit_data:
        save_to_json(cloudkit_data, 'maps_places_cloudkit.json')

    # Resumo
    print("\n" + "=" * 70)
    print("📊 RESUMO DA EXTRAÇÃO")
    print("=" * 70)
    print(f"PDPlaceCache: {len(places) if places else 0} registros")
    print(f"CloudKit: {len(cloudkit_data)} registros")
    print("\n💡 DICA:")
    print("   Se não encontrou lugares salvos, tente:")
    print("   1. Exportar manualmente: Maps > Meus Guias > Compartilhar")
    print("   2. Verificar se está logado no iCloud")
    print("   3. Adicionar alguns lugares favoritos no Maps")
    print("=" * 70)

if __name__ == '__main__':
    main()
