package de.oaa.xxx.games.bdsm;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import de.oaa.xxx.games.bdsm.entity.BdsmGameEntity;
import de.oaa.xxx.games.bdsm.repository.AktiveSperreRepository;
import de.oaa.xxx.games.bdsm.repository.BdsmGameRepository;
import de.oaa.xxx.games.bdsm.repository.MitspielerRepository;
import de.oaa.xxx.games.chastity.cardlock.CardLockEntity;
import de.oaa.xxx.games.chastity.cardlock.CardlockRepository;
import de.oaa.xxx.games.history.GameHistoryEntity;
import de.oaa.xxx.games.history.GameHistoryRepository;
import de.oaa.xxx.games.history.GameRole;
import de.oaa.xxx.games.history.GameType;
import de.oaa.xxx.social.SystemMessageService;
import de.oaa.xxx.social.entity.MessageCause;
import de.oaa.xxx.user.UserRepository;

/**
 * Service für komplexe BDSM-Game-Operationen.
 * Kapselt Spielabschluss-Logik (XP-Vergabe, History) und den BDSM→Chastity-Übergang.
 */
@Service
public class BdsmGameService {

    private static final Logger LOGGER = LoggerFactory.getLogger(BdsmGameService.class);

    private final BdsmGameRepository sessionRepository;
    private final MitspielerRepository mitspielerRepository;
    private final AktiveSperreRepository aktiveSperreRepository;
    private final UserRepository userRepository;
    private final GameHistoryRepository gameHistoryRepository;
    private final CardlockRepository cardlockRepository;
    private final SystemMessageService systemMessageService;

    public BdsmGameService(BdsmGameRepository sessionRepository,
                           MitspielerRepository mitspielerRepository,
                           AktiveSperreRepository aktiveSperreRepository,
                           UserRepository userRepository,
                           GameHistoryRepository gameHistoryRepository,
                           CardlockRepository cardlockRepository,
                           SystemMessageService systemMessageService) {
        this.sessionRepository = sessionRepository;
        this.mitspielerRepository = mitspielerRepository;
        this.aktiveSperreRepository = aktiveSperreRepository;
        this.userRepository = userRepository;
        this.gameHistoryRepository = gameHistoryRepository;
        this.cardlockRepository = cardlockRepository;
        this.systemMessageService = systemMessageService;
    }

    /**
     * Beendet eine BDSM-Session ordentlich: History speichern, XP vergeben,
     * Gäste auf eigenem Gerät benachrichtigen, Daten aufräumen.
     */
    @Transactional
    public void spielAbschliessen(BdsmGameEntity entity) {
        LocalDateTime endTime = LocalDateTime.now();
        long durationMinutes = Duration.between(entity.getStartZeit(), endTime).toMinutes();

        GameHistoryEntity entry = new GameHistoryEntity();
        entry.setGameName("BDSM Game");
        entry.setGameType(GameType.BDSM);
        entry.setStartTime(entity.getStartZeit());
        entry.setEndTime(endTime);
        entry.setDurationMinutes(durationMinutes);
        entry.addParticipant(entity.getUserId(), GameRole.PLAYER);
        entity.getMitspieler().stream()
                .filter(m -> m.getUserId() != null)
                .forEach(m -> entry.addParticipant(m.getUserId(), GameRole.PLAYER));
        gameHistoryRepository.save(entry);

        int xp = (int) durationMinutes;
        userRepository.findById(entity.getUserId()).ifPresent(u -> {
            u.setBdsmXp(u.getBdsmXp() + xp);
            userRepository.save(u);
        });
        entity.getMitspieler().stream()
                .filter(m -> m.getUserId() != null)
                .forEach(m -> userRepository.findById(m.getUserId()).ifPresent(u -> {
                    u.setBdsmXp(u.getBdsmXp() + xp);
                    userRepository.save(u);
                }));

        // Gäste auf eigenem Gerät benachrichtigen
        String endNachricht = "Das BDSM-Spiel wurde erfolgreich beendet. Danke fürs Mitspielen! 🎉";
        entity.getMitspieler().stream()
                .filter(m -> m.isEigenesGeraet() && m.getUserId() != null)
                .forEach(m -> systemMessageService.send(entity.getUserId(), m.getUserId(),
                        endNachricht, "/userhome.html", MessageCause.GAME_STATE));

        bereinige(entity);
    }

    /**
     * Überführt eine BDSM-Session in ein neues Chastity-Lock (BDSM→Chastity-Transition).
     * History + XP werden wie beim normalen Spielabschluss vergeben.
     *
     * @return Das neu angelegte CardLockEntity
     * @throws IllegalArgumentException wenn Session oder Template nicht gefunden
     * @throws IllegalStateException    wenn Lockee bereits ein aktives Lock hat
     */
    @Transactional
    public CardLockEntity zuChastity(UUID sessionId, UUID templateLockId, UUID lockeeUserId, UUID keyholderUserId) {
        BdsmGameEntity entity = sessionRepository.findById(sessionId)
                .orElseThrow(() -> new IllegalArgumentException("Session nicht gefunden: " + sessionId));

        CardLockEntity template = cardlockRepository.findById(templateLockId)
                .orElseThrow(() -> new IllegalArgumentException("Template-Lock nicht gefunden: " + templateLockId));

        if (lockeeUserId != null
                && cardlockRepository.existsByLockeeAndStartTimeIsNotNullAndUnlockTimeIsNull(lockeeUserId)) {
            throw new IllegalStateException("Lockee hat bereits ein aktives Chastity-Lock");
        }

        LocalDateTime now = LocalDateTime.now();
        CardLockEntity newLock = new CardLockEntity();
        newLock.setName(template.getName());
        newLock.setLockee(lockeeUserId);
        newLock.setKeyholder(keyholderUserId);
        newLock.setInitialCards(template.getInitialCards());
        newLock.setPickEveryMinute(template.getPickEveryMinute());
        newLock.setAccumulatePicks(template.isAccumulatePicks());
        newLock.setShowRemainingCards(template.isShowRemainingCards());
        newLock.setLatestOpeningtime(template.getLatestOpeningtime());
        newLock.setHygineOpeningDurationMinutes(template.getHygineOpeningDurationMinutes());
        newLock.setHygineOpeningEveryMinites(template.getHygineOpeningEveryMinites());
        newLock.setTasks(template.getTasks());
        newLock.setRequiresVerification(template.isRequiresVerification());
        newLock.setTestLock(false);
        newLock.setTaskMode(template.getTaskMode());

        int codeLines = template.getUnlockCodeLength() != null ? template.getUnlockCodeLength() : 5;
        newLock.setUnlockCodeLength(codeLines);
        StringBuilder codeBuilder = new StringBuilder();
        java.util.Random rng = new java.util.Random();
        for (int i = 0; i < codeLines; i++) codeBuilder.append(rng.nextInt(10));
        newLock.setUnlockCode(codeBuilder.toString());

        newLock.setStartTime(now);
        newLock.setAvailableCards(template.getInitialCards() != null
                ? new ArrayList<>(template.getInitialCards()) : new ArrayList<>());
        newLock.setOpenPicks(0);
        if (template.getPickEveryMinute() != null) {
            newLock.setNextCardIn(now.plusMinutes(template.getPickEveryMinute()));
        }
        if (template.getHygineOpeningEveryMinites() != null) {
            newLock.setLastHygineOpening(now);
        }
        cardlockRepository.save(newLock);

        // Lockee benachrichtigen
        if (lockeeUserId != null) {
            userRepository.findById(keyholderUserId).ifPresent(keyholder ->
                    systemMessageService.send(keyholderUserId, lockeeUserId,
                            keyholder.getName() + " hat nach dem BDSM Game ein Chastity Lock auf dich gesetzt.",
                            "/games/chastity/activelock.html", MessageCause.GAME_STATE));
        }

        // Spielabschluss-Logik (History + XP + Cleanup)
        LocalDateTime endTime = LocalDateTime.now();
        long durationMinutes = Duration.between(entity.getStartZeit(), endTime).toMinutes();
        GameHistoryEntity entry = new GameHistoryEntity();
        entry.setGameName("BDSM Game");
        entry.setGameType(GameType.BDSM);
        entry.setStartTime(entity.getStartZeit());
        entry.setEndTime(endTime);
        entry.setDurationMinutes(durationMinutes);
        entry.addParticipant(entity.getUserId(), GameRole.PLAYER);
        entity.getMitspieler().stream()
                .filter(m -> m.getUserId() != null)
                .forEach(m -> entry.addParticipant(m.getUserId(), GameRole.PLAYER));
        gameHistoryRepository.save(entry);

        int xp = (int) durationMinutes;
        userRepository.findById(entity.getUserId()).ifPresent(u -> {
            u.setBdsmXp(u.getBdsmXp() + xp);
            userRepository.save(u);
        });
        entity.getMitspieler().stream()
                .filter(m -> m.getUserId() != null)
                .forEach(m -> userRepository.findById(m.getUserId()).ifPresent(u -> {
                    u.setBdsmXp(u.getBdsmXp() + xp);
                    userRepository.save(u);
                }));

        bereinige(entity);

        LOGGER.info("BDSM-Session {} in Chastity-Lock {} überführt (Lockee: {}, Keyholder: {})",
                sessionId, newLock.getLockId(), lockeeUserId, keyholderUserId);
        return newLock;
    }

    /** Löscht alle Session-Daten (Sperren, Mitspieler, Session selbst). */
    private void bereinige(BdsmGameEntity entity) {
        aktiveSperreRepository.deleteAll(entity.getAktiveSperren());
        mitspielerRepository.deleteAll(entity.getMitspieler());
        sessionRepository.delete(entity);
    }
}
