package com.alttd.altitudeweb.controllers.history;

import com.alttd.altitudeweb.api.HistoryApi;
import com.alttd.altitudeweb.setup.Connection;
import com.alttd.altitudeweb.database.Databases;
import com.alttd.altitudeweb.database.litebans.*;
import com.alttd.altitudeweb.model.PunishmentHistoryDto;
import com.alttd.altitudeweb.model.PunishmentHistoryInnerDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@Slf4j
@RestController
public class HistoryApiController implements HistoryApi {

    @Override
    public ResponseEntity<PunishmentHistoryDto> getHistoryForAll(String userType, String type, Integer page) {
        return getHistoryForUsers(userType, type, "", page);
    }

    @Override
    public ResponseEntity<PunishmentHistoryDto> getHistoryForUsers(String userType, String type, String user, Integer page) {
        UserType userTypeEnum = UserType.getUserType(userType);
        HistoryType historyTypeEnum = HistoryType.getHistoryType(type);
        PunishmentHistoryDto punishmentHistory = new PunishmentHistoryDto();
        CompletableFuture<List<HistoryRecord>> historyRecords = new CompletableFuture<>();

        Connection.getConnection(Databases.LITE_BANS)
                .runQuery(sqlSession -> {
                    log.debug("Loading history through name for type {}", type);
                    try {
                        List<HistoryRecord> temp = sqlSession.getMapper(NameHistoryMapper.class)
                                .getRecent(historyTypeEnum, userTypeEnum, user, page);
                        historyRecords.complete(temp);
                    } catch (Exception e) {
                        log.error("Failed to load history through name for type {}", type, e);
                        historyRecords.completeExceptionally(e);
                    }
                });
        return mapPunishmentHistory(punishmentHistory, historyRecords);
    }

    @Override
    public ResponseEntity<PunishmentHistoryDto> getHistoryForUuid(String userType, String type, String uuid, Integer page) {
        UserType userTypeEnum = UserType.getUserType(userType);
        HistoryType historyTypeEnum = HistoryType.getHistoryType(type);
        PunishmentHistoryDto punishmentHistory = new PunishmentHistoryDto();
        CompletableFuture<List<HistoryRecord>> historyRecords = new CompletableFuture<>();

        Connection.getConnection(Databases.LITE_BANS)
                .runQuery(sqlSession -> {
                    log.debug("Loading history through uuid for type {}", type);
                    try {
                        List<HistoryRecord> temp = sqlSession.getMapper(UUIDHistoryMapper.class)
                                .getRecent(historyTypeEnum, userTypeEnum, UUID.fromString(uuid), page);
                        historyRecords.complete(temp);
                    } catch (Exception e) {
                        log.error("Failed to load history through uuid for type {}", type, e);
                        historyRecords.completeExceptionally(e);
                    }
                });
        return mapPunishmentHistory(punishmentHistory, historyRecords);
    }

    @Override
    public ResponseEntity<List<String>> getUserNames(String userType, String type) {
        UserType userTypeEnum = UserType.getUserType(userType);
        HistoryType historyTypeEnum = HistoryType.getHistoryType(type);
        CompletableFuture<List<String>> playerGroupFuture = new CompletableFuture<>();
        
        Connection.getConnection(Databases.LITE_BANS)
                .runQuery(sqlSession -> {
                    log.debug("Loading user names for type {}", type);
                    try {
                        List<String> temp = sqlSession.getMapper(RecentNamesMapper.class)
                                .getRecent(historyTypeEnum, userTypeEnum);
                        playerGroupFuture.complete(temp);
                    } catch (Exception e) {
                        log.error("Failed to load user names for type {}", type, e);
                        playerGroupFuture.completeExceptionally(e);
                    }
                });
        return ResponseEntity.ok().body(playerGroupFuture.join());
    }

    private ResponseEntity<PunishmentHistoryDto> mapPunishmentHistory(PunishmentHistoryDto punishmentHistory, CompletableFuture<List<HistoryRecord>> historyRecords) {
        historyRecords.join().forEach(historyRecord -> {
            PunishmentHistoryInnerDto innerDto = new PunishmentHistoryInnerDto()
                    .uuid(historyRecord.getUuid())
                    .username(historyRecord.getPunishedName())
                    .reason(historyRecord.getReason())
                    .punishmentUserUuid(historyRecord.getBannedByUuid())
                    .punishmentUser(historyRecord.getBannedByName())
                    .removedBy(historyRecord.getRemovedByName())
                    .punishmentTime(historyRecord.getTime())
                    .expiryTime(historyRecord.getUntil())
                    .removedReason(historyRecord.getRemovedByReason())
                    .type(historyRecord.getType());
            punishmentHistory.add(innerDto);
        });
        return ResponseEntity.ok().body(punishmentHistory);
    }
}
