/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.epam.dlab.billing.azure;

import com.epam.dlab.MongoKeyWords;
import com.epam.dlab.billing.azure.config.AzureAuthFile;
import com.epam.dlab.billing.azure.config.BillingConfigurationAzure;
import com.epam.dlab.billing.azure.model.AzureDailyResourceInvoice;
import com.epam.dlab.billing.azure.model.BillingPeriod;
import com.epam.dlab.dto.billing.BillingData;
import com.epam.dlab.exceptions.DlabException;
import com.epam.dlab.util.mongo.modules.IsoDateModule;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CalculateBillingServiceImpl implements CalculateBillingService {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z");
    private static final String SCHEDULER_ID = "azureBillingScheduler";
    private final BillingConfigurationAzure billingConfigurationAzure;
    private final MongoDbBillingClient mongoDbBillingClient;
    private ObjectMapper objectMapper;

    @Autowired
    public CalculateBillingServiceImpl(BillingConfigurationAzure configuration) throws IOException {
        billingConfigurationAzure = configuration;
        objectMapper = new ObjectMapper().registerModule(new IsoDateModule());
        Path path = Paths.get(billingConfigurationAzure.getAuthenticationFile());

        if (path.toFile().exists()) {
            log.info("Read and override configs using auth file");
            try {
                AzureAuthFile azureAuthFile = new ObjectMapper().readValue(path.toFile(), AzureAuthFile.class);
                this.billingConfigurationAzure.setClientId(azureAuthFile.getClientId());
                this.billingConfigurationAzure.setClientSecret(azureAuthFile.getClientSecret());
                this.billingConfigurationAzure.setTenantId(azureAuthFile.getTenantId());
                this.billingConfigurationAzure.setSubscriptionId(azureAuthFile.getSubscriptionId());
            } catch (IOException e) {
                log.error("Cannot read configuration file", e);
                throw e;
            }
            log.info("Configs from auth file are used");
        } else {
            log.info("Configs from yml file are used");
        }

        this.mongoDbBillingClient = new MongoDbBillingClient
                (billingConfigurationAzure.getAggregationOutputMongoDataSource().getHost(),
                        billingConfigurationAzure.getAggregationOutputMongoDataSource().getPort(),
                        billingConfigurationAzure.getAggregationOutputMongoDataSource().getDatabase(),
                        billingConfigurationAzure.getAggregationOutputMongoDataSource().getUsername(),
                        billingConfigurationAzure.getAggregationOutputMongoDataSource().getPassword());
    }

    @Override
    public List<BillingData> getBillingData() {
        try {
            BillingPeriod billingPeriod = getBillingPeriod();
            DateTime currentTime = new DateTime().withZone(DateTimeZone.UTC);
            if (billingPeriod == null) {
                saveBillingPeriod(initialSchedulerInfo(currentTime));
            } else {
                log.info("Billing period from db is {}", billingPeriod);

                if (shouldTriggerJobByTime(currentTime, billingPeriod)) {
                    List<BillingData> billingData = getBillingData(billingPeriod);
                    boolean hasNew = !billingData.isEmpty();
                    updateBillingPeriod(billingPeriod, currentTime, hasNew);
                    return billingData;
                }
            }
        } catch (RuntimeException e) {
            log.error("Cannot update billing information", e);
        }
        return Collections.emptyList();
    }

    private BillingPeriod initialSchedulerInfo(DateTime currentTime) {

        BillingPeriod initialBillingPeriod = new BillingPeriod();
        initialBillingPeriod.setFrom(currentTime.minusDays(2).toDateMidnight().toDate());
        initialBillingPeriod.setTo(currentTime.toDateMidnight().toDate());

        log.info("Initial scheduler info {}", initialBillingPeriod);

        return initialBillingPeriod;

    }

    private boolean shouldTriggerJobByTime(DateTime currentTime, BillingPeriod billingPeriod) {

        DateTime dateTimeToFromBillingPeriod = new DateTime(billingPeriod.getTo()).withZone(DateTimeZone.UTC);

        log.info("Comparing current time[{}, {}] and from scheduler info [{}, {}]", currentTime,
                currentTime.toDateMidnight(),
                dateTimeToFromBillingPeriod, dateTimeToFromBillingPeriod.toDateMidnight());

        if (currentTime.toDateMidnight().isAfter(dateTimeToFromBillingPeriod.toDateMidnight())
                || currentTime.toDateMidnight().isEqual(dateTimeToFromBillingPeriod.toDateMidnight())) {
            log.info("Should trigger the job by time");
            return true;
        }

        log.info("Should not trigger the job by time");
        return false;
    }

    private List<BillingData> getBillingData(BillingPeriod billingPeriod) {
        AzureInvoiceCalculationService azureInvoiceCalculationService
                = new AzureInvoiceCalculationService(billingConfigurationAzure);

        List<AzureDailyResourceInvoice> dailyInvoices = azureInvoiceCalculationService.generateInvoiceData(
                DATE_TIME_FORMATTER.print(new DateTime(billingPeriod.getFrom()).withZone(DateTimeZone.UTC)),
                DATE_TIME_FORMATTER.print(new DateTime(billingPeriod.getTo()).withZone(DateTimeZone.UTC)));

        if (!dailyInvoices.isEmpty()) {
            return dailyInvoices
                    .stream()
                    .map(this::toBillingData)
                    .collect(Collectors.toList());
        } else {
            log.warn("Daily invoices is empty for period {}", billingPeriod);
            return Collections.emptyList();
        }
    }

    private void updateBillingPeriod(BillingPeriod billingPeriod, DateTime currentTime, boolean updates) {

        try {
            mongoDbBillingClient.getDatabase().getCollection(MongoKeyWords.AZURE_BILLING_SCHEDULER_HISTORY).insertOne(
                    Document.parse(objectMapper.writeValueAsString(billingPeriod)).append("updates", updates));
            log.debug("History of billing periods is updated with {}",
                    objectMapper.writeValueAsString(billingPeriod));
        } catch (JsonProcessingException e) {
            log.error("Cannot update history of billing periods", e);

        }

        billingPeriod.setFrom(billingPeriod.getTo());

        if (new DateTime(billingPeriod.getFrom()).withZone(DateTimeZone.UTC).toDateMidnight()
                .isEqual(currentTime.toDateMidnight())) {

            log.info("Setting billing to one day later");
            billingPeriod.setTo(currentTime.plusDays(1).toDateMidnight().toDate());

        } else {
            billingPeriod.setTo(currentTime.toDateMidnight().toDate());
        }

        saveBillingPeriod(billingPeriod);
    }

    private boolean saveBillingPeriod(BillingPeriod billingPeriod) {
        log.debug("Saving billing period {}", billingPeriod);

        try {
            UpdateResult updateResult = mongoDbBillingClient.getDatabase().getCollection(MongoKeyWords.AZURE_BILLING_SCHEDULER)
                    .updateMany(Filters.eq(MongoKeyWords.MONGO_ID, SCHEDULER_ID),
                            new BasicDBObject("$set",
                                    Document.parse(objectMapper.writeValueAsString(billingPeriod))
                                            .append(MongoKeyWords.MONGO_ID, SCHEDULER_ID))
                            , new UpdateOptions().upsert(true)
                    );

            log.debug("Billing period save operation result is {}", updateResult);
            return true;
        } catch (JsonProcessingException e) {
            log.error("Cannot save billing period", e);
        }

        return false;
    }

    private BillingPeriod getBillingPeriod() {
        log.debug("Get billing period");

        try {
            Document document = mongoDbBillingClient.getDatabase().getCollection(MongoKeyWords.AZURE_BILLING_SCHEDULER)
                    .find(Filters.eq(MongoKeyWords.MONGO_ID, SCHEDULER_ID)).first();

            log.debug("Retrieved billing period document {}", document);
            if (document != null) {
                return objectMapper.readValue(document.toJson(), BillingPeriod.class);
            }

            return null;

        } catch (IOException e) {
            log.error("Cannot save billing period", e);
            throw new DlabException("Cannot parse string", e);
        }
    }

    private BillingData toBillingData(AzureDailyResourceInvoice billingData) {
        return BillingData.builder()
                .tag(billingData.getDlabId().toLowerCase())
                .usageDateFrom(Optional.ofNullable(billingData.getUsageStartDate()).map(LocalDate::parse).orElse(null))
                .usageDateTo(Optional.ofNullable(billingData.getUsageEndDate()).map(LocalDate::parse).orElse(null))
                .usageDate(billingData.getDay())
                .product(billingData.getMeterCategory())
                .cost(billingData.getCost())
                .currency(billingData.getCurrencyCode())
                .build();
    }
}
