package ru.nbch.indicsearchservice.exporter;

import jakarta.annotation.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import ru.nbch.indicsearchservice.config.settings.ApplicationSettings;
import ru.nbch.indicsearchservice.model.TableData;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.json.JsonMapper;

@Component
public class JsonExporter implements Exporter {
    private static final Logger log = LoggerFactory.getLogger(JsonExporter.class);

    private final ApplicationSettings settings;
    private final JsonMapper jsonMapper;

    public JsonExporter(ApplicationSettings settings,
                        JsonMapper jsonMapper) {
        this.settings = settings;
        this.jsonMapper = jsonMapper;
    }

    public void writeJsonFile(@Nullable Path aggregatedFile, UUID taskId) {
        if (aggregatedFile == null) {
            return;
        }

        Path jsonFile = settings.getStorageDirectory().toPath().resolve(taskId.toString() + ".json");

        try (BufferedReader reader = Files.newBufferedReader(aggregatedFile);
             JsonGenerator jsonGenerator = jsonMapper.createGenerator(Files.newOutputStream(jsonFile))) {
            jsonGenerator.writeStartArray();

            Iterator<String> iterator = reader.lines().iterator();
            List<String> rows = new ArrayList<>();
            boolean isFirst = true;

            while (iterator.hasNext()) {
                String line = iterator.next();

                if (line == null || line.trim().isEmpty()) {
                    continue;
                }

                List<String> lineList = Arrays.asList(line.split("%%%", -1));
                String tableName = lineList.getFirst();

                if (!isFirst && (FIRST_LEVEL_TABLES.contains(tableName) || line.equals("EOF"))) {
                    TableData parentData = buildTableDataHierarchy(rows);
                    if (parentData != null) {
                        jsonMapper.writeValue(jsonGenerator, parentData);
                    }
                    rows.clear();
                }

                rows.add(line);
                isFirst = false;
            }

            jsonGenerator.writeEndArray();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    private TableData buildTableDataHierarchy(List<String> rows) {
        if (rows == null || rows.isEmpty()) {
            return null;
        }

        TableData parentTableData = parseSingleRow(rows.getFirst());
        if (parentTableData == null) {
            return null;
        }

        for (int i = 1; i < rows.size(); i++) {
            TableData childTableData = parseSingleRow(rows.get(i));
            if (childTableData != null) {
                parentTableData.getRelatedTableData().add(childTableData);
            }
        }

        return parentTableData;
    }

    private TableData parseSingleRow(String row) {
        String[] parts = row.split("%%%", -1);

        if (parts.length == 0 || parts[0].isEmpty()) {
            return null;
        }

        String tableName = parts[0];
        List<TableData.FieldData> fieldData = new ArrayList<>();

        for (int i = 1; i + 1 < parts.length; i += 2) {
            String columnName = parts[i];
            String columnValue = parts[i + 1];

            if (columnName != null && !columnName.isEmpty()) {
                fieldData.add(new TableData.FieldData(columnName, columnValue));
            }
        }

        return new TableData(tableName, fieldData);
    }
}
