package org.example.petshopdesktop.util;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public final class ActivityLogger {

    private static final ActivityLogger INSTANCE = new ActivityLogger();

    private static final String LOG_FILE_NAME = "log.txt";
    private static final DateTimeFormatter TS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private final Path logFilePath;

    private ActivityLogger() {
        this.logFilePath = resolveProjectRoot().resolve(LOG_FILE_NAME);
    }

    public static ActivityLogger getInstance() {
        return INSTANCE;
    }

    public void logInsert(String tableName, String recordId, String details) {
        write("INSERT", String.format("DB_INSERT | Table: %s | ID: %s | Details: %s", tableName, recordId, details));
    }

    public void logUpdate(String tableName, String recordId, String details) {
        write("UPDATE", String.format("DB_UPDATE | Table: %s | ID: %s | Details: %s", tableName, recordId, details));
    }

    public void logDelete(String tableName, String recordId, String details) {
        write("DELETE", String.format("DB_DELETE | Table: %s | ID: %s | Details: %s", tableName, recordId, details));
    }

    public void logException(String location, Exception exception, String context) {
        write("ERROR", String.format(
            "EXCEPTION | Location: %s | Type: %s | Message: %s | Context: %s",
            location,
            exception.getClass().getSimpleName(),
            String.valueOf(exception.getMessage()),
            context
        ));
    }

    public void logInfo(String category, String message) {
        write(category, message);
    }

    public Path getLogFilePath() {
        return logFilePath;
    }

    private static Path resolveProjectRoot() {
        Path start = Paths.get(System.getProperty("user.dir")).toAbsolutePath();
        Path current = start;

        for (int i = 0; i < 6 && current != null; i++) {
            if (Files.exists(current.resolve("pom.xml"))
                || Files.exists(current.resolve("mvnw"))
                || Files.exists(current.resolve("connectionpetstore.properties.example"))) {
                return current;
            }
            current = current.getParent();
        }

        return start;
    }

    private synchronized void write(String level, String message) {
        String timestamp = LocalDateTime.now().format(TS);
        String logEntry = String.format("[%s] [%s] %s%n", timestamp, level, message);

        try {
            Files.writeString(
                logFilePath,
                logEntry,
                StandardCharsets.UTF_8,
                StandardOpenOption.CREATE,
                StandardOpenOption.APPEND
            );
        } catch (Exception e) {
            System.err.println("Failed to write log entry: " + e.getMessage());
        }
    }
}
