"""
audit.py

Purpose:
  Centralized audit logging for authentication events and administrative
  actions. This module provides small, focused helpers to record security-
  relevant events into the SQLite database, so operators have traceability for
  incident response.

How it works:
  - Lazily ensures minimal schemas for two tables: `auth_log` and
    `admin_audit`.
  - Exposes `log_auth_event(...)` and `log_admin_action(...)` with simple
    parameters to record events. Timestamps are stored as UNIX epoch seconds.
  - Keeps the code path lightweight; failures to log never break requests.

Data model:
  - auth_log(id, ts, ip, user_id, username, event, detail)
  - admin_audit(id, ts, ip, admin_user_id, target_user_id, action, detail)
"""

from __future__ import annotations

import time
from typing import Optional

from .db import get_db


def _now() -> int:
    return int(time.time())


def _ensure_schema() -> None:
    db = get_db()
    db.execute(
        """
        CREATE TABLE IF NOT EXISTS auth_log (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ts INTEGER NOT NULL,
            ip TEXT,
            user_id INTEGER,
            username TEXT,
            event TEXT NOT NULL,
            detail TEXT
        )
        """
    )
    db.execute(
        """
        CREATE TABLE IF NOT EXISTS admin_audit (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            ts INTEGER NOT NULL,
            ip TEXT,
            admin_user_id INTEGER NOT NULL,
            target_user_id INTEGER,
            action TEXT NOT NULL,
            detail TEXT
        )
        """
    )
    db.commit()


def log_auth_event(event: str, *, username: Optional[str] = None, user_id: Optional[int] = None,
                   ip: Optional[str] = None, detail: Optional[str] = None) -> None:
    try:
        _ensure_schema()
        db = get_db()
        db.execute(
            'INSERT INTO auth_log (ts, ip, user_id, username, event, detail) VALUES (?, ?, ?, ?, ?, ?)',
            (_now(), ip, user_id, username, event, detail),
        )
        db.commit()
    except Exception:
        # Auditing must be best-effort only; never break requests
        pass


def log_admin_action(action: str, *, admin_user_id: int, target_user_id: Optional[int] = None,
                     ip: Optional[str] = None, detail: Optional[str] = None) -> None:
    try:
        _ensure_schema()
        db = get_db()
        db.execute(
            'INSERT INTO admin_audit (ts, ip, admin_user_id, target_user_id, action, detail) VALUES (?, ?, ?, ?, ?, ?)',
            (_now(), ip, admin_user_id, target_user_id, action, detail),
        )
        db.commit()
    except Exception:
        pass


def get_request_ip(request) -> Optional[str]:
    try:
        fwd = (request.headers.get('X-Forwarded-For') or '').split(',')[0].strip()
        return fwd or request.remote_addr
    except Exception:
        return None


