#include <QDebug>
#include "fiebdc.h"
//#include "globalvars.h" // Asumiendo que globalVars está definido aquí

#include <QDate>

FIEBDC::FIEBDC(QString filename, Budget* budget) {
    __budget = budget;
    __filename = filename;
    if (__budget != nullptr) {
        __budget->filename = __filename;
    }
    __cancel = false;
    __format_list = {"FIEBDC-3/95", "FIEBDC-3/98", "FIEBDC-3/2002",
                     "FIEBDC-3/2004", "FIEBDC-3/2007"};
    __character_sets_dict = {{"ANSI", "cp1252"},
                             {"850", "850"},
                             {"437", "cp437"}};
    __file_format = "FIEBDC-3/2007";
    //__generator = globalVars.name + " " + globalVars.version;

    __character_set = "850";
    initializePatterns();
}

void FIEBDC::initializePatterns() {
    __pattern = {
        {"control_tilde", QRegularExpression(R"(((\r\n)| |\t)+~)")},
        {"control_vbar", QRegularExpression(R"(((\r\n)| |\t)+\|)")},
        {"control_backslash", QRegularExpression(R"(((\r\n)| |\t)+\\)")},
        {"valid_code", QRegularExpression(R"([^A-Za-z0-9ñÑ.$#%&_])")},
        {"special_char", QRegularExpression(R"([#%&])")},
        {"no_float", QRegularExpression(R"([^\-0-9.])")},
        {"formula", QRegularExpression(R"(.*[^0123456789\.()\+\-\*/\^abcdp ].*)")},
        {"comment", QRegularExpression(R"(#.*\r\n)")},
        {"empty_line", QRegularExpression(R"((\r\n) *\r\n)")},
        {"space_before_backslash", QRegularExpression(R"(( )+\\)")},
        {"space_after_backslash", QRegularExpression(R"(\\( )+)")},
        {"start_noend_backslash", QRegularExpression(R"((\r\n\\\.*[^\\\])\r\n)")},
        {"end_oper", QRegularExpression(R"((\+|-|\*|/|/^|@|&|<|>|<=|>=|=|!) *\r\n)")},
        {"matricial_var", QRegularExpression(R"((\r\n *[%|\$][A-ZÑ].*=.*, ) *\r\n)")},
        {"descomposition", QRegularExpression(R"(^([^:]+):(.*)$)")},
        {"var", QRegularExpression(R"(^([$%][A-ZÑ][()0-9, ]*)=(.*)$)")},
        {"after_first_tilde", QRegularExpression(R"(^[^~]*~)")},
        {"end_control", QRegularExpression(R"(((\r\n)| |\t)+$)")}
    };
}

void FIEBDC::cancel() {
    __cancel = true;
}

QString FIEBDC::eraseControlCharacters(const QString& input) {
    // Implementación de la función para eliminar caracteres de control
    QString string = input;
    string = string.replace(__pattern["control_tilde"], "~");
    string = string.replace(__pattern["control_vbar"], "|");
    // Uncomment if control_backslash processing is needed
    // string = string.replace(__pattern["control_backslash"], "\\");
    return string;
}

bool FIEBDC::validateCode(const QString& code) {
    // Implementación de la función para validar el código
    QRegularExpression re("^[A-Z0-9]+$");
    return re.match(code).hasMatch();
}

QDate FIEBDC::parseDate(const QString& dateStr) {
    /*parseDate(date)

    date: in the format:
        uneven len: add a Leading 0
        len = 8  DDMMYYYY
        len <= 6 DDMMYY “80/20”. >80 -> >1980 <80 -> <2080
        len < 5  MMYY
        len < 3  YY
    Test date string and return a tuple (YYYY, MM, DD)
    or None if the date format is invalid
    */

    if (dateStr.isEmpty()) {
        return QDate();
    }

    QString paddedDate = dateStr;
    if (dateStr.length() % 2 != 0) {
        paddedDate.prepend("0"); // Agregar un 0 inicial si la longitud es impar
    }

    // Intentar con diferentes formatos según la longitud
    if (paddedDate.length() == 8) {
        return QDate::fromString(paddedDate, "ddMMyyyy");
    } else if (paddedDate.length() == 6) {
        QString yearPrefix = paddedDate.right(2).toInt() < 80 ? "20" : "19";
        return QDate::fromString(yearPrefix + paddedDate, "yyyyMMdd");
    } else if (paddedDate.length() == 4) {
        QString yearPrefix = paddedDate.right(2).toInt() < 80 ? "20" : "19";
        return QDate::fromString(yearPrefix + paddedDate, "yyyyMM");
    } else if (paddedDate.length() == 2) {
        QString yearPrefix = paddedDate.toInt() < 80 ? "20" : "19";
        return QDate::fromString(yearPrefix + paddedDate, "yyyy");
    }

    return QDate(); // Fecha inválida
}


void FIEBDC::parseRecord(const QString& record) {
    /*
    parseRecord(record, interface)

        record: the record line readed from the file whith the format:
            type|field|field|subfield\\subfield|...
        [a] nothing or "a"
        {a} zero or more #-#twice#-# "a"
        <a> one or more #-#twice#-# "a"
        Types: V C D Y M N T K L Q J G E X B F A
            V: Property and Version
                1- [File_Owner]
                2- Format_Version[\\DDMMYYYY]
                3- [Program_Generator]
                4- [Header]\\{Title\\}
                5- [Chaters_set]
                6- [Comment]
            C: Record:
                1- Code{\\Code}
                2- [Unit]
                3- [Summary]
                4- {Price\\}
                5- {Date\\}
                6- [Type]
            D or Y: DECOMPOSITION or ADD DECOMPOSITION
                1- Parent Code
                2- <Child Code\\ [Factor]\\ [Yield]>
            M or N: MEASURE or ADD MEASURE
                1- [Parent Code\\]Child Code
                2- {Path\}
                3- TOTAL MEASURE
                4- {Type\\Comment\\Unit\\Length\\Width\\Height\\}
                5- [Label]
            T: Text
                1- Code
                2- Description text
            K: Coefficients
                1- { DN \\ DD \\ DS \\ DR \\ DI \\ DP \\ DC \\ DM \\ DIVISA \\ }
                2-  CI \\ GG \\ BI \\ BAJA \\ IVA
                3- { DRC \\ DC \\ DRO \\ DFS \\ DRS \\ DFO \\ DUO \\ DI \\ DES \\ DN \\
                  DD \\ DS \\ DIVISA \\ }
                4- [ n ]
            L: Sheet of Conditions 1
                A)
                    1- Empty
                    2- {Section Code\\Section Title}
                B)
                    1- Record Code
                    2- {Section Code\\Section Text}
                    3- {Section Code\\RTF file}
                    4- {Section Code\\HTM file}
            Q: Sheet of Conditions 2
                1- Record Code
                2- {Section Code\\Paragraph key\\{Field key;}\\}|
            J: Sheet of Conditions 3
                1- Paragraph code
                2- [Paragraph text]
                3- [RTF file]
                4- [HTML file]
            G: Grafic info
                1- <grafic_file.ext\\>
            E: Company
                1- company Code
                2 [ summary ]
                3- [ name ]
                4- { [ type ] \\ [ subname ] \\ [ address ] \\ [ postal_code ]
                  \\ [ town ] \\ [ province ] \\ [ country ] \\ { phone; }
                  \\ { fax; }  \\ {contact_person; } \\ }
                5- [ cif ] \\ [ web ] \\ [ email ] \\
            X: Tecnical information
                A)
                    1- Empty
                    2- < TI_Code \\ TI_Descitption \\ TI_Unit >
                B)
                    1- Record_code
                    2- < TI_Code \\ TI_value >
            F: #-#Adjunto#-# File
                1- Record code
                2- { Type \\ { Filenames; } \\ [Description] }
            B: Change code
                1- Record Code
                2- New code
            A: Labels
                1- Record Code
                2- <Label\\>
            interface:
    */
    QStringList fields = record.split("|");
    if (fields.isEmpty()) {
        return;
    }

    QString recordType = fields.at(0);
    if (recordType == "V")
    {
    }
    else if (recordType == "C")
    {
    }
    else if (recordType == "D" || recordType == "Y")
    {
    }
    else if (recordType == "T")
    {
    } else {
        qDebug() << "Unknown record type:" << recordType << fields;
    }
}

void FIEBDC::parseV(QStringList fields)
{
    /*
    parseV(field_list)

    field_list: field list of the record
        0- V :Property and Version
        1- [File_Owner]
        2- Format_Version[\DDMMYYYY]
        3- [Program_Generator]
        4- [Header]\{Title\}
        5- [Chaters_set]
        6- [Comment]
        7- [Data type]
        8- [Number budget certificate]
        9- [Date budget certificate]
    */

    if (fields.size() < 10) {
        qWarning() << "Invalid 'V' record, insufficient fields:" << fields;
        return;
    }

    QString owner = fields[1].trimmed();
    QString versionDate = fields[2].trimmed();
    QString generator = fields[3].trimmed();
    QString headerTitle = fields[4].trimmed();
    QString characterSet = fields[5].trimmed();
    QString comment = fields[6].trimmed();
    QString dataType = fields[7].trimmed();
    QString numberCertificate = fields[8].trimmed();
    QString dateCertificate = fields[9].trimmed();

    // Process version and date
    QStringList versionDateParts = versionDate.split("\\");
    if (!versionDateParts.isEmpty()) {
        auto fileFormat = versionDateParts[0];
        qDebug() << "File format set to:" << fileFormat;

        if (versionDateParts.size() > 1) {
            QDate parsedDate = parseDate(versionDateParts[1]);
            if (parsedDate.isValid()) {
                qDebug() << "Parsed version date:" << parsedDate;
            }
        }
    }

    /*
    # _____number of fields_____
    # Any INFORMATION after last field separator is ignored
    if len(field_list) > 10:
        field_list = field_list[:10]
    # If there are no sufficient fields, the fields are added
    # with empty value:""
    else:
        field_list = field_list + [""]*(10-len(field_list))
    # control character are erased: end of line, tab, space
    # only leading and trailing whitespace in owner, generator, comment
    # _____Fields_____
    _record_type = self.delete_control_space(field_list[0])
    _owner = field_list[1].strip()
    _owner = self.delete_control(_owner)
    _version_date = self.delete_control_space(field_list[2])
    _generator = field_list[3].strip()
    _generator = self.delete_control(_generator)
    _header_title = field_list[4].strip()
    _header_title = self.delete_control(_header_title)
    _character_set = self.delete_control_space(field_list[5])
    _comment = field_list[6].strip("\t \n\r")
    _data_type = self.delete_control_space(field_list[7])
    _number_certificate = self.delete_control_space(field_list[8])
    __date_certificate = self.delete_control_space(field_list[9])
    # _____Owner_____
    self.__budget.setOwner(_owner)
    # _____Version-Date_____
    _version_date = _version_date.split("\\")
    _file_format = _version_date[0]
    if _file_format in self.__format_list:
        self.__file_format = _file_format
        _tuni = _("FIEBDC format: $1")
        _uni = utils.mapping(_tuni, (_file_format,))
        print(_uni)

    if len(_version_date) > 1:
        _date = _version_date[1]
        if _date != "":
            _parsed_date = self.parseDate(_date)
            if _parsed_date is not  None:
                self.__budget.setDate(_parsed_date)
    # _____Generator_____
    # ignored field
    _tuni = _("FIEBDC file generated by $1")
    _uni = utils.mapping(_tuni, (_generator,))
    print(_uni)
    # _____Header_Title_____
    _header_title = _header_title.split("\\")
    _header_title = [_title.strip() for _title in _header_title]
    _header = _header_title.pop(0)
    _title = [ ]
    for _title_index in _header_title:
        if _title_index != "":
            _title.append(_title_index)
    if _header != "":
        self.__budget.setTitleList([ _header, _title])
    # _____Characters_set_____
    # field parsed in readFile method
    # _____Comment_____
    if _comment != "":
        self.__budget.setComment(_comment)
    # _____Data type_____
    # 1 -> Base data.
    # 2 -> Budget.
    # 3 -> Budget certificate.
    # 4 -> Base date update.
    try:
        _data_type = int(_data_type)
    except ValueError:
        _data_type = ""
    if _data_type == 3:
        # _____Number budget certificate_____
        try:
            _number_certificate = int(_number_certificate)
        except ValueError:
            _number_certificate = ""
        # _____Date budget certificate_____
        if _date_certificate != "":
            _parsed_date_certificate = self.parseDate(_date_certificate)
            if _parsed_date_certificate is None:
                _date_certificate = ""
            else:
                _date_certificate = _parsed_date_certificate
        self.__budget.setBudgetype(_data_type)
        self.__budget.setCertificateOrder(_number_certificate)
        self.__budget.setCertificateDate(_parsed_date_cerfificate)
    elif _data_type != "":
        self.__budget.setBudgeType(_data_type)
    self.__statistics.valid = self.__statistics.valid + 1
    */
}

void FIEBDC::readFile(Budget* budget, QString filename) {
    // Implementación de la función para leer el archivo
    if (budget != nullptr) {
        __budget = budget;
    }
    if (!filename.isEmpty()) {
        __filename = filename;
    }
    // Lógica para leer el archivo
}
