package cz.muni.fi.pa165.statistics.statistics;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.UUID;

import org.apache.http.entity.StringEntity;
import org.springframework.transaction.annotation.Transactional;

@Service
public class StatisticService {

    private final StatisticRepository repository;

    @Autowired
    public StatisticService(StatisticRepository repository){
        this.repository = repository;
    }

    @Transactional
    public UserStatistic createStatistic(UserStatistic userStatistic) throws IOException {
        UserStatistic statistic = repository.findUserHouseDateStatistics(userStatistic.getUserId(), userStatistic.getHouseId(), userStatistic.getMonthNum(), userStatistic.getYearNum());

        if (statistic == null){
            userStatistic.setId(UUID.randomUUID().toString());
            userStatistic.setName(String.format("User%s_house%s_%d/%d.",
                    userStatistic.getUserEmail(),
                    userStatistic.getHouseId(),
                    userStatistic.getMonthNum(),
                    userStatistic.getYearNum()));
            userStatistic.setMonthlyConsumption(generateStatistic(userStatistic));
            repository.save(userStatistic);
            return userStatistic;
        }

        return statistic;
    }

    @Transactional
    public List<UserStatistic> findAllUserStatistics(String userId)
    {
        return repository.findAllByUser(userId);
    }

    @Transactional
    public List<UserStatistic> findAllUserStatisticsByHouse(String userId, String houseId)
    {
        return repository.findAllByUserAndHouse(userId, houseId);
    }

    public double generateStatistic(UserStatistic userStatistic) throws IOException {

        Instant startDateTime = GetFirstDayOfMonth(userStatistic.getYearNum(), userStatistic.getMonthNum());
        Instant lastDateTime = GetLastDayOfMonth(userStatistic.getYearNum(), userStatistic.getMonthNum());

        String payload = String.format("""
                {
                    "userId": "%s",
                    "houseId": "%s",
                    "startTime": "%s",
                    "endTime": "%s"
                }
                """, userStatistic.getUserId(),
                userStatistic.getHouseId(),
                startDateTime,
                lastDateTime);
        StringEntity entity = new StringEntity(payload,
                ContentType.APPLICATION_JSON);

        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost request = new HttpPost("http://localhost:8080/api/user/statistics");
        request.setEntity(entity);
        request.setHeader("Content-Type", "application/json");

        HttpResponse response = httpClient.execute(request);

        // TODO: assert response equals 200 and write message if not

        String result = EntityUtils.toString(response.getEntity());

        return result.isEmpty() ? 0
                : Double.valueOf(result);
    }

    private Instant GetLastDayOfMonth(int year, int month){
        LocalDateTime date = LocalDateTime.of(year,
                month,1,0,0,0,0);
        LocalDateTime date_pom = date.plusMonths(1);
        LocalDateTime lastDateOfMonth = date_pom.minusDays(1);

        return LocalDateTime.of(year,
                month,
                lastDateOfMonth.getDayOfMonth(),
                23,59,59,999999).atZone(ZoneId.systemDefault()).toInstant();
    }

    private Instant GetFirstDayOfMonth(int year, int month){
        return LocalDateTime.of(year,
                month,1,0,0,0,0).atZone(ZoneId.systemDefault()).toInstant();
    }
}
