#include "projectdao.h"

// --------------- Project CRUD ---------------

bool ProjectDAO::create(Project &proj)
{
    QSqlQuery query;
    query.prepare("INSERT INTO PROJECT (CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, "
                  "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, "
                  "POSTCODE, CITY, PHONE, MOBILE, EMAIL, CREATEDBY) "
                  "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
    query.addBindValue(proj.code);
    query.addBindValue(proj.title);
    query.addBindValue(proj.customerCode);
    query.addBindValue(proj.customerName);
    query.addBindValue(proj.startDate);
    query.addBindValue(proj.duration);
    query.addBindValue(proj.state);
    query.addBindValue(proj.contact);
    query.addBindValue(proj.address1);
    query.addBindValue(proj.address2);
    query.addBindValue(proj.postcode);
    query.addBindValue(proj.city);
    query.addBindValue(proj.phone);
    query.addBindValue(proj.mobile);
    query.addBindValue(proj.email);
    query.addBindValue("user");

    if (!query.exec()) {
        qWarning() << "ProjectDAO::create - Error:" << query.lastError().text();
        return false;
    }
    proj.id = query.lastInsertId().toInt();
    return true;
}

bool ProjectDAO::update(const Project &proj)
{
    QSqlQuery query;
    query.prepare("UPDATE PROJECT SET TITLE=?, CUSTOMER_CODE=?, CUSTOMER_NAME=?, "
                  "START_DATE=?, DURATION=?, STATE=?, CONTACT=?, ADDRESS1=?, ADDRESS2=?, "
                  "POSTCODE=?, CITY=?, PHONE=?, MOBILE=?, EMAIL=? WHERE CODE=?");
    query.addBindValue(proj.title);
    query.addBindValue(proj.customerCode);
    query.addBindValue(proj.customerName);
    query.addBindValue(proj.startDate);
    query.addBindValue(proj.duration);
    query.addBindValue(proj.state);
    query.addBindValue(proj.contact);
    query.addBindValue(proj.address1);
    query.addBindValue(proj.address2);
    query.addBindValue(proj.postcode);
    query.addBindValue(proj.city);
    query.addBindValue(proj.phone);
    query.addBindValue(proj.mobile);
    query.addBindValue(proj.email);
    query.addBindValue(proj.code);

    if (!query.exec()) {
        qWarning() << "ProjectDAO::update - Error:" << query.lastError().text();
        return false;
    }
    return query.numRowsAffected() > 0;
}

bool ProjectDAO::remove(const QString &code)
{
    QSqlQuery query;
    query.prepare("DELETE FROM PROJECT WHERE CODE = ?");
    query.addBindValue(code);
    if (!query.exec()) {
        qWarning() << "ProjectDAO::remove - Error:" << query.lastError().text();
        return false;
    }
    return true;
}

Project ProjectDAO::getByCode(const QString &code)
{
    Project proj;
    QSqlQuery query;
    query.prepare("SELECT ID, CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, "
                  "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, "
                  "POSTCODE, CITY, PHONE, MOBILE, EMAIL FROM PROJECT WHERE CODE = ?");
    query.addBindValue(code);
    if (query.exec() && query.next()) {
        proj.id = query.value(0).toInt();
        proj.code = query.value(1).toString();
        proj.title = query.value(2).toString();
        proj.customerCode = query.value(3).toString();
        proj.customerName = query.value(4).toString();
        proj.startDate = query.value(5).toDate();
        proj.duration = query.value(6).toDate();
        proj.state = query.value(7).toString();
        proj.contact = query.value(8).toString();
        proj.address1 = query.value(9).toString();
        proj.address2 = query.value(10).toString();
        proj.postcode = query.value(11).toString();
        proj.city = query.value(12).toString();
        proj.phone = query.value(13).toString();
        proj.mobile = query.value(14).toString();
        proj.email = query.value(15).toString();
    }
    return proj;
}

Project ProjectDAO::getById(int id)
{
    Project proj;
    QSqlQuery query;
    query.prepare("SELECT ID, CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, "
                  "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, "
                  "POSTCODE, CITY, PHONE, MOBILE, EMAIL FROM PROJECT WHERE ID = ?");
    query.addBindValue(id);
    if (query.exec() && query.next()) {
        proj.id = query.value(0).toInt();
        proj.code = query.value(1).toString();
        proj.title = query.value(2).toString();
        proj.customerCode = query.value(3).toString();
        proj.customerName = query.value(4).toString();
        proj.startDate = query.value(5).toDate();
        proj.duration = query.value(6).toDate();
        proj.state = query.value(7).toString();
        proj.contact = query.value(8).toString();
        proj.address1 = query.value(9).toString();
        proj.address2 = query.value(10).toString();
        proj.postcode = query.value(11).toString();
        proj.city = query.value(12).toString();
        proj.phone = query.value(13).toString();
        proj.mobile = query.value(14).toString();
        proj.email = query.value(15).toString();
    }
    return proj;
}

QVector<Project> ProjectDAO::getAll()
{
    QVector<Project> result;
    QSqlQuery query("SELECT ID, CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, "
                    "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, "
                    "POSTCODE, CITY, PHONE, MOBILE, EMAIL FROM PROJECT ORDER BY CODE");
    while (query.next()) {
        Project proj;
        proj.id = query.value(0).toInt();
        proj.code = query.value(1).toString();
        proj.title = query.value(2).toString();
        proj.customerCode = query.value(3).toString();
        proj.customerName = query.value(4).toString();
        proj.startDate = query.value(5).toDate();
        proj.duration = query.value(6).toDate();
        proj.state = query.value(7).toString();
        proj.contact = query.value(8).toString();
        proj.address1 = query.value(9).toString();
        proj.address2 = query.value(10).toString();
        proj.postcode = query.value(11).toString();
        proj.city = query.value(12).toString();
        proj.phone = query.value(13).toString();
        proj.mobile = query.value(14).toString();
        proj.email = query.value(15).toString();
        result.append(proj);
    }
    return result;
}

QStringList ProjectDAO::getAllCodes()
{
    QStringList codes;
    QSqlQuery query("SELECT CODE FROM PROJECT ORDER BY CODE");
    while (query.next())
        codes.append(query.value(0).toString());
    return codes;
}

bool ProjectDAO::exists(const QString &code)
{
    QSqlQuery query;
    query.prepare("SELECT COUNT(*) FROM PROJECT WHERE CODE = ?");
    query.addBindValue(code);
    if (query.exec() && query.next())
        return query.value(0).toInt() > 0;
    return false;
}

// --------------- Project status ---------------

bool ProjectDAO::setState(const QString &code, const QString &state)
{
    QSqlQuery query;
    query.prepare("UPDATE PROJECT SET STATE = ? WHERE CODE = ?");
    query.addBindValue(state);
    query.addBindValue(code);
    return query.exec();
}

QStringList ProjectDAO::getStates()
{
    return {"draft", "active", "paused", "completed", "cancelled"};
}

// --------------- Project documents ---------------

bool ProjectDAO::attachDocument(const QString &projectCode, const QString &docType, const QString &docCode)
{
    QSqlQuery query;
    query.prepare("INSERT INTO PROJECTDOCUMENT (PROJECT_CODE, DOC_TYPE, DOC_CODE, CREATEDBY) "
                  "VALUES (?, ?, ?, ?)");
    query.addBindValue(projectCode);
    query.addBindValue(docType);
    query.addBindValue(docCode);
    query.addBindValue("user");

    if (!query.exec()) {
        qWarning() << "ProjectDAO::attachDocument - Error:" << query.lastError().text();
        return false;
    }
    return true;
}

bool ProjectDAO::removeDocument(int docId)
{
    QSqlQuery query;
    query.prepare("DELETE FROM PROJECTDOCUMENT WHERE ID = ?");
    query.addBindValue(docId);
    return query.exec();
}

QVector<ProjectDocument> ProjectDAO::getDocuments(const QString &projectCode)
{
    QVector<ProjectDocument> result;
    QSqlQuery query;
    query.prepare("SELECT ID, PROJECT_CODE, DOC_TYPE, DOC_CODE FROM PROJECTDOCUMENT WHERE PROJECT_CODE = ?");
    query.addBindValue(projectCode);
    if (query.exec()) {
        while (query.next()) {
            ProjectDocument doc;
            doc.id = query.value(0).toInt();
            doc.projectCode = query.value(1).toString();
            doc.docType = query.value(2).toString();
            doc.docCode = query.value(3).toString();
            result.append(doc);
        }
    }
    return result;
}

// --------------- Project budget ---------------

bool ProjectDAO::addBudgetLine(const QString &projectCode, const QString &concept, double amount)
{
    QSqlQuery query;
    query.prepare("INSERT INTO PROJECTBUDGET (PROJECT_CODE, CONCEPT, AMOUNT, CREATEDBY) VALUES (?, ?, ?, ?)");
    query.addBindValue(projectCode);
    query.addBindValue(concept);
    query.addBindValue(amount);
    query.addBindValue("user");

    if (!query.exec()) {
        qWarning() << "ProjectDAO::addBudgetLine - Error:" << query.lastError().text();
        return false;
    }
    return true;
}

bool ProjectDAO::removeBudgetLine(int budgetId)
{
    QSqlQuery query;
    query.prepare("DELETE FROM PROJECTBUDGET WHERE ID = ?");
    query.addBindValue(budgetId);
    return query.exec();
}

QVector<ProjectBudget> ProjectDAO::getBudget(const QString &projectCode)
{
    QVector<ProjectBudget> result;
    QSqlQuery query;
    query.prepare("SELECT ID, PROJECT_CODE, CONCEPT, AMOUNT FROM PROJECTBUDGET WHERE PROJECT_CODE = ?");
    query.addBindValue(projectCode);
    if (query.exec()) {
        while (query.next()) {
            ProjectBudget b;
            b.id = query.value(0).toInt();
            b.projectCode = query.value(1).toString();
            b.concept = query.value(2).toString();
            b.amount = query.value(3).toDouble();
            result.append(b);
        }
    }
    return result;
}

double ProjectDAO::getTotalBudget(const QString &projectCode)
{
    QSqlQuery query;
    query.prepare("SELECT COALESCE(SUM(AMOUNT), 0) FROM PROJECTBUDGET WHERE PROJECT_CODE = ?");
    query.addBindValue(projectCode);
    if (query.exec() && query.next())
        return query.value(0).toDouble();
    return 0.0;
}

// --------------- Financial summary ---------------

double ProjectDAO::getTotalCost(const QString &projectCode)
{
    QSqlQuery query;
    query.prepare("SELECT COALESCE(SUM(PRICE), 0) FROM SALEDOCUMENT WHERE PROJECT_CODE = ?");
    query.addBindValue(projectCode);
    if (query.exec() && query.next())
        return query.value(0).toDouble();
    return 0.0;
}

double ProjectDAO::getTotalInvoiced(const QString &projectCode)
{
    QSqlQuery query;
    query.prepare("SELECT COALESCE(SUM(PRICE), 0) FROM SALEDOCUMENT WHERE PROJECT_CODE = ? AND TYPE = 'FA'");
    query.addBindValue(projectCode);
    if (query.exec() && query.next())
        return query.value(0).toDouble();
    return 0.0;
}

QPair<double, double> ProjectDAO::getFinancialSummary(const QString &projectCode)
{
    double totalBudget = getTotalBudget(projectCode);
    double totalCost = getTotalCost(projectCode);
    return {totalBudget, totalCost};
}