#include "csvexporter.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/specificationtablemodel.h"
#include "../model/perechentablemodel.h"
#include "../model/vedomosttablemodel.h"
#include "../model/simplelisttablemodel.h"
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QDebug>
#include <QStandardPaths>

CSVExporter::CSVExporter(QObject *parent)
    : QObject(parent)
{
}

bool CSVExporter::exportSpecificationPCB(const QString &filePath, SpecificationPCBTableModel *model)
{
    if (!model) {
        m_lastError = "Модель таблицы не указана";
        return false;
    }
    
    return exportTableModel(filePath, model, true);
}

bool CSVExporter::exportSpecification(const QString &filePath, SpecificationTableModel *model)
{
    if (!model) {
        m_lastError = "Модель таблицы не указана";
        return false;
    }
    
    return exportTableModel(filePath, model, true);
}

bool CSVExporter::exportPerechen(const QString &filePath, PerechenTableModel *model)
{
    if (!model) {
        m_lastError = "Модель таблицы не указана";
        return false;
    }
    
    return exportTableModel(filePath, model, true);
}

bool CSVExporter::exportVedomost(const QString &filePath, VedomostTableModel *model)
{
    if (!model) {
        m_lastError = "Модель таблицы не указана";
        return false;
    }
    
    return exportTableModel(filePath, model, true);
}

bool CSVExporter::exportSimpleList(const QString &filePath, SimpleListTableModel *model)
{
    if (!model) {
        m_lastError = "Модель таблицы не указана";
        return false;
    }
    
    return exportTableModel(filePath, model, true);
}

bool CSVExporter::exportTableModel(const QString &filePath, QAbstractTableModel *model, bool includeHeaders)
{
    if (!model) {
        m_lastError = "Модель таблицы не указана";
        return false;
    }
    
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        m_lastError = QString("Не удалось открыть файл для записи: %1").arg(file.errorString());
        return false;
    }
    
    // Записываем UTF-8 BOM напрямую в файл для корректного отображения в Excel
    QByteArray bom;
    bom.append(static_cast<char>(0xEF));
    bom.append(static_cast<char>(0xBB));
    bom.append(static_cast<char>(0xBF));
    if (file.write(bom) != 3) {
        m_lastError = "Не удалось записать BOM в файл";
        file.close();
        return false;
    }
    
    QTextStream out(&file);
    // Устанавливаем кодировку UTF-8 для корректного отображения в Excel
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    if (codec) {
        out.setCodec(codec);
    } else {
        // Fallback на строковое имя кодировки
        out.setCodec("UTF-8");
    }
    // Отключаем автоматическое определение Unicode, так как мы уже записали BOM
    out.setAutoDetectUnicode(false);
    
    // Разделитель для CSV (точка с запятой для Excel в русской локали)
    const QString delimiter = ";";
    
    try {
        // Записываем заголовки, если нужно
        if (includeHeaders) {
            QStringList headers;
            int columnCount = model->columnCount();
            for (int col = 0; col < columnCount; ++col) {
                QVariant header = model->headerData(col, Qt::Horizontal, Qt::DisplayRole);
                headers << escapeCsvValue(header.toString());
            }
            out << formatCsvRow(headers) << "\n";
        }
        
        // Записываем данные
        int rowCount = model->rowCount();
        for (int row = 0; row < rowCount; ++row) {
            QStringList values;
            int columnCount = model->columnCount();
            
            for (int col = 0; col < columnCount; ++col) {
                QModelIndex index = model->index(row, col);
                QVariant data = model->data(index, Qt::DisplayRole);
                values << escapeCsvValue(data.toString());
            }
            
            out << formatCsvRow(values) << "\n";
        }
        
        file.close();
        m_lastError.clear();
        return true;
        
    } catch (const std::exception &e) {
        m_lastError = QString("Ошибка при записи в файл: %1").arg(e.what());
        file.close();
        return false;
    } catch (...) {
        m_lastError = "Неизвестная ошибка при записи в файл";
        file.close();
        return false;
    }
}

QString CSVExporter::escapeCsvValue(const QString &value) const
{
    // Если значение содержит разделитель, кавычки или перенос строки, заключаем в кавычки
    if (value.contains(";") || value.contains("\"") || value.contains("\n") || value.contains("\r")) {
        // Экранируем кавычки удвоением
        QString escaped = value;
        escaped.replace("\"", "\"\"");
        return "\"" + escaped + "\"";
    }
    
    return value;
}

QString CSVExporter::formatCsvRow(const QStringList &values) const
{
    return values.join(";");
}

QString CSVExporter::lastError() const
{
    return m_lastError;
}

