package com.caliverse.admin.domain.datacomponent;

import com.caliverse.admin.global.common.exception.MetaDataException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

@Component
@Slf4j
public class JsonFileReader {
    @Value("${caliverse.metadata.path}")
    private String metaDataPath;

    private final ObjectMapper objectMapper;

    public JsonFileReader() {
        this.objectMapper = new ObjectMapper();
    }

    public List<Map<String, Object>> readJsonFile(String metaName) {
        List<Map<String, Object>> resultMap = new ArrayList<>();

        try {
            File metaFile = new File(metaDataPath, metaName);
            log.info("Trying to load data from: {}", metaFile.getPath());

            if (metaFile.isDirectory()) {
                // 디렉토리인 경우 모든 JSON 파일을 읽어서 결과를 합침
                log.info("Found directory: {}, reading all JSON files", metaFile.getPath());

                try (Stream<Path> paths = Files.walk(metaFile.toPath())) {
                    List<File> jsonFiles = paths
                            .filter(Files::isRegularFile)
                            .filter(p -> p.toString().toLowerCase().endsWith(".json"))
                            .map(Path::toFile)
                            .toList();

                    if (jsonFiles.isEmpty()) {
                        log.warn("No JSON files found in directory: {}", metaFile.getPath());
                        return null;
                    }

                    for (File jsonFile : jsonFiles) {
                        log.info("Processing JSON file: {}", jsonFile.getPath());
                        List<Map<String, Object>> fileResult = parseJsonFile(jsonFile);
                        if (fileResult != null) {
                            resultMap.addAll(fileResult);
                        }
                    }
                }
            } else {
                // 일반 파일인 경우
                String jsonFileName = metaName + "Data.json";
                metaFile = new File(metaDataPath, jsonFileName);
                log.info("Original path not found, trying: {}", metaFile.getPath());

                if (!metaFile.exists()) {
                    log.error("Neither directory nor file found: {} or {}", metaName, jsonFileName);
                    return null;
                }

                return parseJsonFile(metaFile);
            }

        } catch (IOException e) {
            log.error("Failed to read from path: {}", metaName, e);
            throw new MetaDataException("Failed to read from path: " + metaName, e);
        }

        return resultMap;
    }

    private List<Map<String, Object>> parseJsonFile(File file) {
        try {
            log.debug("Parsing JSON file: {}", file.getPath());
            String fileContent = readFileAsString(file);
            JsonNode rootNode = objectMapper.readTree(fileContent);
//            JsonNode listNode = rootNode.get(listName);

            if (!rootNode.isEmpty()) {
                String firstFieldName = rootNode.fieldNames().next();
                JsonNode firstNode = rootNode.get(firstFieldName);

                List<Map<String, Object>> resultList = objectMapper.readValue(
                        firstNode.toString(),
                        new TypeReference<>() {}
                );

                log.debug("Successfully parsed JSON file: {}, first field: {}, items count: {}",
                        file.getName(), firstFieldName, resultList.size());
                return resultList;
            } else {
                log.warn("No fields found in JSON file: {}", file.getPath());
                return null;
            }

        } catch (JsonProcessingException e) {
            log.error("Failed to parse JSON from file: {}", file.getName(), e);
            throw new MetaDataException("Failed to parse JSON from file: " + file.getName(), e);
        } catch (IOException e) {
            log.error("Failed to read file: {}", file.getName(), e);
            throw new MetaDataException("Failed to read file: " + file.getName(), e);
        }
    }

    private String readFileAsString(File file) throws IOException {
        StringBuilder fileContents = new StringBuilder((int)file.length());
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
            String line;
            while((line = br.readLine()) != null) {
                fileContents.append(line);
            }
        }
        return fileContents.toString();
    }
}
