package com.airlock.iam.admin.application.service.analytics;

import com.airlock.iam.admin.application.service.license.LicenseService;
import com.airlock.iam.admin.application.service.license.UsageDataService;
import com.airlock.iam.admin.domain.model.analytics.Analytics;
import com.airlock.iam.admin.domain.model.analytics.LicenseAnalytics;
import com.airlock.iam.admin.domain.model.analytics.StructuredLicenseAnalytics;
import com.airlock.iam.admin.domain.model.analytics.UsageAnalytics;
import com.airlock.iam.base.misc.time.TimeProvider;
import com.airlock.iam.license.domain.model.date.LicenseDate;
import com.airlock.iam.license.domain.model.mac.Mac48Address;
import com.airlock.iam.system.property.IamSystemProperties;
import com.airlock.iam.system.version.CurrentVersion;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;
import java.util.stream.Collectors;

public class AnalyticsService {
   private final Provider<LicenseService> licenseService;
   private final Provider<AnalyticsReportingLevel> reportingLevel;
   private final Provider<TimeProvider> time;
   private final Provider<UsageDataService> usageDataService;

   @Inject
   public AnalyticsService(
      Provider<LicenseService> licenseService,
      Provider<AnalyticsReportingLevel> reportingLevel,
      Provider<TimeProvider> time,
      Provider<UsageDataService> usageDataService
   ) {
      this.licenseService = licenseService;
      this.reportingLevel = reportingLevel;
      this.time = time;
      this.usageDataService = usageDataService;
   }

   public Analytics getAnalytics() {
      return Analytics.builder()
         .iamVersion(CurrentVersion.getDisplayString())
         .license(
            LicenseAnalytics.builder()
               .structured(this.structuredLicenseData())
               .licenseText(((LicenseService)this.licenseService.get()).getActiveLicenseText())
               .build()
         )
         .userCount(((LicenseService)this.licenseService.get()).getCurrentUsers().orElse(0))
         .usageAnalyticsEnabled(((AnalyticsReportingLevel)this.reportingLevel.get()).isUsageAnalyticsEnabled())
         .runningInDocker(IamSystemProperties.isRunningInDocker())
         .createdAt(((TimeProvider)this.time.get()).getCurrentInstant())
         .usageData(this.getUsageAnalyticsIfEnabled())
         .build();
   }

   private Optional<UsageAnalytics> getUsageAnalyticsIfEnabled() {
      return ((AnalyticsReportingLevel)this.reportingLevel.get()).isUsageAnalyticsEnabled()
         ? Optional.of(((UsageDataService)this.usageDataService.get()).retrieveUsageAnalytics())
         : Optional.empty();
   }

   private Optional<StructuredLicenseAnalytics> structuredLicenseData() {
      return ((LicenseService)this.licenseService.get())
         .getActiveLicense()
         .map(
            license -> StructuredLicenseAnalytics.builder()
               .owner(Optional.ofNullable(license.getOwner()))
               .issuedOn(date(license.getIssueDate()))
               .validFrom(date(license.getValidFromDate()))
               .validUntil(date(license.getValidUntilDate()))
               .environment(Optional.ofNullable(license.getEnvironment()))
               .licensedUsers(license.getNrOfLicensedUsers())
               .licensedInstances(license.getNrOfLicensedInstances())
               .licensedTags(license.getLicensedModules())
               .bundles(license.getBundles())
               .licensedMac48Addresses(license.getLicensedMacAddrs().stream().<String>map(Mac48Address::toString).collect(Collectors.toSet()))
               .build()
         );
   }

   private static Optional<String> date(LicenseDate licenseDate) {
      return Optional.ofNullable(licenseDate).map(Object::toString);
   }
}
