package com.iqser.red.service.peristence.v1.server.integration.tests.performance;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import jakarta.transaction.Transactional;

import org.assertj.core.util.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.TransientSecurityContext;
import org.springframework.stereotype.Service;

import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierStatsClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
import com.iqser.red.service.peristence.v1.server.integration.service.UserProvider;
import com.iqser.red.service.persistence.management.v1.processor.acl.custom.dossier.DossierACLService;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.DictionaryEntryEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.WatermarkEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierTemplateEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeConfigEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileAttributeConfigRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileAttributesRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.TypeRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.WatermarkRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.dictionaryentry.EntryRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DownloadFileType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.WatermarkOrientation;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ProcessingStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class PerformanceTestService {

    private final static Integer DOSSIER_COUNT = 1;
    private final static Integer FILE_PER_DOSSIER_COUNT = 100;
    private final static Integer TYPE_COUNT = 1;
    private final static Integer TYPE_ENTRY_COUNT = 500;
    private final static Integer FILE_ATTRIBUTE_COUNT = 15;

    @Autowired
    private DossierClient dossierClient;
    @Autowired
    private FileClient fileClient;
    @Autowired
    private DossierStatsClient dossierStatsClient;
    @Autowired
    private DossierTemplateRepository dossierTemplateRepository;
    @Autowired
    private WatermarkRepository watermarkRepository;
    @Autowired
    private DossierRepository dossierRepository;
    @Autowired
    private TypeRepository typeRepository;
    @Autowired
    private EntryRepository entryRepository;
    @Autowired
    private FileAttributeConfigRepository fileAttributeConfigRepository;
    @Autowired
    private FileRepository fileRepository;
    @Autowired
    private FileAttributesRepository fileAttributesRepository;
    @Autowired
    private DossierACLService dossierACLService;

    @Autowired
    private UserProvider userProvider;


    @Transactional
    public void doSetup() {

        long start = System.currentTimeMillis();

        DossierTemplateEntity dte = new DossierTemplateEntity();
        dte.setId(UUID.randomUUID().toString());
        dte.setName("Test");
        dte.setDownloadFileTypes(Sets.newTreeSet(DownloadFileType.ANNOTATED,
                DownloadFileType.REDACTED,
                DownloadFileType.ORIGINAL,
                DownloadFileType.PREVIEW,
                DownloadFileType.FLATTEN));
        dte.setCreatedBy("123");
        dte.setDescription("Lorem Ipsum");
        dte.setModifiedBy("123");

        dte = dossierTemplateRepository.saveAndFlush(dte);

        var watermark = new WatermarkEntity();
        watermark.setName("watermark name");
        watermark.setEnabled(true);
        watermark.setText("Minions ipsum chasy para tu la bodaaa bananaaaa hana dul sae. Chasy hana dul sae pepete hana dul sae belloo! Tatata bala tu ti aamoo! Jeje.");
        watermark.setOrientation(WatermarkOrientation.DIAGONAL);
        watermark.setDossierTemplate(dte);

        var watermarkConfig = watermarkRepository.save(watermark);

        List<FileAttributeConfigEntity> fces = new ArrayList<>();
        for (int i = 0; i < FILE_ATTRIBUTE_COUNT; i++) {
            FileAttributeConfigEntity fce = new FileAttributeConfigEntity();
            fce.setId(UUID.randomUUID().toString());
            fce.setDossierTemplate(dte);
            fce.setLabel("123");
            fce.setCsvColumnHeader("123");
            fce.setPrimaryAttribute(true);
            fce.setFilterable(true);
            fce.setPlaceholder("Lorem Ipsum");
            fce.setType(FileAttributeType.TEXT);
            fce.setDossierTemplate(dte);
            fces.add(fce);

        }

        fces = fileAttributeConfigRepository.saveAll(fces);

        log.info("Created File Attributes Config");

        for (int i = 0; i < TYPE_COUNT; i++) {
            TypeEntity te = new TypeEntity();
            te.setId(UUID.randomUUID().toString());
            te.setDossierTemplate(dte);
            te.setDescription("Lorem Ipsum");
            te.setLabel("Lorem ipsum");
            te.setType("Type " + i);
            te.setAddToDictionaryAction(true);
            te.setCaseInsensitive(true);
            te.setHexColor("hexColor");
            te.setRank(10 + i);
            te.setVersion(1231);
            te.setRecommendation(true);
            te.setHint(false);

            te = typeRepository.save(te);

            List<DictionaryEntryEntity> des = new ArrayList<>();
            for (int j = 0; j < TYPE_ENTRY_COUNT; j++) {
                DictionaryEntryEntity de = new DictionaryEntryEntity();
                de.setTypeId(te.getId());
                de.setDeleted(false);
                de.setVersion(1);
                de.setValue("Dictionary Entry" + i + "/" + j);
                des.add(de);

            }
            entryRepository.saveAll(des);
            log.info("Created Type: {}", te.getType());
        }

        log.info("Created Dossier Template Data ...");

        var user = userProvider.getUserId();
        SecurityContextHolder.setContext(new TransientSecurityContext(new TestingAuthenticationToken(user, "secret")));

        for (int i = 0; i < DOSSIER_COUNT; i++) {

            DossierEntity d = new DossierEntity();
            d.setId(UUID.randomUUID().toString());
            d.setDossierName("Dossier " + i);
            d.setDossierTemplate(dte);
            d.setDueDate(OffsetDateTime.now());
            d.setDescription("Lorem Ipsum");
            d.setWatermarkId(watermarkConfig.getId());
            d.setStartDate(OffsetDateTime.now());
            d.setApproverIds(Sets.newTreeSet("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"));
            d.setMemberIds(Sets.newTreeSet("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"));
            d.setDownloadFileTypes(Sets.newTreeSet(DownloadFileType.ANNOTATED,
                    DownloadFileType.REDACTED,
                    DownloadFileType.ORIGINAL,
                    DownloadFileType.PREVIEW,
                    DownloadFileType.FLATTEN));

            d = this.dossierRepository.save(d);

            dossierACLService.updateDossierACL(Set.of(user), Set.of(user), user, d.getId());

            List<FileEntity> files = new ArrayList<>();
            for (int j = 0; j < FILE_PER_DOSSIER_COUNT; j++) {
                FileEntity f = new FileEntity();
                f.setId(UUID.randomUUID().toString());
                f.setAdded(OffsetDateTime.now());
                f.setAssignee("123");
                f.setApprovalDate(OffsetDateTime.now());
                f.setAnalysisDuration(123);
                f.setDictionaryVersion(33);
                f.setDossierId(d.getId());
                f.setDossierDictionaryVersion(22);
                f.setExcluded(false);
                f.setExcludedPages(getExcludedPages());
                f.setFilename("Lorem Ipsum");
                f.setHasAnnotationComments(false);
                f.setHasRedactions(true);
                f.setHasImages(true);
                f.setHasHints(true);
                f.setUploader("!2321");
                f.setWorkflowStatus(WorkflowStatus.APPROVED);
                f.setProcessingStatus(ProcessingStatus.FULLREPROCESS);
                f.setLastUpdated(OffsetDateTime.now());
                f.setLastUploaded(OffsetDateTime.now());
                f.setLastProcessed(OffsetDateTime.now());
                f.setLastFileAttributeChange(OffsetDateTime.now());
                f.setDossierId(d.getId());
                files.add(f);

            }

            log.info("Created Dossier: {}", d.getDossierName());
            files = fileRepository.saveAll(files);

            ArrayList<FileAttributeEntity> fileAttributes = new ArrayList<>();
            List<FileAttributeConfigEntity> finalFces = fces;
            files.forEach(file -> finalFces.forEach(fce -> {
                FileAttributeEntity fa = new FileAttributeEntity();
                fa.setFileAttributeId(new FileAttributeEntity.FileAttributeEntityId());
                fa.getFileAttributeId().setFileId(file.getId());
                fa.getFileAttributeId().setFileAttributeConfigId(fce.getId());
                fa.setValue("Lorem Ipsum ...");
                fileAttributes.add(fa);
            }));
            fileAttributesRepository.saveAll(fileAttributes);
        }

        long end = System.currentTimeMillis();

        log.info("Created Performance data in: {}ms", end - start);
    }


    private Set<Integer> getExcludedPages() {

        Set<Integer> pages = new HashSet<>();
        for (int i = 0; i < 100; i++) {
            pages.add(i);
        }
        return pages;
    }

}
