package ru.soune.nocopy.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.tarriff.TariffDTO;
import ru.soune.nocopy.dto.tarriff.TariffRequest;
import ru.soune.nocopy.dto.tarriff.TariffResponse;
import ru.soune.nocopy.entity.tarif.TariffTimeTerm;
import ru.soune.nocopy.entity.user.AuthToken;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.service.tariff.TariffService;

import java.util.List;
import java.util.Map;

@Component
@Slf4j
@RequiredArgsConstructor
public class TariffHandler implements RequestHandler {

    private final ObjectMapper objectMapper;

    private final TariffService tariffService;

    private final AuthTokenRepository authTokenRepository;

    @Override
    public BaseResponse handle(BaseRequest request) throws Exception {
        try {
            TariffRequest tariffRequest = objectMapper.convertValue(request.getMessageBody(), TariffRequest.class);
            String action = tariffRequest.getAction();

            switch (action) {
                case "add":
                    return handleAddTariff(request, tariffRequest);
                case "remove":
                    return handleRemoveTariff(request, tariffRequest);
                case "update":
                    return handleUpdateTariff(request, tariffRequest);
                case "get" :
                    return handleGetTariffs(request, tariffRequest);
                case "tariffs_by_type" :
                    return handleGetTariffsByType(request, tariffRequest);
            }

        } catch (Exception e) {
            log.error("Error add tariff", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Error processing request: " + e.getMessage(),
                    null);
        }

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(), null);
    }

    private BaseResponse handleAddTariff(BaseRequest request, TariffRequest tariffRequest) {
        tariffService.addTariff(tariffRequest.getName(), tariffRequest.getPrice(), tariffRequest.getType(),
                tariffRequest.getTokens(), tariffRequest.getDiskSize(), tariffRequest.getMaxUsers(),
                tariffRequest.getMaxFilesCount(), tariffRequest.getTariffTerm());

        TariffResponse tariffResponse = TariffResponse.builder()
                .tariffName(tariffRequest.getName())
                .tariffType(tariffRequest.getType())
                .build();

        return new BaseResponse(request.getMsgId(), MessageCode.TARIFF_IS_ADD.getCode(),
                MessageCode.TARIFF_IS_ADD.getDescription(),
                tariffResponse);
    }

    private BaseResponse handleRemoveTariff(BaseRequest request, TariffRequest tariffRequest) {
        TariffDTO tariff = tariffService.getTariffById(tariffRequest.getId());

        if (tariff == null) {
            return new BaseResponse(request.getMsgId(), MessageCode.TARIFF_IS_NOT_FOUND.getCode(),
                    MessageCode.TARIFF_IS_NOT_FOUND.getDescription(),
                    Map.of("id", tariffRequest.getId()));
        }

        TariffResponse tariffResponse = TariffResponse.builder()
                .tariffName(tariff.getName())
                .tariffType(tariff.getType())
                .build();

        tariffService.deleteTariff(tariffRequest.getId());

        return new BaseResponse(request.getMsgId(), MessageCode.TARIFF_IS_DELETED.getCode(),
                MessageCode.TARIFF_IS_DELETED.getDescription(),
                tariffResponse);
    }

    private BaseResponse handleUpdateTariff(BaseRequest request, TariffRequest tariffRequest) {
        TariffDTO tariff = tariffService.getTariffById(tariffRequest.getId());

        if (tariff == null) {
            return new BaseResponse(request.getMsgId(), MessageCode.TARIFF_IS_NOT_FOUND.getCode(),
                    MessageCode.TARIFF_IS_NOT_FOUND.getDescription(),
                    Map.of("id", tariffRequest.getId()));
        }

        TariffDTO tariffDTO = tariffService.updateTariff(tariffRequest.getId(), tariff);

        TariffResponse tariffResponse = TariffResponse.builder()
                .tariffName(tariffDTO.getName())
                .tariffType(tariffDTO.getType())
                .build();


        return new BaseResponse(request.getMsgId(), MessageCode.TARIFF_IS_UPDATED.getCode(),
                MessageCode.TARIFF_IS_UPDATED.getDescription(),
                tariffResponse);
    }

    private BaseResponse handleGetTariffs(BaseRequest request, TariffRequest tariffRequest) {
        AuthToken authToken = authTokenRepository.findByToken(tariffRequest.getUserToken()).orElseThrow();
        User user = authToken.getUser();

        if (tariffRequest.getTariffTerm() == null || !TariffTimeTerm.validTerms().contains(
                tariffRequest.getTariffTerm())) {
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Not valid tariff_term",
                    Map.of("Valid term", TariffTimeTerm.validTerms()));
        }

        List<TariffDTO> allTariffs = tariffService.getTariffByAccountTypeAndTariffTerm(user,
                TariffTimeTerm.valueOf(tariffRequest.getTariffTerm().toUpperCase()));

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(),
                Map.of("tariffs", allTariffs));
    }

    private BaseResponse handleGetTariffsByType(BaseRequest request, TariffRequest tariffRequest) {
        List<TariffDTO> allTariffs = tariffService.getTariffByType(tariffRequest.getType());

        return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(),
                Map.of("token_tariffs", allTariffs));
    }
}
