package com.iqser.red.persistence.service.v1.external.api.impl.controller;

import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.READ_LICENSE;
import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.UPDATE_LICENSE;

import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RestController;

import com.iqser.red.service.persistence.service.v1.api.external.resource.LicenseResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.Feature;
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.FeatureType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.License;
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.RedactionLicenseModel;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantContext;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequiredArgsConstructor
public class LicenseController implements LicenseResource {

    private static final String LICENSE_OBJECT_ID = "license/redact-manager-license.json";
    private static final String DEMO_PDFTRON_LICENSE = "demo:1650351709282:7bd235e003000000004ec28a6743e1163a085e2115de2536ab6e2cfe5a";
    private static final String LICENSE_CUSTOMER = "LICENSE_CUSTOMER";
    private static final String LICENSE_START = "LICENSE_START";
    private static final String LICENSE_END = "LICENSE_END";
    private static final String LICENSE_PAGE_COUNT = "LICENSE_PAGE_COUNT";
    private static final String PDFTRON_FRONTEND_LICENSE = "PDFTRON_FRONTEND_LICENSE";
    private static final String PDFTRON_FEATURE = "pdftron";
    private static final String PROCESSING_PAGES_FEATURE = "processingPages";
    private static final String DEFAULT_PROCESSING_PAGES = "200000";
    private final StorageService storageService;
    private final Environment environment;


    @Override
    @SneakyThrows
    @PreAuthorize("hasAuthority('" + UPDATE_LICENSE + "')")
    public void updateLicense(RedactionLicenseModel licenseModel) {

        storageService.storeJSONObject(TenantContext.getTenantId(), LICENSE_OBJECT_ID, licenseModel);
    }


    @Override
    @PreAuthorize("hasAuthority('" + READ_LICENSE + "')")
    public RedactionLicenseModel getLicense() {

        if (storageService.objectExists(TenantContext.getTenantId(), LICENSE_OBJECT_ID)) {
            try {
                return storageService.readJSONObject(TenantContext.getTenantId(), LICENSE_OBJECT_ID, RedactionLicenseModel.class);
            } catch (Exception e) {
                return generateDemoLicense();
            }
        } else {
            return generateDemoLicense();
        }
    }


    private RedactionLicenseModel generateDemoLicense() {

        License demo = new License();
        demo.setId("RedactManager");
        demo.setName("RedactManager License");
        demo.setProduct("RedactManager");

        var licensedTo = environment.getProperty(LICENSE_CUSTOMER, "RedactManager Demo License");
        demo.setLicensedTo(licensedTo);

        var licenseStartDate = parseDate(environment.getProperty(LICENSE_START));
        var start = licenseStartDate != null ? licenseStartDate : OffsetDateTime.now().withDayOfYear(1).withHour(0).withMinute(0).withSecond(0).truncatedTo(ChronoUnit.SECONDS);
        demo.setValidFrom(start);

        var licenseEndDate = parseDate(environment.getProperty(LICENSE_END));
        var end = licenseEndDate != null ? licenseEndDate : OffsetDateTime.now()
                .withMonth(12)
                .withDayOfMonth(31)
                .withHour(0)
                .withMinute(0)
                .withSecond(0)
                .truncatedTo(ChronoUnit.SECONDS);
        demo.setValidUntil(end);

        var pdftronLicense = environment.getProperty(PDFTRON_FRONTEND_LICENSE, DEMO_PDFTRON_LICENSE);
        demo.getFeatures().add(Feature.builder().name(PDFTRON_FEATURE).type(FeatureType.STRING).value(pdftronLicense).build());

        var pageCount = Long.parseLong(environment.getProperty(LICENSE_PAGE_COUNT, DEFAULT_PROCESSING_PAGES));
        demo.getFeatures().add(Feature.builder().name(PROCESSING_PAGES_FEATURE).type(FeatureType.NUMBER).value(pageCount).build());

        var demoLicense = new RedactionLicenseModel();
        demoLicense.setActiveLicense("RedactManager");
        demoLicense.getLicenses().add(demo);

        return demoLicense;
    }


    private OffsetDateTime parseDate(String date) {

        if (StringUtils.isEmpty(date)) {
            return null;
        }
        var parts = date.split("-");
        if (parts.length != 3) {
            return null;
        }

        try {
            return OffsetDateTime.now()
                    .withYear(Integer.parseInt(parts[2]))
                    .withMonth(Integer.parseInt(parts[1]))
                    .withDayOfMonth(Integer.parseInt(parts[0]))
                    .withHour(0)
                    .withMinute(0)
                    .withSecond(0)
                    .truncatedTo(ChronoUnit.SECONDS);
        } catch (Exception e) {
            log.debug("Failed to parse date: {}", date);
            return null;
        }

    }

}
