#!/usr/bin/env python3
"""
Migration Tool: SQLite (wview) → PostgreSQL (wetterstation)
Migriert Wetterdaten vom 1.1.2025 bis heute
"""

import sqlite3
import psycopg
from datetime import datetime, timezone
import os
from pathlib import Path
from dotenv import load_dotenv
import sys

# Umgebungsvariablen laden
env_path = Path(__file__).parent / '.env'
load_dotenv(dotenv_path=env_path)

# Konfiguration
SQLITE_DB = "data/wview-archive.sdb"
START_DATE = datetime(2025, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
END_DATE = datetime(2026, 3, 23, 0, 0, 0, tzinfo=timezone.utc)

# PostgreSQL-Konfiguration
DB_HOST = os.getenv('DB_HOST', 'localhost')
DB_PORT = int(os.getenv('DB_PORT', 5432))
DB_NAME = os.getenv('DB_NAME', 'wetterstation')
DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')

# Soll die Tabelle vorher geleert werden?
TRUNCATE_TABLE = False  # Auf False setzen, um vorhandene Daten zu behalten

# Konvertierungsfunktionen
def fahrenheit_to_celsius(f):
    """Fahrenheit → Celsius"""
    if f is None:
        return None
    return (f - 32) * 5 / 9

def inches_hg_to_hpa(inhg):
    """inches Hg → hPa"""
    if inhg is None:
        return None
    return inhg * 33.8639

def mph_to_kmh(mph):
    """mph → km/h"""
    if mph is None:
        return None
    return mph * 1.60934

def inches_to_mm(inches):
    """inches → mm"""
    if inches is None:
        return None
    return inches * 25.4

def unix_to_datetime(timestamp):
    """Unix timestamp → datetime"""
    return datetime.fromtimestamp(timestamp, tz=timezone.utc)


def main():
    print("=" * 60)
    print("SQLite → PostgreSQL Migration")
    print("=" * 60)
    print(f"Quelle: {SQLITE_DB}")
    print(f"Zeitraum: {START_DATE.date()} bis {END_DATE.date()}")
    print(f"Ziel: PostgreSQL ({DB_HOST}:{DB_PORT}/{DB_NAME})")
    print("=" * 60)
    print()
    
    # SQLite öffnen
    try:
        sqlite_conn = sqlite3.connect(SQLITE_DB)
        sqlite_cursor = sqlite_conn.cursor()
        print("✓ SQLite-Verbindung hergestellt")
    except Exception as e:
        print(f"✗ Fehler beim Öffnen der SQLite-Datenbank: {e}")
        sys.exit(1)
    
    # PostgreSQL öffnen
    try:
        pg_conn = psycopg.connect(
            host=DB_HOST,
            port=DB_PORT,
            dbname=DB_NAME,
            user=DB_USER,
            password=DB_PASSWORD
        )
        pg_cursor = pg_conn.cursor()
        print("✓ PostgreSQL-Verbindung hergestellt")
    except Exception as e:
        print(f"✗ Fehler beim Verbinden mit PostgreSQL: {e}")
        sqlite_conn.close()
        sys.exit(1)
    
    # Tabelle anlegen falls nicht vorhanden
    try:
        pg_cursor.execute("""
            CREATE TABLE IF NOT EXISTS weather_data (
                id SERIAL PRIMARY KEY,
                datetime TIMESTAMPTZ NOT NULL,
                temperature FLOAT,
                humidity INTEGER,
                pressure FLOAT,
                wind_speed FLOAT,
                wind_gust FLOAT,
                wind_dir FLOAT,
                rain FLOAT,
                rain_rate FLOAT,
                temp_in FLOAT,
                humidity_in INTEGER,
                forecast INTEGER,
                bar_trend INTEGER,
                source VARCHAR,
                received_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                UNIQUE(datetime)
            )
        """)
        pg_cursor.execute(
            "CREATE INDEX IF NOT EXISTS idx_weather_datetime_desc "
            "ON weather_data (datetime DESC)"
        )
        pg_conn.commit()
        print("✓ Tabelle weather_data bereit")
    except Exception as e:
        print(f"✗ Fehler beim Anlegen der Tabelle: {e}")
        sqlite_conn.close()
        pg_conn.close()
        sys.exit(1)

    # Tabelle leeren falls gewünscht
    if TRUNCATE_TABLE:
        print("\nLeere PostgreSQL-Tabelle weather_data...")
        try:
            pg_cursor.execute("TRUNCATE TABLE weather_data RESTART IDENTITY CASCADE")
            pg_conn.commit()
            print("✓ Tabelle geleert")
        except Exception as e:
            print(f"✗ Fehler beim Leeren der Tabelle: {e}")
            sqlite_conn.close()
            pg_conn.close()
            sys.exit(1)
    
    # Zeitraum in Unix timestamps umrechnen
    start_ts = int(START_DATE.timestamp())
    end_ts = int(END_DATE.timestamp())
    
    # Daten aus SQLite laden
    print(f"\nLade Daten aus SQLite (Zeitraum: {start_ts} - {end_ts})...")
    sqlite_cursor.execute("""
        SELECT 
            dateTime,
            outTemp,
            outHumidity,
            barometer,
            windSpeed,
            windGust,
            windDir,
            rain,
            rainRate
        FROM archive
        WHERE dateTime >= ? AND dateTime <= ?
        ORDER BY dateTime ASC
    """, (start_ts, end_ts))
    
    rows = sqlite_cursor.fetchall()
    print(f"✓ {len(rows)} Datensätze gefunden")
    
    if len(rows) == 0:
        print("Keine Daten im angegebenen Zeitraum gefunden.")
        sqlite_conn.close()
        pg_conn.close()
        return
    
    # Migration durchführen
    print("\nMigriere Daten...")
    inserted = 0
    skipped = 0
    errors = 0
    
    for row in rows:
        try:
            (dateTime, outTemp, outHumidity, barometer, 
             windSpeed, windGust, windDir, rain, rainRate) = row
            
            # Konvertierungen
            dt = unix_to_datetime(dateTime)
            temp_c = fahrenheit_to_celsius(outTemp)
            humidity = int(outHumidity) if outHumidity is not None else None
            pressure_hpa = inches_hg_to_hpa(barometer)
            wind_speed_kmh = mph_to_kmh(windSpeed)
            wind_gust_kmh = mph_to_kmh(windGust)
            rain_mm = inches_to_mm(rain)
            rain_rate_mm = inches_to_mm(rainRate)
            
            # In PostgreSQL einfügen
            pg_cursor.execute("""
                INSERT INTO weather_data
                (datetime, temperature, humidity, pressure,
                 wind_speed, wind_gust, wind_dir, rain, rain_rate, source)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                ON CONFLICT (datetime) DO NOTHING
            """, (dt, temp_c, humidity, pressure_hpa,
                  wind_speed_kmh, wind_gust_kmh, windDir, rain_mm, rain_rate_mm, 'wview'))
            
            if pg_cursor.rowcount > 0:
                inserted += 1
                if inserted % 1000 == 0:
                    pg_conn.commit()
                    print(f"  {inserted} Datensätze eingefügt...")
            else:
                skipped += 1
                
        except Exception as e:
            errors += 1
            if errors <= 5:  # Zeige nur die ersten 5 Fehler
                print(f"  Fehler bei Datensatz {dateTime}: {e}")
    
    # Commit verbleibende Daten
    pg_conn.commit()
    
    # Zusammenfassung
    print("\n" + "=" * 60)
    print("Migration abgeschlossen!")
    print("=" * 60)
    print(f"Eingefügt:   {inserted} Datensätze")
    print(f"Übersprungen: {skipped} Datensätze (bereits vorhanden)")
    print(f"Fehler:      {errors} Datensätze")
    print("=" * 60)
    
    # Zeitraum der migrierten Daten anzeigen
    if inserted > 0:
        pg_cursor.execute("""
            SELECT MIN(datetime), MAX(datetime), COUNT(*)
            FROM weather_data
            WHERE datetime >= %s AND datetime <= %s
        """, (START_DATE, END_DATE))
        min_dt, max_dt, count = pg_cursor.fetchone()
        print(f"\nDaten in PostgreSQL:")
        print(f"  Von:    {min_dt}")
        print(f"  Bis:    {max_dt}")
        print(f"  Gesamt: {count} Datensätze")
    
    # Verbindungen schließen
    sqlite_conn.close()
    pg_conn.close()
    print("\n✓ Fertig!")


if __name__ == "__main__":
    main()
