package de.assecutor.votianlt.service;

import de.assecutor.votianlt.model.User;
import de.assecutor.votianlt.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Locale;

/**
 * Service für monatliche Scheduler-Aufgaben, die am letzten Tag des Monats
 * (Ultimo) ausgeführt werden.
 */
@Service
public class MonthlySchedulerService {

    private static final Logger logger = LoggerFactory.getLogger(MonthlySchedulerService.class);

    private final EmailService emailService;
    private final UserRepository userRepository;

    public MonthlySchedulerService(EmailService emailService, UserRepository userRepository) {
        this.emailService = emailService;
        this.userRepository = userRepository;
    }

    /**
     * Läuft täglich um 08:00 Uhr und erinnert die Administratoren drei Tage vor
     * Ultimo per E-Mail daran, die Monatsrechnungen fertigzustellen.
     */
    @Scheduled(cron = "0 0 8 * * *")
    public void checkAndSendInvoiceReminder() {
        LocalDate today = LocalDate.now();
        LocalDate lastDayOfMonth = YearMonth.from(today).atEndOfMonth();

        if (!today.equals(lastDayOfMonth.minusDays(3))) {
            return;
        }

        logger.info("Drei Tage vor Ultimo ({}): Sende Rechnungs-Erinnerung an die Administratoren.", lastDayOfMonth);
        sendInvoiceReminderToAdmins(lastDayOfMonth);
    }

    private void sendInvoiceReminderToAdmins(LocalDate lastDayOfMonth) {
        List<User> admins = userRepository.findAll().stream()
                .filter(user -> user.getRoles() != null && user.getRoles().contains("ADMIN"))
                .filter(user -> user.getEmail() != null && !user.getEmail().isBlank()).toList();

        if (admins.isEmpty()) {
            logger.warn("Keine Administratoren mit E-Mail-Adresse gefunden, Rechnungs-Erinnerung entfällt.");
            return;
        }

        String monthLabel = YearMonth.from(lastDayOfMonth)
                .format(DateTimeFormatter.ofPattern("LLLL yyyy", Locale.GERMAN));
        String dueDateLabel = lastDayOfMonth.format(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
        String subject = "Erinnerung: Rechnungen für " + monthLabel + " erstellen";
        String body = "Hallo,\n\n" //
                + "in drei Tagen ist Ultimo (" + dueDateLabel + ").\n"
                + "Bitte die Monatsrechnungen für " + monthLabel
                + " fertigstellen: Seite \"Rechnungen erstellen\" im Admin-Bereich (/admin-create-invoices).\n\n"
                + "Diese Nachricht wurde automatisch von VotianLT versendet.";

        for (User admin : admins) {
            try {
                emailService.sendSimpleEmail(admin.getEmail(), subject, body);
                logger.info("Rechnungs-Erinnerung an {} gesendet.", admin.getEmail());
            } catch (Exception e) {
                logger.error("Rechnungs-Erinnerung an {} fehlgeschlagen: {}", admin.getEmail(), e.getMessage(), e);
            }
        }
    }

    /**
     * Scheduler, der täglich um 23:00 Uhr läuft und prüft, ob heute der letzte Tag
     * des Monats ist. Wenn ja, wird die monatliche Aufgabe ausgeführt.
     */
    @Scheduled(cron = "0 0 23 * * *") // Täglich um 23:00 Uhr
    public void checkAndRunMonthlyTask() {
        LocalDate today = LocalDate.now();
        LocalDate lastDayOfMonth = YearMonth.from(today).atEndOfMonth();

        if (today.equals(lastDayOfMonth)) {
            logger.info("Heute ist der letzte Tag des Monats ({}). Führe monatliche Aufgabe aus.", today);
            runMonthlyUltimoTask();
        } else {
            logger.debug("Heute ({}) ist nicht der letzte Tag des Monats. Nächster Ultimo: {}", today, lastDayOfMonth);
        }
    }

    /**
     * Alternative Implementierung: Direkter Cron-Ausdruck für den letzten Tag des
     * Monats. Dieser Scheduler läuft am letzten Tag jedes Monats um 23:00 Uhr.
     * 
     * Hinweis: Dieser Ansatz ist weniger flexibel, da er nicht alle Monate korrekt
     * abdeckt. Der obige Ansatz mit täglicher Prüfung ist robuster.
     */
    // @Scheduled(cron = "0 0 23 L * *") // Am letzten Tag des Monats um 23:00 Uhr
    public void runMonthlyUltimoTaskDirect() {
        logger.info("Monatliche Ultimo-Aufgabe wird direkt ausgeführt am: {}", LocalDate.now());
        runMonthlyUltimoTask();
    }

    /**
     * Die eigentliche monatliche Aufgabe, die am Ultimo ausgeführt wird. Hier
     * können Sie Ihre spezifische Geschäftslogik implementieren.
     */
    private void runMonthlyUltimoTask() {
        try {
            logger.info("=== MONATLICHE ULTIMO-AUFGABE GESTARTET ===");

            generateMonthlyReports();
            cleanupOldData();
            sendMonthlyNotifications();

            logger.info("=== MONATLICHE ULTIMO-AUFGABE ERFOLGREICH ABGESCHLOSSEN ===");

        } catch (Exception e) {
            logger.error("Fehler bei der Ausführung der monatlichen Ultimo-Aufgabe", e);
            // Hier könnten Sie zusätzliche Fehlerbehandlung implementieren,
            // z.B. E-Mail-Benachrichtigung an Administratoren
        }
    }

    /**
     * Beispiel-Methode: Monatliche Berichte generieren
     */
    private void generateMonthlyReports() {
        logger.info("Generiere monatliche Berichte...");
    }

    /**
     * Beispiel-Methode: Alte Daten bereinigen
     */
    private void cleanupOldData() {
        logger.info("Bereinige alte Daten...");
    }

    /**
     * Beispiel-Methode: Monatliche Benachrichtigungen versenden
     */
    private void sendMonthlyNotifications() {
        logger.info("Versende monatliche Benachrichtigungen...");
    }

    /**
     * Hilfsmethode zum manuellen Auslösen der monatlichen Aufgabe (z.B. für Tests)
     */
    public void triggerMonthlyTaskManually() {
        logger.info("Monatliche Aufgabe wird manuell ausgelöst");
        runMonthlyUltimoTask();
    }
}