#include "databasemanager.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QStandardPaths>
#include <QDir>

DatabaseManager& DatabaseManager::instance()
{
    static DatabaseManager instance;
    return instance;
}

DatabaseManager::DatabaseManager() = default;

DatabaseManager::~DatabaseManager()
{
    if (m_db.isOpen()) {
        m_db.close();
    }
}

bool DatabaseManager::initialize(const QString& databasePath)
{
    QMutexLocker locker(&m_mutex);
    if (m_initialized) {
        return true;
    }

    QString dbPath = databasePath;
    if (dbPath.isEmpty()) {
        // Use application data location
        QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
        if (!dir.exists()) {
            dir.mkpath(".");
        }
        dbPath = dir.filePath("wino-mail.sqlite");
    }

    m_db = QSqlDatabase::addDatabase("QSQLITE", "wino_mail_connection");
    m_db.setDatabaseName(dbPath);

    if (!m_db.open()) {
        qWarning() << "Failed to open database:" << m_db.lastError().text();
        return false;
    }

    QSqlQuery query(m_db);
    // Enable foreign keys
    query.exec("PRAGMA foreign_keys = ON;");

    // Create tables if they don't exist

    // Account table
    if (!query.exec(
        "CREATE TABLE IF NOT EXISTS Account ("
        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
        "email TEXT NOT NULL, "
        "displayName TEXT, signature TEXT, "
        "type INTEGER NOT NULL, " // 0=Outlook,1=Gmail,2=IMAP
        "accessToken TEXT, "
        "refreshToken TEXT, "
        "tokenExpires DATETIME, "
        "incomingHost TEXT, "
        "incomingPort INTEGER, "
        "incomingSsl INTEGER, "
        "outgoingHost TEXT, "
        "outgoingPort INTEGER, "
        "outgoingSsl INTEGER, "
        "connUsername TEXT, "
        "connPassword TEXT, "
        "authMethod TEXT"
        ");")) {
        qWarning() << "Failed to create Account table:" << query.lastError().text();
        return false;
    }

    // Folder table
    if (!query.exec(
        "CREATE TABLE IF NOT EXISTS Folder ("
        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
        "accountId INTEGER NOT NULL, "
        "name TEXT NOT NULL, "
        "parentFolderId TEXT, "
        "isInbox BOOLEAN DEFAULT 0, "
        "isSent BOOLEAN DEFAULT 0, "
        "isDrafts BOOLEAN DEFAULT 0, "
        "isTrash BOOLEAN DEFAULT 0, "
        "unreadCount INTEGER DEFAULT 0, "
        "lastSynced DATETIME, "
        "FOREIGN KEY(accountId) REFERENCES Account(id) ON DELETE CASCADE"
        ");")) {
        qWarning() << "Failed to create Folder table:" << query.lastError().text();
        return false;
    }

    // MailCopy table (simplified)
    if (!query.exec(
        "CREATE TABLE IF NOT EXISTS MailCopy ("
        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
        "folderId INTEGER NOT NULL, "
        "messageId TEXT UNIQUE, "
        "subject TEXT, "
        "sender TEXT, "
        "recipient TEXT, "
        "date DATETIME, "
        "read BOOLEAN DEFAULT 0, "
        "flagged BOOLEAN DEFAULT 0, "
        "hasAttachment BOOLEAN DEFAULT 0, "
        "size INTEGER, "
        "uid INTEGER, "
        "fileId TEXT, " // references the .eml file in storage
        "FOREIGN KEY(folderId) REFERENCES Folder(id) ON DELETE CASCADE"
        ");")) {
        qWarning() << "Failed to create MailCopy table:" << query.lastError().text();
        return false;
    }

    // Attachments table (optional)
    if (!query.exec(
        "CREATE TABLE IF NOT EXISTS Attachment ("
        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
        "mailCopyId INTEGER NOT NULL, "
        "filename TEXT, "
        "mimeType TEXT, "
        "size INTEGER, "
        "contentId TEXT, "
        "FOREIGN KEY(mailCopyId) REFERENCES MailCopy(id) ON DELETE CASCADE"
        ");")) {
        qWarning() << "Failed to create Attachment table:" << query.lastError().text();
        return false;
    }

    m_initialized = true;
    qDebug() << "Database initialized at:" << dbPath;
    return true;
}

QSqlDatabase& DatabaseManager::database()
{
    return m_db;
}