package ru.soune.nocopy.service.file;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ru.soune.nocopy.entity.user.ProtectedFileCheck;
import ru.soune.nocopy.repository.ProtectedFileCheckRepository;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
public class FileCleanupService {

    @Value("${file.storage.base-path}")
    private String basePath;

    @Value("${file.storage.temp-ttl-hours}")
    private int tempTtlHours;

    private final ProtectedFileCheckRepository protectedFileCheckRepository;

    @Scheduled(cron = "0 0 3 * * *")
    public void cleanupExpiredFiles() {
        log.info("Starting cleanup of expired temporary files");

        cleanupOldPeriods();

        Path tempDir = Paths.get(basePath, "temp");
        if (!Files.exists(tempDir)) {
            return;
        }

        try {
            Files.walkFileTree(tempDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                        throws IOException {

                    LocalDateTime fileTime = LocalDateTime.ofInstant(
                            Instant.ofEpochMilli(attrs.lastModifiedTime().toMillis()),
                            ZoneId.systemDefault()
                    );

                    LocalDateTime cutoffTime = LocalDateTime.now()
                            .minusHours(tempTtlHours);

                    if (fileTime.isBefore(cutoffTime)) {
                        Files.delete(file);
                        log.debug("Deleted expired file: {}", file);
                    }

                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                        throws IOException {

                    if (exc == null) {
                        if (Files.list(dir).count() == 0 &&
                                !dir.equals(tempDir)) {
                            Files.delete(dir);
                            log.debug("Deleted empty directory: {}", dir);
                        }
                    }

                    return FileVisitResult.CONTINUE;
                }
            });

            log.info("Cleanup completed successfully");

        } catch (IOException e) {
            log.error("Error during cleanup", e);
        }
    }

    private void cleanupOldPeriods() {
        LocalDate thirtyDaysAgo = LocalDate.now().minusDays(30);

        List<ProtectedFileCheck> checks = protectedFileCheckRepository.findByPeriodStartDateBefore(thirtyDaysAgo);

        for (ProtectedFileCheck check : checks) {
            check.cleanupOldData();
        }

        protectedFileCheckRepository.saveAll(checks);
        log.info("Cleaned up {} old protection usage records", checks.size());
    }
}
