#!/usr/bin/env python3
"""Initialisiert die SQLite-Datenbank für TESM.

WICHTIG: Wer hier eine neue Tabelle oder Spalte hinzufügt, muss auch die
Datei SCHEMA_VERSION (daneben, im selben Verzeichnis) um 1 erhöhen.
update.sh vergleicht diese Zahl zwischen der aktuell installierten und der
neuen Version, um zu entscheiden, ob ein Update in-place laufen darf
(bestehende Datenbank bleibt erhalten) oder eine frische Installation
nötig ist (Datenbank wird beiseitegesichert). Ein vergessenes Hochzählen
würde dazu führen, dass ein Host mit altem Schema faelschlich per
In-Place-Update aktualisiert wird, statt frisch installiert zu werden --
_ensure_schema() faengt die meisten Faelle zwar zur Laufzeit ab, ist aber
kein Ersatz fuer eine korrekte Versionsnummer hier."""
import os
import sqlite3

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.environ.get("TESM_DB_PATH", os.path.join(BASE_DIR, "sqlite.db"))

conn = sqlite3.connect(DB_PATH)
c = conn.cursor()

c.execute("""
CREATE TABLE IF NOT EXISTS credentials (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT UNIQUE NOT NULL,
    username TEXT NOT NULL,
    password TEXT NOT NULL,
    category TEXT NOT NULL DEFAULT 'switch',
    deleted_at TEXT
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS switches (
    hostname TEXT PRIMARY KEY,
    ip TEXT NOT NULL,
    ssh_port INTEGER,
    credential_id INTEGER,
    last_modified_by TEXT,
    last_modified_at TEXT,
    deleted_at TEXT,
    FOREIGN KEY (credential_id) REFERENCES credentials(id)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS devices (
    mac TEXT PRIMARY KEY,
    ip TEXT NOT NULL,
    switch_hostname TEXT,
    port TEXT,
    name TEXT NOT NULL,
    is_active INTEGER DEFAULT 1,
    last_modified_by TEXT,
    last_modified_at TEXT,
    credential_id INTEGER,
    ssh_port INTEGER,
    deleted_at TEXT,
    FOREIGN KEY (switch_hostname) REFERENCES switches(hostname)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    password TEXT NOT NULL,
    is_admin INTEGER DEFAULT 0,
    first_name TEXT,
    last_name TEXT,
    avatar_filename TEXT,
    auth_source TEXT NOT NULL DEFAULT 'local',
    email TEXT,
    is_locked INTEGER NOT NULL DEFAULT 0,
    deleted_at TEXT
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS groups (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT UNIQUE NOT NULL,
    is_default INTEGER DEFAULT 0,
    is_system INTEGER DEFAULT 0,
    deleted_at TEXT
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS group_permissions (
    group_id INTEGER NOT NULL,
    permission TEXT NOT NULL,
    PRIMARY KEY (group_id, permission),
    FOREIGN KEY (group_id) REFERENCES groups(id)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS user_groups (
    user_id INTEGER NOT NULL,
    group_id INTEGER NOT NULL,
    PRIMARY KEY (user_id, group_id),
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (group_id) REFERENCES groups(id)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS settings (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS dhcp_option_defs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    code INTEGER NOT NULL UNIQUE,
    name TEXT NOT NULL UNIQUE,
    type TEXT NOT NULL,
    description TEXT,
    is_standard INTEGER NOT NULL DEFAULT 0
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS dhcp_option_values (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    option_def_id INTEGER NOT NULL,
    device_mac TEXT NOT NULL DEFAULT '',
    value TEXT NOT NULL,
    FOREIGN KEY (option_def_id) REFERENCES dhcp_option_defs(id),
    UNIQUE (option_def_id, device_mac)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS dhcp_subnets (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    interface TEXT NOT NULL,
    range_start TEXT NOT NULL,
    range_end TEXT NOT NULL,
    gateway TEXT,
    dns TEXT,
    sort_order INTEGER NOT NULL DEFAULT 0,
    enabled INTEGER NOT NULL DEFAULT 1
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS dhcp_manual_reservations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mac TEXT NOT NULL UNIQUE,
    ip TEXT NOT NULL,
    name TEXT NOT NULL
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS service_accounts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    purpose TEXT UNIQUE NOT NULL,
    username TEXT NOT NULL,
    password TEXT NOT NULL
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS ldap_group_mappings (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ad_group_dn TEXT UNIQUE NOT NULL,
    ad_group_name TEXT NOT NULL,
    app_group_id INTEGER NOT NULL,
    FOREIGN KEY (app_group_id) REFERENCES groups(id)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS ldap_fileshare_mappings (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ad_group_dn TEXT NOT NULL,
    ad_group_name TEXT NOT NULL,
    share_label TEXT NOT NULL,
    share_unc TEXT NOT NULL,
    UNIQUE(ad_group_dn, share_unc)
);
""")

c.execute("""
CREATE TABLE IF NOT EXISTS audit_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ts TEXT NOT NULL,
    username TEXT NOT NULL,
    action TEXT NOT NULL,
    target TEXT,
    details TEXT
);
""")

c.execute("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", ("interval", "5"))
c.execute("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", ("check_interval", "300"))

cur = c.execute("INSERT OR IGNORE INTO groups (name, is_default, is_system) VALUES (?, 1, 1)", ("Benutzer",))
if cur.rowcount > 0:
    default_group_id = cur.lastrowid
    c.executemany(
        "INSERT OR IGNORE INTO group_permissions (group_id, permission) VALUES (?, ?)",
        [
            (default_group_id, "devices_group.view"),
            (default_group_id, "devices.view"),
            (default_group_id, "switches.view"),
            (default_group_id, "logs_group.view"),
            (default_group_id, "logs_live.view"),
        ],
    )

conn.commit()
conn.close()
print(f"Datenbank '{DB_PATH}' wurde initialisiert inklusive Settings.")
