package ru.soune.nocopy.migration;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.service.file.cloud.CloudStorageService;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
@RequiredArgsConstructor
public class S3MigrationTool {

    private final FileEntityRepository fileEntityRepository;
    private final CloudStorageService cloudStorageService;

    private static final Path FAILED_LOG = Paths.get("migration_failed.txt");

    public void migrationFilesToS3() {
        log.info("=== START MIGRATION ===");
        clearLogFile();

        List<FileEntity> allFiles = fileEntityRepository.findAll();
        log.info("Total files: {}", allFiles.size());

        int success = 0;
        List<String> failedIds = new ArrayList<>();

        for (FileEntity file : allFiles) {
            if (migrateFile(file)) {
                success++;
            } else {
                failedIds.add(file.getId());
            }
        }

        log.info("=== COMPLETED: success {}, failed {} ===", success, failedIds.size());
        if (!failedIds.isEmpty()) {
            log.info("Failed file IDs: {}", String.join(", ", failedIds));
            log.info("Details saved to: {}", FAILED_LOG.toAbsolutePath());
        }
    }

    private boolean migrateFile(FileEntity file) {
        StringBuilder errors = new StringBuilder();

        try {
            cloudStorageService.saveFilesToStorage(
                    file.getMimeType(), file.getFileExtension(), file.getFilePath()
            );
        } catch (Exception e) {
            errors.append("main:").append(e.getMessage()).append("; ");
        }

        if ("image".equals(file.getMimeType())) {
            try {
                cloudStorageService.saveFilesToStorage(
                        file.getMimeType(), file.getFileExtension(), file.getMediumPath()
                );
            } catch (Exception e) {
                errors.append("medium:").append(e.getMessage()).append("; ");
            }
            try {
                cloudStorageService.saveFilesToStorage(
                        file.getMimeType(), file.getFileExtension(), file.getThumbnailPath()
                );
            } catch (Exception e) {
                errors.append("thumb:").append(e.getMessage()).append("; ");
            }
        }

        if (file.getProtectedFilePath() != null) {
            try {
                cloudStorageService.saveFilesToStorage(
                        file.getMimeType() != null ? file.getMimeType() : "application",
                        file.getFileExtension(),
                        file.getProtectedFilePath()
                );
            } catch (Exception e) {
                errors.append("protected:").append(e.getMessage()).append("; ");
            }
        }

        if (errors.length() > 0) {
            writeToFile(String.format("%s | %s | %s",
                    file.getId(), file.getOriginalFileName(), errors));
            log.warn("Failed to migrate: {} | {}", file.getId(), file.getOriginalFileName());
            return false;
        }

        return true;
    }

    private void clearLogFile() {
        try {
            Files.deleteIfExists(FAILED_LOG);
        } catch (IOException e) {
            log.warn("Failed to clear log file");
        }
    }

    private void writeToFile(String line) {
        try {
            Files.write(FAILED_LOG, (line + "\n").getBytes(),
                    StandardOpenOption.CREATE, StandardOpenOption.APPEND);
        } catch (IOException e) {
            log.error("Failed to write to log file", e);
        }
    }
}