import sqlite3
from dataclasses import dataclass
import hashlib
from typing import Optional

@dataclass
class DocumentsCustomModel:
    id: Optional[int] = None
    user_id: Optional[int] = None
    name: Optional[str] = None
    path: Optional[str] = None
    created_at: Optional[str] = None
    access: Optional[str] = None


class DocumentsCustom:
    def __init__(self, db_path="instance/app_database.db"):
        self.db_path = db_path
        self._create_audit_table()

    def _create_audit_table(self):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute(
                """
                CREATE TABLE IF NOT EXISTS documents_custom (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    user_id INTEGER NOT NULL,
                    name TEXT,
                    path TEXT,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                    access TEXT
                );
                """
            )
            conn.commit()

    def new_entry(self, entry:DocumentsCustomModel):
        """Create a new entry."""
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute(
                    """
                    INSERT INTO documents_custom (user_id, name, path, access)
                    VALUES (?, ?, ?, ?)
                    """,
                    (entry.user_id, entry.name, entry.path, entry.access),
                )
                conn.commit()
                return cursor.lastrowid
        except sqlite3.IntegrityError:
            return None
        
    def get_all_entries(self):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM documents_custom")
            rows = cursor.fetchall()

            return [
                DocumentsCustomModel(
                    id = row[0],
                    user_id =  row[1],
                    name = row[2],
                    path = row[3],
                    created_at = row[4],
                    access = row[5]
                )
                for row in rows
            ]
        
    def get_entries_by_user_id(self, user_id):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM documents_custom WHERE user_id = ?", (user_id, ))
            rows = cursor.fetchall()

            return [
                DocumentsCustomModel(
                    id = row[0],
                    user_id =  row[1],
                    name = row[2],
                    path = row[3],
                    created_at = row[4],
                    access = row[5]
                )
                for row in rows
            ]
        
    def get_entry_by_id(self, id):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM documents_custom WHERE id = ?", (id, ))
            row = cursor.fetchone()
            if row:
                return DocumentsCustomModel(
                    id = row[0],
                    user_id =  row[1],
                    name = row[2],
                    path = row[3],
                    created_at = row[4],
                    access = row[5]
                )
            return None

    def delete_entry(self, id):
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                # SQLite allows direct string comparison for ISO 8601 dates
                cursor.execute(
                    "DELETE FROM documents_custom WHERE id = ? ",
                    (id,)
                )
                conn.commit()
                return cursor.rowcount  # Returns the number of deleted rows
        except sqlite3.Error as e:
            print(f"An error occurred: {e}")
            return 0

@dataclass
class CustomDocumentRequestModel:
    id: Optional[int] = None
    client_id: Optional[int] = None
    request_text: Optional[str] = None
    status: Optional[str] = "new"
    price: Optional[float] = 0.0
    expert_id: Optional[int] = None
    document_id: Optional[int] = None
    created_at: Optional[str] = None

class CustomDocumentRequests:
    def __init__(self, db_path="instance/app_database.db"):
        self.db_path = db_path
        self._create_table()

    def _create_table(self):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute(
                """
                CREATE TABLE IF NOT EXISTS custom_document_requests (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    client_id INTEGER NOT NULL,
                    request_text TEXT,
                    status TEXT DEFAULT 'new',
                    price REAL DEFAULT 0.0,
                    expert_id INTEGER,
                    document_id INTEGER,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                );
                """
            )
            conn.commit()

    def new_entry(self, entry: CustomDocumentRequestModel):
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute(
                    """
                    INSERT INTO custom_document_requests (client_id, request_text, status, price, expert_id, document_id)
                    VALUES (?, ?, ?, ?, ?, ?)
                    """,
                    (entry.client_id, entry.request_text, entry.status, entry.price, entry.expert_id, entry.document_id),
                )
                conn.commit()
                return cursor.lastrowid
        except sqlite3.Error as e:
            print(f"Database error: {e}")
            return None

    def get_all_entries(self):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM custom_document_requests")
            rows = cursor.fetchall()
            return [
                CustomDocumentRequestModel(
                    id=row[0],
                    client_id=row[1],
                    request_text=row[2],
                    status=row[3],
                    price=row[4],
                    expert_id=row[5],
                    document_id=row[6],
                    created_at=row[7]
                ) for row in rows]

    def get_entry_by_id(self, id):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM custom_document_requests WHERE id = ?", (id,))
            row = cursor.fetchone()
            if row:
                return CustomDocumentRequestModel(
                    id=row[0],
                    client_id=row[1],
                    request_text=row[2],
                    status=row[3],
                    price=row[4],
                    expert_id=row[5],
                    document_id=row[6],
                    created_at=row[7]
                )
            return None

    def get_entries_by_client_id(self, client_id):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM custom_document_requests WHERE client_id = ?", (client_id,))
            rows = cursor.fetchall()
            return [
                CustomDocumentRequestModel(
                    id=row[0],
                    client_id=row[1],
                    request_text=row[2],
                    status=row[3],
                    price=row[4],
                    expert_id=row[5],
                    document_id=row[6],
                    created_at=row[7]
                ) for row in rows]

    def get_entries_by_expert_id(self, expert_id):
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM custom_document_requests WHERE expert_id = ? ORDER BY id DESC", (expert_id,))
            rows = cursor.fetchall()
            return [
                CustomDocumentRequestModel(
                    id=row[0],
                    client_id=row[1],
                    request_text=row[2],
                    status=row[3],
                    price=row[4],
                    expert_id=row[5],
                    document_id=row[6],
                    created_at=row[7]
                ) for row in rows]

    def update_entry(self, id, status=None, price=None, expert_id=None, document_id=None, request_text=None):
        if status is None and price is None and expert_id is None and document_id is None and request_text is None:
            return False

        # Fetch existing entry to preserve unchanged values if not provided
        existing_entry = self.get_entry_by_id(id)
        if not existing_entry:
            return False

        # Use existing values if new ones are not provided
        status = status if status is not None else existing_entry.status
        price = price if price is not None else existing_entry.price
        expert_id = expert_id if expert_id is not None else existing_entry.expert_id
        document_id = document_id if document_id is not None else existing_entry.document_id
        request_text = request_text if request_text is not None else existing_entry.request_text

        fields = []
        params = []

        if request_text is not None:
            fields.append("request_text = ?")
            params.append(request_text)
        if status is not None:
            fields.append("status = ?")
            params.append(status)
        if price is not None:
            fields.append("price = ?")
            params.append(price)
        if expert_id is not None:
            fields.append("expert_id = ?")
            params.append(expert_id)
        if document_id is not None:
            fields.append("document_id = ?")
            params.append(document_id)

        params.append(id)
        query = f"UPDATE custom_document_requests SET {', '.join(fields)} WHERE id = ?"

        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute(query, tuple(params))
                conn.commit()
                return cursor.rowcount > 0
        except sqlite3.Error as e:
            print(f"An error occurred during update: {e}")
            return False

    def delete_entry(self, id):
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "DELETE FROM custom_document_requests WHERE id = ?",
                    (id,)
                )
                conn.commit()
                return cursor.rowcount
        except sqlite3.Error as e:
            print(f"An error occurred during delete: {e}")
            return 0