import sqlite3
import logging
import os
from dotenv import dotenv_values

logger = logging.getLogger(__name__)

DB_DIR = "app_database"
DB_FILE = os.path.join(DB_DIR, "factum.db")

class DBService:
    def __init__(self):
        logging.debug("Initializing DBService")
        self.conn = self.connect_db()
        self.initialize_schema()
        
    def connect_db(self):
        logging.debug(f"Trying to connect to database at {DB_FILE}")
        if not os.path.exists(DB_DIR):
            logging.debug(f"Database directory {DB_DIR} does not exist, creating...")
            os.makedirs(DB_DIR, exist_ok=True)
        try:
            conn = sqlite3.connect(DB_FILE)
            logging.info("Database connection established.")
            return conn
        except sqlite3.Error as e:
            logging.error(f"Database connection failed: {e}")
            raise
        
    def initialize_schema(self):
        try:
            with self.conn:
                cursor = self.conn.cursor()
                cursor.executescript("""
                    CREATE TABLE IF NOT EXISTS cases(
                        id INTEGER PRIMARY KEY, 
                        case_file TEXT, 
                        case_name_pretty TEXT,
                        case_description TEXT,
                        creation_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
                    );
                    CREATE TABLE IF NOT EXISTS evidence(
                        id INTEGER PRIMARY KEY, 
                        parent_case_id INTEGER,
                        evid_descr TEXT,
                        evidence_hash TEXT,
                        creation_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                        FOREIGN KEY(parent_case_id) REFERENCES cases(id)
                    );
                    CREATE TABLE IF NOT EXISTS notes(
                        id INTEGER PRIMARY KEY, 
                        note_text TEXT,
                        creation_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                        note_hash TEXT,
                        note_hash_sig TEXT,
                        parent_evidence_id INTEGER,
                        parent_case_id INTEGER,
                        FOREIGN KEY(parent_evidence_id) REFERENCES evidence(id),
                        FOREIGN KEY(parent_case_id) REFERENCES cases(id)
                    );
                    CREATE TABLE IF NOT EXISTS ioc(
                        id INTEGER PRIMARY KEY, 
                        ioc_type TEXT CHECK(ioc_type IN ('ip', 'domain', 'url', 'hash')),
                        ioc_value TEXT
                    );
                    CREATE TABLE IF NOT EXISTS note_ioc_map(
                        note_id INTEGER,
                        ioc_id INTEGER,
                        PRIMARY KEY(note_id, ioc_id),
                        FOREIGN KEY(note_id) REFERENCES notes(id),
                        FOREIGN KEY(ioc_id) REFERENCES ioc(id)
                    );
                    CREATE TABLE IF NOT EXISTS tags(
                        id INTEGER PRIMARY KEY, 
                        tag_text TEXT
                    );
                    CREATE TABLE IF NOT EXISTS note_tag_map(
                        note_id INTEGER,
                        tag_id INTEGER,
                        PRIMARY KEY(note_id, tag_id),
                        FOREIGN KEY(note_id) REFERENCES notes(id),
                        FOREIGN KEY(tag_id) REFERENCES tags(id)
                    );
                    CREATE TABLE IF NOT EXISTS settings(
                        id INTEGER PRIMARY KEY, 
                        setting_key TEXT UNIQUE,
                        setting_value TEXT
                    );
                    """)
                logging.info("Database schema initialized.")
        except sqlite3.Error as e:
            logging.error(f"Failed to initialize database schema: {e}")
            raise