package io.netfoundry.billing.controller;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.UUID;
import org.springframework.data.domain.Page;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.netfoundry.billing.domain.contract.Contract;
import io.netfoundry.billing.domain.usage.submission.UsageSubmissionService;
import io.netfoundry.billing.domain.usage.submission.UsageSubmissionSummary;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequiredArgsConstructor
@Slf4j
public class MonthlyUsageSubmissionContractController {
  private final static String FIRST_DAY_OF_MONTH = "First day of month in epoch : {}";
  private final static String LAST_DAY_OF_MONTH = "last day of month in epoch : {}";

  private final UsageSubmissionService usageSubmissionService;


  @PostMapping(value = "/submit-monthly-usage02", produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<UsageSubmissionSummary> submitMonthlyUsage(@NotNull @RequestParam("planId") String planId,
      @NotNull @RequestParam("lastDayOfMonthEpochMs") Long lastDayOfMonthEpochMs, @RequestParam(value = "contractId", required = false) UUID contractId) {
    // authUtilService.validateEnterpriseSubscriptionReadAll();
    LocalDateTime lastDayOfMonth = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastDayOfMonthEpochMs), ZoneId.of("UTC"));
    Long firstDayOfMonthEpoch = lastDayOfMonth.withDayOfMonth(1).with(LocalTime.MIN).toInstant(ZoneOffset.UTC).toEpochMilli();
    Long lastDayOfMonthEpoch = lastDayOfMonth.with(LocalTime.MAX).toInstant(ZoneOffset.UTC).toEpochMilli();
    LocalDateTime firstDayOfMonthDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(firstDayOfMonthEpoch), ZoneOffset.UTC);
    LocalDateTime lastDayOfMonthDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastDayOfMonthEpoch), ZoneOffset.UTC);
    log.info(FIRST_DAY_OF_MONTH, firstDayOfMonthDateTime);
    log.info(LAST_DAY_OF_MONTH, lastDayOfMonthDateTime);
    Page<Contract> contracts = null;

    log.info("=== Starting monthly usage submission ===");
    log.info("Plan: {}, Date range: {} to {}", planId, firstDayOfMonthDateTime, lastDayOfMonthDateTime);

    UsageSubmissionSummary usageSubmissionSummary;

    if (contractId != null) {
      log.info("Processing single account: {}", contractId);
      usageSubmissionSummary = usageSubmissionService.processContract(contractId, firstDayOfMonthDateTime, lastDayOfMonthDateTime);
    } else {
      log.info("Processing all accounts in batches of 5");
      usageSubmissionSummary = usageSubmissionService.processAllContractsPaginated(planId, firstDayOfMonthDateTime, lastDayOfMonthDateTime, 5);
    }

    log.info("=== Monthly usage submission completed ===");
    log.info("Summary: {} successful, {} failed, {} total records submitted", usageSubmissionSummary.getSuccessCount(), usageSubmissionSummary.getFailureCount(),
        usageSubmissionSummary.getTotalRecordsSubmitted());
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    String writeValueAsString = "";
    try {
      writeValueAsString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(usageSubmissionSummary);
    } catch (JsonProcessingException e) {
      e.printStackTrace();
    }
    log.info("=== Monthly usage submission response payload ==={}", writeValueAsString);

    return ResponseEntity.ok(usageSubmissionSummary);
  }

}
