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.violation.ViolationStatisticsRequest;
import ru.soune.nocopy.dto.violation.ViolationStatisticsResponse;
import ru.soune.nocopy.entity.user.AuthToken;
import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.service.violation.ViolationService;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Optional;

@Slf4j
@Component
@RequiredArgsConstructor
public class ViolationStatisticsHandler implements RequestHandler {
    private final ObjectMapper objectMapper;

    private final ViolationService violationService;

    private final AuthTokenRepository authTokenRepository;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public BaseResponse handle(BaseRequest request) throws Exception {
        ViolationStatisticsRequest statRequest = objectMapper.convertValue(request.getMessageBody(),
                ViolationStatisticsRequest.class);

        validateRequest(statRequest);

        LocalDateTime startDate = null;
        LocalDateTime endDate = null;

        if (statRequest.getStartDate() != null && statRequest.getEndDate() != null) {
            startDate = parseDate(statRequest.getStartDate());
            endDate = parseDate(statRequest.getEndDate());

            if (endDate != null && !statRequest.getEndDate().contains(" ")) {
                endDate = endDate.withHour(23).withMinute(59).withSecond(59);
            }
        }

        Optional<AuthToken> tokenOptional = authTokenRepository.findByToken(statRequest.getToken());

        if (tokenOptional.isEmpty()) {
            throw new IllegalArgumentException("User token is required");
        }

        Long userId = tokenOptional.orElseThrow().getUser().getId();

        ViolationStatisticsResponse statistics = violationService.getViolationStatistics(
                userId,
                statRequest.getFileId(),
                startDate,
                endDate);

        return BaseResponse.builder()
                .msgId(request.getMsgId())
                .messageBody(statistics)
                .build();
    }

    private void validateRequest(ViolationStatisticsRequest request) {
        if (request.getToken() == null) {
            throw new IllegalArgumentException("Token is required");
        }
    }

    private LocalDateTime parseDate(String dateStr) {
        try {
            return LocalDateTime.parse(dateStr, DATE_FORMATTER);
        } catch (DateTimeParseException e) {
            try {
                return LocalDateTime.parse(dateStr + " 00:00:00", DATE_FORMATTER);
            } catch (DateTimeParseException ex) {
                log.error("Error parsing date: {}", dateStr, ex);
                return null;
            }
        }
    }
}
