"""SQLite database management for Chatixia."""

from __future__ import annotations

import sqlite3
import threading
from pathlib import Path

from logging_config import get_logger

log = get_logger(__name__)

_SCHEMA = """
CREATE TABLE IF NOT EXISTS sessions (
    id          TEXT PRIMARY KEY,
    title       TEXT NOT NULL DEFAULT '',
    created_at  TEXT NOT NULL,
    updated_at  TEXT NOT NULL,
    messages    TEXT NOT NULL,
    metadata    TEXT NOT NULL DEFAULT '{}'
);

CREATE TABLE IF NOT EXISTS memories (
    id              TEXT PRIMARY KEY,
    content         TEXT NOT NULL,
    created_at      TEXT NOT NULL,
    source_session  TEXT NOT NULL,
    tags            TEXT NOT NULL DEFAULT '[]'
);

CREATE TABLE IF NOT EXISTS system_prompts (
    id          TEXT PRIMARY KEY,
    name        TEXT NOT NULL UNIQUE,
    content     TEXT NOT NULL,
    created_at  TEXT NOT NULL,
    updated_at  TEXT NOT NULL,
    is_active   INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS agent_logs (
    id              TEXT PRIMARY KEY,
    session_id      TEXT,
    timestamp       TEXT NOT NULL,
    event_type      TEXT NOT NULL,
    duration_ms     INTEGER,
    tokens_input    INTEGER,
    tokens_output   INTEGER,
    tokens_total    INTEGER,
    tool_name       TEXT,
    tool_args       TEXT,
    response_preview TEXT,
    error           TEXT,
    metadata        TEXT NOT NULL DEFAULT '{}'
);

CREATE INDEX IF NOT EXISTS idx_agent_logs_session ON agent_logs(session_id);
CREATE INDEX IF NOT EXISTS idx_agent_logs_timestamp ON agent_logs(timestamp);
CREATE INDEX IF NOT EXISTS idx_agent_logs_event_type ON agent_logs(event_type);

CREATE TABLE IF NOT EXISTS workflows (
    id            TEXT PRIMARY KEY,
    name          TEXT NOT NULL,
    summary       TEXT NOT NULL DEFAULT '',
    session_id    TEXT NOT NULL,
    workflow_json TEXT NOT NULL,
    created_at    TEXT NOT NULL,
    updated_at    TEXT NOT NULL,
    metadata      TEXT NOT NULL DEFAULT '{}'
);

CREATE INDEX IF NOT EXISTS idx_workflows_created_at ON workflows(created_at);
CREATE INDEX IF NOT EXISTS idx_workflows_session_id ON workflows(session_id);

CREATE TABLE IF NOT EXISTS knowledge_items (
    id              TEXT PRIMARY KEY,
    title           TEXT NOT NULL,
    source_type     TEXT NOT NULL,
    source_url      TEXT,
    source_filename TEXT,
    file_path       TEXT,
    raw_text        TEXT NOT NULL DEFAULT '',
    summary         TEXT NOT NULL DEFAULT '',
    key_points      TEXT NOT NULL DEFAULT '[]',
    tags            TEXT NOT NULL DEFAULT '[]',
    status          TEXT NOT NULL DEFAULT 'pending',
    error_message   TEXT,
    char_count      INTEGER NOT NULL DEFAULT 0,
    created_at      TEXT NOT NULL,
    updated_at      TEXT NOT NULL,
    metadata        TEXT NOT NULL DEFAULT '{}'
);

CREATE INDEX IF NOT EXISTS idx_knowledge_status ON knowledge_items(status);
CREATE INDEX IF NOT EXISTS idx_knowledge_created_at ON knowledge_items(created_at);
CREATE INDEX IF NOT EXISTS idx_knowledge_source_type ON knowledge_items(source_type);

CREATE TABLE IF NOT EXISTS knowledge_connections (
    id          TEXT PRIMARY KEY,
    source_id   TEXT NOT NULL,
    target_id   TEXT NOT NULL,
    label       TEXT NOT NULL DEFAULT '',
    strength    REAL NOT NULL DEFAULT 0.5,
    created_at  TEXT NOT NULL,
    FOREIGN KEY (source_id) REFERENCES knowledge_items(id) ON DELETE CASCADE,
    FOREIGN KEY (target_id) REFERENCES knowledge_items(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_kconn_source ON knowledge_connections(source_id);
CREATE INDEX IF NOT EXISTS idx_kconn_target ON knowledge_connections(target_id);

CREATE TABLE IF NOT EXISTS knowledge_entities (
    id              TEXT PRIMARY KEY,
    item_id         TEXT NOT NULL,
    entity_type     TEXT NOT NULL,
    name            TEXT NOT NULL,
    description     TEXT NOT NULL DEFAULT '',
    properties      TEXT NOT NULL DEFAULT '{}',
    created_at      TEXT NOT NULL,
    FOREIGN KEY (item_id) REFERENCES knowledge_items(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_kent_item_id ON knowledge_entities(item_id);
CREATE INDEX IF NOT EXISTS idx_kent_type ON knowledge_entities(entity_type);
CREATE INDEX IF NOT EXISTS idx_kent_name ON knowledge_entities(name);

CREATE TABLE IF NOT EXISTS knowledge_entity_connections (
    id          TEXT PRIMARY KEY,
    source_id   TEXT NOT NULL,
    target_id   TEXT NOT NULL,
    label       TEXT NOT NULL DEFAULT '',
    strength    REAL NOT NULL DEFAULT 0.5,
    created_at  TEXT NOT NULL,
    FOREIGN KEY (source_id) REFERENCES knowledge_entities(id) ON DELETE CASCADE,
    FOREIGN KEY (target_id) REFERENCES knowledge_entities(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_kec_source ON knowledge_entity_connections(source_id);
CREATE INDEX IF NOT EXISTS idx_kec_target ON knowledge_entity_connections(target_id);

CREATE TABLE IF NOT EXISTS goals (
    id              TEXT PRIMARY KEY,
    name            TEXT NOT NULL,
    description     TEXT NOT NULL,
    enabled         INTEGER NOT NULL DEFAULT 1,
    check_interval  INTEGER NOT NULL DEFAULT 300,
    sensor_prompt   TEXT NOT NULL,
    action_prompt   TEXT NOT NULL DEFAULT '',
    autonomy_level  TEXT NOT NULL DEFAULT 'auto',
    skills_allowed  TEXT NOT NULL DEFAULT '[]',
    last_run_at     TEXT,
    created_at      TEXT NOT NULL,
    updated_at      TEXT NOT NULL,
    metadata        TEXT NOT NULL DEFAULT '{}'
);

CREATE INDEX IF NOT EXISTS idx_goals_enabled ON goals(enabled);

CREATE TABLE IF NOT EXISTS goal_runs (
    id          TEXT PRIMARY KEY,
    goal_id     TEXT NOT NULL,
    started_at  TEXT NOT NULL,
    finished_at TEXT,
    status      TEXT NOT NULL DEFAULT 'running',
    observation TEXT,
    decision    TEXT,
    result      TEXT,
    session_id  TEXT,
    metadata    TEXT NOT NULL DEFAULT '{}',
    FOREIGN KEY (goal_id) REFERENCES goals(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_goal_runs_goal_id ON goal_runs(goal_id);
CREATE INDEX IF NOT EXISTS idx_goal_runs_started_at ON goal_runs(started_at);
"""


class Database:
    """Thin wrapper around a SQLite connection with automatic schema init."""

    def __init__(self, db_path: str | Path = ".chatixia/db/chatixia.db") -> None:
        self.path = Path(db_path)
        self.path.parent.mkdir(parents=True, exist_ok=True)

        self.lock = threading.Lock()
        self.conn = sqlite3.connect(str(self.path), check_same_thread=False)
        self.conn.row_factory = sqlite3.Row
        self.conn.execute("PRAGMA journal_mode=WAL")
        self.conn.execute("PRAGMA foreign_keys=ON")
        self._init_schema()

        log.debug("database_ready", path=str(self.path))

    def _init_schema(self) -> None:
        """Create tables if they don't exist."""
        self.conn.executescript(_SCHEMA)
        self.conn.commit()

    def close(self) -> None:
        """Close the database connection."""
        self.conn.close()
