package com.screenshot.scheduler;

import com.screenshot.config.AppConfig;
import com.screenshot.service.UploadService;
import com.screenshot.service.ZipService;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.concurrent.*;

/**
 * Планировщик ежедневной отправки скриншотов на сервер
 */
public class UploadScheduler {

    private final ScheduledExecutorService scheduler;
    private final ZipService zipService;
    private final UploadService uploadService;
    private final AppConfig config;
    private ScheduledFuture<?> currentTask;
    private volatile boolean running = false;

    public UploadScheduler(AppConfig config) {
        this.scheduler = Executors.newScheduledThreadPool(1);
        this.zipService = new ZipService();
        this.uploadService = new UploadService();
        this.config = config;
    }

    /**
     * Запустить планировщик
     */
    public void start() {
        if (!config.isUploadEnabled()) {
            System.out.println("Автоматическая отправка отключена");
            return;
        }

        if (running) {
            System.out.println("Планировщик отправки уже запущен");
            return;
        }

        running = true;
        scheduleNextUpload();
        System.out.println("Планировщик отправки запущен. Время отправки: " +
                config.getUploadScheduleTime());
    }

    /**
     * Запланировать следующую отправку
     */
    private void scheduleNextUpload() {
        if (!running) return;

        LocalTime uploadTime = config.getUploadScheduleTime();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime nextRun = now.toLocalDate().atTime(uploadTime);

        // Если время сегодня уже прошло, планируем на завтра
        if (now.isAfter(nextRun)) {
            nextRun = nextRun.plusDays(1);
        }

        long delayMillis = Duration.between(now, nextRun).toMillis();

        System.out.println("Следующая отправка запланирована на: " + nextRun);

        currentTask = scheduler.schedule(() -> {
            performUpload();
            scheduleNextUpload(); // Планируем следующую
        }, delayMillis, TimeUnit.MILLISECONDS);
    }

    /**
     * Выполнить отправку
     */
    public void performUpload() {
        System.out.println("\n========== НАЧАЛО ОТПРАВКИ ==========");
        System.out.println("Время: " + LocalDateTime.now());

        Path sourcePath = Path.of(config.getSavePath());
        Path tempDir = sourcePath.resolve(".temp_upload");

        try {
            // Проверяем доступность сервера
            String serverUrl = config.getUploadServerUrl();
            System.out.println("Проверка сервера: " + serverUrl);

            if (!uploadService.isServerAvailable(serverUrl)) {
                System.err.println("Сервер недоступен!");
                return;
            }
            System.out.println("Сервер доступен");

            // Создаём ZIP архивы
            System.out.println("Создание архивов...");
            List<Path> archives = zipService.createZipArchives(
                    sourcePath,
                    tempDir,
                    config.getMaxZipSizeBytes()
            );

            if (archives.isEmpty()) {
                System.out.println("Нет файлов для отправки");
                return;
            }

            System.out.println("Создано архивов: " + archives.size());

            // Отправляем архивы поочерёдно
            int successCount = 0;
            int failCount = 0;

            for (int i = 0; i < archives.size(); i++) {
                Path archive = archives.get(i);
                System.out.println("\nОтправка " + (i + 1) + "/" + archives.size() +
                        ": " + archive.getFileName());

                UploadService.UploadResult result = uploadService.uploadWithRetry(
                        archive,
                        serverUrl,
                        config.getUploadRetryCount(),
                        config.getUploadRetryDelaySeconds()
                );

                if (result.success()) {
                    successCount++;
                } else {
                    failCount++;
                    System.err.println("Не удалось отправить: " + archive.getFileName());
                }
            }

            // Итоги
            System.out.println("\n----- ИТОГИ -----");
            System.out.println("Успешно: " + successCount);
            System.out.println("Ошибок: " + failCount);

            // Удаляем исходные файлы если настроено
            if (failCount == 0 && config.isDeleteAfterUpload()) {
                System.out.println("Удаление исходных файлов...");
                zipService.deleteSourceFiles(sourcePath);
            }

            // Удаляем временные архивы
            zipService.deleteArchives(archives);

            // Удаляем временную директорию
            Files.deleteIfExists(tempDir);

        } catch (IOException e) {
            System.err.println("Ошибка отправки: " + e.getMessage());
            e.printStackTrace();
        }

        System.out.println("========== КОНЕЦ ОТПРАВКИ ==========\n");
    }

    /**
     * Остановить планировщик
     */
    public void stop() {
        running = false;
        if (currentTask != null) {
            currentTask.cancel(false);
        }
        System.out.println("Планировщик отправки остановлен");
    }

    /**
     * Перезапустить с новыми настройками
     */
    public void restart() {
        stop();
        start();
    }

    /**
     * Завершить работу
     */
    public void shutdown() {
        stop();
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public boolean isRunning() {
        return running;
    }
}
