"""Einmalige Datenmigration zu Multi-Tenancy.

Dieses Script:
1. Erstellt die AegisSight-Organisation
2. Erstellt eine permanente Lizenz fuer AegisSight
3. Weist bestehende Nutzer (rac00n, ch33tah) der AegisSight-Org zu
4. Setzt tenant_id auf alle bestehenden Daten
5. Erstellt Portal-Admin-Zugaenge
"""
import asyncio
import os
import sys
import shutil
from datetime import datetime

# Pfade fuer Imports
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from config import DB_PATH, TIMEZONE
from database import init_db, get_db
from auth import hash_password


# E-Mail-Adressen fuer bestehende Nutzer
USER_EMAILS = {
    "rac00n": os.environ.get("RACOON_EMAIL", "momohomma@googlemail.com"),
    "ch33tah": os.environ.get("CHEETAH_EMAIL", "hendrik_gebhardt@gmx.de"),
}


async def migrate():
    """Fuehrt die Multi-Tenancy-Migration durch."""

    # 1. Backup erstellen
    if os.path.exists(DB_PATH):
        backup_path = DB_PATH + f".backup-{datetime.now().strftime('%Y%m%d_%H%M%S')}"
        shutil.copy2(DB_PATH, backup_path)
        print(f"Backup erstellt: {backup_path}")
    else:
        print("Keine bestehende Datenbank gefunden. Frische Installation.")

    # 2. Schema-Migration (init_db erstellt neue Tabellen und fuegt Spalten hinzu)
    await init_db()
    print("Schema-Migration abgeschlossen.")

    db = await get_db()
    try:
        # 3. Pruefen ob Migration bereits gelaufen ist
        cursor = await db.execute("SELECT COUNT(*) as cnt FROM organizations")
        org_count = (await cursor.fetchone())["cnt"]
        if org_count > 0:
            print("Migration wurde bereits durchgefuehrt. Abbruch.")
            return

        # 4. AegisSight-Organisation anlegen
        now = datetime.now(TIMEZONE).isoformat()
        cursor = await db.execute(
            """INSERT INTO organizations (name, slug, is_active, created_at, updated_at)
               VALUES (?, ?, 1, ?, ?)""",
            ("AegisSight", "aegissight", now, now),
        )
        aegis_org_id = cursor.lastrowid
        print(f"Organisation AegisSight angelegt (ID: {aegis_org_id})")

        # 5. Permanente Lizenz fuer AegisSight
        await db.execute(
            """INSERT INTO licenses (organization_id, license_type, max_users, valid_from, valid_until, status, notes)
               VALUES (?, 'permanent', 50, ?, NULL, 'active', 'Interne AegisSight-Lizenz')""",
            (aegis_org_id, now),
        )
        print("Permanente Lizenz fuer AegisSight erstellt")

        # 6. Bestehende Nutzer der AegisSight-Org zuweisen
        cursor = await db.execute("SELECT id, username FROM users")
        users = await cursor.fetchall()

        for user in users:
            username = user["username"]
            email = USER_EMAILS.get(username, f"{username}@aegis-sight.de")

            await db.execute(
                """UPDATE users SET
                   organization_id = ?,
                   role = 'org_admin',
                   is_active = 1,
                   email = ?
                   WHERE id = ?""",
                (aegis_org_id, email, user["id"]),
            )
            print(f"Nutzer '{username}' -> AegisSight (org_admin, email: {email})")

        # 7. tenant_id auf alle bestehenden Incidents setzen
        await db.execute(
            "UPDATE incidents SET tenant_id = ? WHERE tenant_id IS NULL",
            (aegis_org_id,),
        )
        cursor = await db.execute("SELECT changes()")
        changes = (await cursor.fetchone())[0]
        print(f"{changes} Incidents mit tenant_id versehen")

        # 8. tenant_id auf alle bestehenden Articles setzen
        await db.execute(
            "UPDATE articles SET tenant_id = ? WHERE tenant_id IS NULL",
            (aegis_org_id,),
        )
        cursor = await db.execute("SELECT changes()")
        changes = (await cursor.fetchone())[0]
        print(f"{changes} Articles mit tenant_id versehen")

        # 9. tenant_id auf alle bestehenden fact_checks setzen
        await db.execute(
            "UPDATE fact_checks SET tenant_id = ? WHERE tenant_id IS NULL",
            (aegis_org_id,),
        )

        # 10. tenant_id auf alle bestehenden refresh_log setzen
        await db.execute(
            "UPDATE refresh_log SET tenant_id = ? WHERE tenant_id IS NULL",
            (aegis_org_id,),
        )

        # 11. tenant_id auf alle bestehenden incident_snapshots setzen
        await db.execute(
            "UPDATE incident_snapshots SET tenant_id = ? WHERE tenant_id IS NULL",
            (aegis_org_id,),
        )

        # 12. tenant_id auf alle bestehenden notifications setzen
        await db.execute(
            "UPDATE notifications SET tenant_id = ? WHERE tenant_id IS NULL",
            (aegis_org_id,),
        )

        # 13. System-Quellen bleiben global (tenant_id=NULL)
        # Nur nutzer-erstellte Quellen bekommen tenant_id
        await db.execute(
            "UPDATE sources SET tenant_id = ? WHERE added_by != 'system' AND tenant_id IS NULL",
            (aegis_org_id,),
        )
        print("Nutzer-Quellen mit tenant_id versehen (System-Quellen bleiben global)")

        # 14. Portal-Admin-Zugaenge anlegen
        print("\n--- Portal-Admin-Zugaenge ---")
        portal_users = ["rac00n", "ch33tah"]
        for pu in portal_users:
            # Pruefen ob schon existiert
            cursor = await db.execute(
                "SELECT id FROM portal_admins WHERE username = ?", (pu,)
            )
            if await cursor.fetchone():
                print(f"Portal-Admin '{pu}' existiert bereits")
                continue

            # Passwort generieren
            import secrets
            import string
            password = ''.join(secrets.choice(string.ascii_letters + string.digits + "!@#$%&*") for _ in range(16))
            pw_hash = hash_password(password)

            await db.execute(
                "INSERT INTO portal_admins (username, password_hash) VALUES (?, ?)",
                (pu, pw_hash),
            )
            print(f"Portal-Admin '{pu}' erstellt - Passwort: {password}")

        await db.commit()
        print("\nMigration erfolgreich abgeschlossen!")

    except Exception as e:
        print(f"\nFEHLER bei Migration: {e}")
        raise
    finally:
        await db.close()


if __name__ == "__main__":
    asyncio.run(migrate())
