package com.nanri.aiimage.modules.file.service;

import cn.hutool.core.io.FileUtil;
import com.nanri.aiimage.config.StorageProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.regex.Pattern;

@Slf4j
@Service
@RequiredArgsConstructor
public class LocalTempCleanupService {

    private static final Pattern ROOT_TEMP_FILE_PATTERN = Pattern.compile("^[a-fA-F0-9]{32}(\\.[^.]+)?$");
    private static final List<String> RESULT_DIR_NAMES = List.of(
            "dedupe-result",
            "convert-result",
            "split-result",
            "brand-source-download",
            "brand-result"
    );

    private final StorageProperties storageProperties;

    @Scheduled(cron = "${aiimage.storage.cleanup-cron:0 0 */6 * * *}")
    public void cleanupLocalTempDir() {
        if (!storageProperties.isCleanupEnabled()) {
            return;
        }
        File tempDir = FileUtil.file(storageProperties.getLocalTempDir());
        if (!tempDir.exists() || !tempDir.isDirectory()) {
            return;
        }

        Instant sourceExpireBefore = Instant.now().minus(storageProperties.getSourceRetentionHours(), ChronoUnit.HOURS);
        Instant resultExpireBefore = Instant.now().minus(storageProperties.getResultRetentionHours(), ChronoUnit.HOURS);

        int deletedSourceCount = 0;
        int deletedResultCount = 0;
        File[] children = tempDir.listFiles();
        if (children == null || children.length == 0) {
            return;
        }

        for (File child : children) {
            try {
                if (child.isFile() && isManagedRootTempFile(child) && isExpired(child, sourceExpireBefore)) {
                    if (FileUtil.del(child)) {
                        deletedSourceCount++;
                    }
                    continue;
                }
                if (child.isDirectory() && RESULT_DIR_NAMES.contains(child.getName())) {
                    deletedResultCount += deleteExpiredChildrenRecursively(child, resultExpireBefore);
                    deleteEmptyDirectories(child, tempDir);
                }
            } catch (Exception ex) {
                log.warn("清理本地临时文件失败: path={}", child.getAbsolutePath(), ex);
            }
        }

        if (deletedSourceCount > 0 || deletedResultCount > 0) {
            log.info("本地临时目录清理完成: sourceDeleted={}, resultDeleted={}, tempDir={}", deletedSourceCount, deletedResultCount, tempDir.getAbsolutePath());
        }
    }

    private int deleteExpiredChildrenRecursively(File file, Instant expireBefore) {
        int deletedCount = 0;
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null) {
                for (File child : children) {
                    deletedCount += deleteExpiredChildrenRecursively(child, expireBefore);
                }
            }
            if (isExpired(file, expireBefore) && isDirectoryEmpty(file) && FileUtil.del(file)) {
                deletedCount++;
            }
            return deletedCount;
        }
        if (isExpired(file, expireBefore) && FileUtil.del(file)) {
            return 1;
        }
        return 0;
    }

    private void deleteEmptyDirectories(File directory, File stopAt) {
        File current = directory;
        while (current != null && !current.equals(stopAt) && isDirectoryEmpty(current)) {
            if (!FileUtil.del(current)) {
                return;
            }
            current = current.getParentFile();
        }
    }

    private boolean isManagedRootTempFile(File file) {
        return ROOT_TEMP_FILE_PATTERN.matcher(file.getName()).matches();
    }

    private boolean isExpired(File file, Instant expireBefore) {
        return Instant.ofEpochMilli(file.lastModified()).isBefore(expireBefore);
    }

    private boolean isDirectoryEmpty(File directory) {
        File[] children = directory.listFiles();
        return children == null || children.length == 0;
    }
}
