-- FIDO-Key Management System - Database Schema

-- ============================================================================
-- ROLES TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS roles (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(50) UNIQUE NOT NULL,
    description TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- ============================================================================
-- USERS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username VARCHAR(100) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255),
    role_id INTEGER NOT NULL,
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    is_active BOOLEAN DEFAULT 1,
    must_change_password BOOLEAN DEFAULT 1,
    email_notifications INTEGER NOT NULL DEFAULT 1,
    last_login DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (role_id) REFERENCES roles(id)
);

-- ============================================================================
-- FIDO KEYS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS fido_keys (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(255) NOT NULL,
    serial_number VARCHAR(255) UNIQUE NOT NULL,
    status VARCHAR(20) NOT NULL CHECK(status IN ('aktiv', 'inaktiv')),
    description TEXT,
    assigned_to_user_id INTEGER,
    created_by_user_id INTEGER NOT NULL,
    updated_by_user_id INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (assigned_to_user_id) REFERENCES users(id) ON DELETE SET NULL,
    FOREIGN KEY (created_by_user_id) REFERENCES users(id),
    FOREIGN KEY (updated_by_user_id) REFERENCES users(id)
);

-- ============================================================================
-- ASSETS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS assets (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(255) NOT NULL,
    type VARCHAR(50) NOT NULL CHECK(type IN ('Notebook', 'Monitor', 'Headset', 'Other')),
    serial_number VARCHAR(255) UNIQUE NOT NULL,
    model VARCHAR(255),
    status VARCHAR(20) NOT NULL CHECK(status IN ('verfuegbar', 'zugewiesen', 'inaktiv', 'beschaedigt')),
    purchase_date DATE,
    description TEXT,
    teamviewer_id TEXT,
    assigned_to_user_id INTEGER,
    created_by_user_id INTEGER NOT NULL,
    updated_by_user_id INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (assigned_to_user_id) REFERENCES users(id) ON DELETE SET NULL,
    FOREIGN KEY (created_by_user_id) REFERENCES users(id),
    FOREIGN KEY (updated_by_user_id) REFERENCES users(id)
);

-- ============================================================================
-- ASSET ASSIGNMENTS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS asset_assignments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    asset_id INTEGER NOT NULL,
    user_id INTEGER NOT NULL,
    assigned_by_user_id INTEGER NOT NULL,
    assigned_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    returned_at DATETIME,
    notes TEXT,
    onboarding_protocol_id INTEGER,
    offboarding_protocol_id INTEGER,
    FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (assigned_by_user_id) REFERENCES users(id)
);

-- ============================================================================
-- ONBOARDING PROTOCOLS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS onboarding_protocols (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    employee_user_id INTEGER NOT NULL,
    status VARCHAR(20) NOT NULL CHECK(status IN ('pending', 'in_progress', 'completed')),
    start_date DATE NOT NULL,
    completion_date DATE,
    checklist_data TEXT,
    notes TEXT,
    pdf_file_path VARCHAR(500),
    created_by_user_id INTEGER NOT NULL,
    updated_by_user_id INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (employee_user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (created_by_user_id) REFERENCES users(id),
    FOREIGN KEY (updated_by_user_id) REFERENCES users(id)
);

-- ============================================================================
-- OFFBOARDING PROTOCOLS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS offboarding_protocols (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    employee_user_id INTEGER NOT NULL,
    status VARCHAR(20) NOT NULL CHECK(status IN ('pending', 'in_progress', 'completed')),
    exit_date DATE NOT NULL,
    completion_date DATE,
    checklist_data TEXT,
    notes TEXT,
    pdf_file_path VARCHAR(500),
    created_by_user_id INTEGER NOT NULL,
    updated_by_user_id INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (employee_user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (created_by_user_id) REFERENCES users(id),
    FOREIGN KEY (updated_by_user_id) REFERENCES users(id)
);

-- ============================================================================
-- AUDIT LOG TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS audit_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    action VARCHAR(50) NOT NULL,
    entity_type VARCHAR(50) NOT NULL,
    entity_id INTEGER NOT NULL,
    old_value TEXT,
    new_value TEXT,
    ip_address VARCHAR(45),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- ============================================================================
-- INDEXES FOR PERFORMANCE
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_users_role_id ON users(role_id);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
CREATE INDEX IF NOT EXISTS idx_users_is_active ON users(is_active);

CREATE INDEX IF NOT EXISTS idx_fido_keys_serial ON fido_keys(serial_number);
CREATE INDEX IF NOT EXISTS idx_fido_keys_status ON fido_keys(status);
CREATE INDEX IF NOT EXISTS idx_fido_keys_assigned_to ON fido_keys(assigned_to_user_id);
CREATE INDEX IF NOT EXISTS idx_fido_keys_created_by ON fido_keys(created_by_user_id);

CREATE INDEX IF NOT EXISTS idx_assets_serial ON assets(serial_number);
CREATE INDEX IF NOT EXISTS idx_assets_type ON assets(type);
CREATE INDEX IF NOT EXISTS idx_assets_status ON assets(status);
CREATE INDEX IF NOT EXISTS idx_assets_assigned_to ON assets(assigned_to_user_id);

CREATE INDEX IF NOT EXISTS idx_asset_assignments_asset ON asset_assignments(asset_id);
CREATE INDEX IF NOT EXISTS idx_asset_assignments_user ON asset_assignments(user_id);
CREATE INDEX IF NOT EXISTS idx_asset_assignments_dates ON asset_assignments(assigned_at, returned_at);

CREATE INDEX IF NOT EXISTS idx_onboarding_employee ON onboarding_protocols(employee_user_id);
CREATE INDEX IF NOT EXISTS idx_onboarding_status ON onboarding_protocols(status);
CREATE INDEX IF NOT EXISTS idx_onboarding_dates ON onboarding_protocols(start_date, completion_date);

CREATE INDEX IF NOT EXISTS idx_offboarding_employee ON offboarding_protocols(employee_user_id);
CREATE INDEX IF NOT EXISTS idx_offboarding_status ON offboarding_protocols(status);
CREATE INDEX IF NOT EXISTS idx_offboarding_dates ON offboarding_protocols(exit_date, completion_date);

CREATE INDEX IF NOT EXISTS idx_audit_log_user_id ON audit_log(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_log_entity ON audit_log(entity_type, entity_id);
CREATE INDEX IF NOT EXISTS idx_audit_log_created_at ON audit_log(created_at);

-- ============================================================================
-- TICKETS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS tickets (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ticket_number TEXT UNIQUE NOT NULL,
    title TEXT NOT NULL,
    description TEXT,
    status VARCHAR(30) NOT NULL DEFAULT 'offen'
        CHECK(status IN ('offen','in_bearbeitung','warten_auf_mitarbeiter','warten_auf_support','geschlossen')),
    priority VARCHAR(20) NOT NULL DEFAULT 'mittel'
        CHECK(priority IN ('niedrig','mittel','hoch','kritisch')),
    category VARCHAR(50) NOT NULL DEFAULT 'Allgemein'
        CHECK(category IN ('Software','Allgemein','SelectLine','Hardware')),
    source VARCHAR(10) NOT NULL DEFAULT 'web'
        CHECK(source IN ('web','email')),
    requester_name TEXT,
    requester_email TEXT,
    assigned_to_user_id INTEGER,
    created_by_user_id INTEGER,
    asset_id INTEGER,
    email_message_id TEXT,
    resolved_at DATETIME,
    closed_at DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (assigned_to_user_id) REFERENCES users(id) ON DELETE SET NULL,
    FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL,
    FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE SET NULL
);

-- ============================================================================
-- TICKET COMMENTS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS ticket_comments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ticket_id INTEGER NOT NULL,
    user_id INTEGER,
    comment TEXT NOT NULL,
    is_internal INTEGER NOT NULL DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (ticket_id) REFERENCES tickets(id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);

-- ============================================================================
-- LICENSES TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS licenses (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    vendor TEXT,
    license_type TEXT NOT NULL DEFAULT 'subscription'
        CHECK(license_type IN ('subscription', 'oem', 'volume', 'perpetual')),
    product_key TEXT,
    seats INTEGER,
    purchase_date DATE,
    expiry_date DATE,
    cost REAL,
    notes TEXT,
    sku_id TEXT,
    created_by_user_id INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS idx_licenses_expiry ON licenses(expiry_date);
CREATE INDEX IF NOT EXISTS idx_licenses_type ON licenses(license_type);

-- ============================================================================
-- INDEXES FOR TICKETS
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
CREATE INDEX IF NOT EXISTS idx_tickets_priority ON tickets(priority);
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to_user_id);
CREATE INDEX IF NOT EXISTS idx_tickets_created_by ON tickets(created_by_user_id);
CREATE INDEX IF NOT EXISTS idx_tickets_asset ON tickets(asset_id);
CREATE INDEX IF NOT EXISTS idx_ticket_comments_ticket ON ticket_comments(ticket_id);

-- ============================================================================
-- MONITORING AGENTS TABLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS monitoring_agents (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    hostname VARCHAR(255) UNIQUE NOT NULL,
    ip_address VARCHAR(50),
    mac_address VARCHAR(100),
    os_name VARCHAR(255),
    os_version VARCHAR(255),
    cpu_model VARCHAR(255),
    cpu_cores INTEGER,
    cpu_usage_percent REAL,
    ram_total_gb REAL,
    ram_used_gb REAL,
    disk_total_gb REAL,
    disk_free_gb REAL,
    last_user VARCHAR(255),
    uptime_hours REAL,
    domain VARCHAR(255),
    agent_version VARCHAR(50),
    installed_software TEXT,
    windows_updates_pending INTEGER DEFAULT 0,
    status VARCHAR(20) DEFAULT 'online',
    last_checkin DATETIME DEFAULT CURRENT_TIMESTAMP,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_monitoring_agents_hostname ON monitoring_agents(hostname);
CREATE INDEX IF NOT EXISTS idx_monitoring_agents_status ON monitoring_agents(status);
CREATE INDEX IF NOT EXISTS idx_monitoring_agents_last_checkin ON monitoring_agents(last_checkin);


-- ============================================================================
-- NEXUS SCANNER TABLES
-- ============================================================================
CREATE TABLE IF NOT EXISTS scanner_sites (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id VARCHAR(10) NOT NULL UNIQUE,
    last_seen DATETIME,
    scanner_version VARCHAR(50),
    host_count INTEGER DEFAULT 0,
    check_count INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS scanner_assets (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id VARCHAR(10) NOT NULL,
    ip VARCHAR(50) NOT NULL,
    mac VARCHAR(100),
    hostname VARCHAR(255),
    vendor VARCHAR(255),
    status VARCHAR(20) DEFAULT 'online',
    first_seen DATETIME,
    last_seen DATETIME,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(site_id, ip)
);

CREATE TABLE IF NOT EXISTS scanner_alerts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id VARCHAR(10) NOT NULL,
    check_name VARCHAR(255) NOT NULL,
    check_type VARCHAR(50),
    target VARCHAR(255),
    status VARCHAR(20) NOT NULL,
    latency_ms INTEGER DEFAULT 0,
    error_msg TEXT,
    subject TEXT,
    triggered_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_scanner_assets_site ON scanner_assets(site_id);
CREATE INDEX IF NOT EXISTS idx_scanner_assets_status ON scanner_assets(status);
CREATE INDEX IF NOT EXISTS idx_scanner_alerts_site ON scanner_alerts(site_id, triggered_at DESC);
