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.TariffInfoDTO;
import ru.soune.nocopy.dto.tarriff.TariffInfoRequest;
import ru.soune.nocopy.dto.tarriff.TariffInfoResponse;
import ru.soune.nocopy.entity.tarif.Tariff;
import ru.soune.nocopy.entity.tarif.TariffStatus;
import ru.soune.nocopy.entity.tarif.TariffTimeTerm;
import ru.soune.nocopy.entity.tarif.TariffType;
import ru.soune.nocopy.repository.TariffRepository;
import ru.soune.nocopy.service.tariff.TariffInfoService;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

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

    private final ObjectMapper objectMapper;
    
    private final TariffInfoService tariffInfoService;

    private final TariffRepository tariffRepository;

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

            switch (action) {
                case "create":
                    return handleCreateTariffInfo(request, tariffInfoRequest);
                case "create_by_type":
                    return handleCreateTariffInfoByType(request, tariffInfoRequest);
                case "update":
                    return handleUpdateTariffInfo(request, tariffInfoRequest);
                case "delete":
                    return handleDeleteTariffInfo(request, tariffInfoRequest);
                case "get_by_id":
                    return handleGetTariffInfoById(request, tariffInfoRequest);
                case "get_all":
                    return handleGetAllTariffInfos(request, tariffInfoRequest);
                default:
                    return new BaseResponse(
                            request.getMsgId(),
                            MessageCode.ERROR_TARIFF_INFO.getCode(),
                            "Unknown action: " + action,
                            null
                    );
            }
        } catch (Exception e) {
            log.error("Error processing tariff info request", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Error processing request: " + e.getMessage(),
                    null
            );
        }
    }

    private BaseResponse handleCreateTariffInfo(BaseRequest request, TariffInfoRequest tariffInfoRequest) {
        try {
            Long tariffId = tariffInfoRequest.getTariffId();
            Tariff tariff= tariffRepository.findById(tariffId).orElseThrow();
            TariffTimeTerm tariffTerm = tariff.getTariffTerm();
            LocalDateTime endDateTime = LocalDateTime.now().plusDays(tariffTerm.getDays());

            TariffInfoDTO tariffInfoDTO = new TariffInfoDTO(null,
                    tariffInfoRequest.getStatus() != null ? tariffInfoRequest.getStatus() : TariffStatus.ACTIVE.name(),
                    tariffInfoRequest.getStartTariff() != null ? tariffInfoRequest.getStartTariff() : LocalDateTime.now(),
                    endDateTime, tariffInfoRequest.getTariffId(), tariff.getName(), tariff.getTokens(),
                    tariff.getDiskSize(), 0L, 0, tariff.getMaxFilesCount());

            TariffInfoDTO createdTariffInfo = tariffInfoService.createTariffInfo(tariffInfoDTO);

            TariffInfoResponse response = TariffInfoResponse.builder()
                    .id(createdTariffInfo.getId())
                    .status(createdTariffInfo.getStatus())
                    .startTariff(createdTariffInfo.getStartTariff())
                    .endTariff(createdTariffInfo.getEndTariff())
                    .tariffId(createdTariffInfo.getTariffId())
                    .tariffName(createdTariffInfo.getTariffName())
                    .build();

            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Tariff info created successfully",
                    response
            );
        } catch (Exception e) {
            log.error("Error creating tariff info", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Failed to create tariff info: " + e.getMessage(),
                    null
            );
        }
    }

    private BaseResponse handleCreateTariffInfoByType(BaseRequest request, TariffInfoRequest tariffInfoRequest) {
        try {
            if (tariffInfoRequest.getTariffType() == null) {
                return new BaseResponse(
                        request.getMsgId(),
                        MessageCode.ERROR_TARIFF_INFO.getCode(),
                        "Tariff type is required for create_by_type action",
                        null
                );
            }

            tariffInfoService.createTariffInfo(
                    TariffType.valueOf(tariffInfoRequest.getTariffType().toUpperCase())
            );

            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Tariff info created successfully by type: " + tariffInfoRequest.getTariffType(),
                    null
            );
        } catch (IllegalArgumentException e) {
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Invalid tariff type: " + tariffInfoRequest.getTariffType(),
                    null
            );
        } catch (Exception e) {
            log.error("Error creating tariff info by type", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Failed to create tariff info by type: " + e.getMessage(),
                    null
            );
        }
    }

    private BaseResponse handleUpdateTariffInfo(BaseRequest request, TariffInfoRequest tariffInfoRequest) {
        try {
            if (tariffInfoRequest.getId() == null) {
                return new BaseResponse(
                        request.getMsgId(),
                        MessageCode.ERROR_TARIFF_INFO.getCode(),
                        "Tariff info ID is required for update",
                        null
                );
            }
            Long tariffId = tariffInfoRequest.getTariffId();
            Tariff tariff = tariffRepository.findById(tariffId).orElseThrow();

            TariffInfoDTO tariffInfoDTO = new TariffInfoDTO(
                    tariffInfoRequest.getId(),
                    tariffInfoRequest.getStatus(),
                    tariffInfoRequest.getStartTariff(),
                    tariffInfoRequest.getEndTariff(),
                    tariffInfoRequest.getTariffId(),
                    tariff.getName(), null, tariff.getDiskSize(), null, null, tariff.getMaxFilesCount()
            );

            TariffInfoDTO updatedTariffInfo = tariffInfoService.updateTariffInfo(
                    tariffInfoRequest.getId(),
                    tariffInfoDTO
            );

            TariffInfoResponse response = TariffInfoResponse.builder()
                    .id(updatedTariffInfo.getId())
                    .status(updatedTariffInfo.getStatus())
                    .startTariff(updatedTariffInfo.getStartTariff())
                    .endTariff(updatedTariffInfo.getEndTariff())
                    .tariffId(updatedTariffInfo.getTariffId())
                    .tariffName(updatedTariffInfo.getTariffName())
                    .build();

            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Tariff info updated successfully",
                    response
            );
        } catch (Exception e) {
            log.error("Error updating tariff info", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Failed to update tariff info: " + e.getMessage(),
                    null
            );
        }
    }

    private BaseResponse handleDeleteTariffInfo(BaseRequest request, TariffInfoRequest tariffInfoRequest) {
        try {
            if (tariffInfoRequest.getId() == null) {
                return new BaseResponse(
                        request.getMsgId(),
                        MessageCode.ERROR_TARIFF_INFO.getCode(),
                        "Tariff info ID is required for delete",
                        null
                );
            }

            TariffInfoDTO tariffInfo = tariffInfoService.getTariffInfoById(tariffInfoRequest.getId());

            tariffInfoService.deleteTariffInfo(tariffInfoRequest.getId());

            TariffInfoResponse response = TariffInfoResponse.builder()
                    .id(tariffInfo.getId())
                    .status(tariffInfo.getStatus())
                    .startTariff(tariffInfo.getStartTariff())
                    .endTariff(tariffInfo.getEndTariff())
                    .tariffId(tariffInfo.getTariffId())
                    .tariffName(tariffInfo.getTariffName())
                    .build();

            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Tariff info deleted successfully",
                    response
            );
        } catch (Exception e) {
            log.error("Error deleting tariff info", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Failed to delete tariff info: " + e.getMessage(),
                    null
            );
        }
    }

    private BaseResponse handleGetTariffInfoById(BaseRequest request, TariffInfoRequest tariffInfoRequest) {
        try {
            if (tariffInfoRequest.getId() == null) {
                return new BaseResponse(
                        request.getMsgId(),
                        MessageCode.ERROR_TARIFF_INFO.getCode(),
                        "Tariff info ID is required",
                        null
                );
            }

            TariffInfoDTO tariffInfo = tariffInfoService.getTariffInfoById(tariffInfoRequest.getId());

            TariffInfoResponse response = TariffInfoResponse.builder()
                    .id(tariffInfo.getId())
                    .status(tariffInfo.getStatus())
                    .startTariff(tariffInfo.getStartTariff())
                    .endTariff(tariffInfo.getEndTariff())
                    .tariffId(tariffInfo.getTariffId())
                    .tariffName(tariffInfo.getTariffName())
                    .build();

            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Tariff info retrieved successfully",
                    response
            );
        } catch (Exception e) {
            log.error("Error getting tariff info by ID", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Failed to get tariff info: " + e.getMessage(),
                    null
            );
        }
    }

    private BaseResponse handleGetAllTariffInfos(BaseRequest request, TariffInfoRequest tariffInfoRequest) {
        try {
            List<TariffInfoDTO> allTariffInfos = tariffInfoService.getAllTariffInfos();

            List<TariffInfoResponse> responses = allTariffInfos.stream()
                    .map(info -> TariffInfoResponse.builder()
                            .id(info.getId())
                            .status(info.getStatus())
                            .startTariff(info.getStartTariff())
                            .endTariff(info.getEndTariff())
                            .tariffId(info.getTariffId())
                            .tariffName(info.getTariffName())
                            .build())
                    .collect(Collectors.toList());

            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Tariff infos retrieved successfully",
                    Map.of("tariff_infos", responses, "count", responses.size())
            );
        } catch (Exception e) {
            log.error("Error getting all tariff infos", e);
            return new BaseResponse(
                    request.getMsgId(),
                    MessageCode.ERROR_TARIFF_INFO.getCode(),
                    "Failed to get tariff infos: " + e.getMessage(),
                    null
            );
        }
    }
}
