package com.aip.gateway.api.repository;

import com.aip.gateway.api.aip.manager.AipFileManager;
import com.aip.gateway.api.aip.model.AipLabel;
import com.aip.gateway.api.aip.model.AipTemplate;
import com.aip.gateway.api.dao.mapper.BaseDbMapper;
import com.aip.gateway.api.entity.TbAipLabel;
import com.aip.gateway.api.entity.TbAipPolicy;
import com.aip.gateway.api.entity.TbAipTemplate;
import com.aip.gateway.api.model.response.GeneralResponse;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Getter
@Component
@RequiredArgsConstructor
public class AipFileRepository {

    private final AppRepository repo;
    private final BaseDbMapper mapper;
    private AipFileManager manager;

    public boolean initialize() {
        this.manager = new AipFileManager(this.repo.getSettings().getConfig());
        if (!this.manager.initialize()) {
            log.error("AipFileManager.initialize Failed, {}, {}", this.manager.getLastErrNo(), this.manager.getLastErrMsg());
            return false;
        }
        if (!this.manager.createProfile()) {
            log.error("AipFileManager.createProfile Failed, {}, {}", this.manager.getLastErrNo(), this.manager.getLastErrMsg());
            return false;
        }
        if (!this.manager.createEngine()) {
            log.error("AipFileManager.createEngine Failed, {}, {}", this.manager.getLastErrNo(), this.manager.getLastErrMsg());
            return false;
        }
        log.info("AipFileManager Initialize And Create Success.");

        downloadAipInfo();
        return true;
    }

    public GeneralResponse downloadAipInfo() {
        List<AipLabel> labels = this.manager.getSensitivityLabels();
        List<AipLabel> polities = this.getManager().getPolicySensitivityLabels();
        List<AipTemplate> templates = this.getManager().getTemplates();
        if (labels == null) {
            labels = new ArrayList<>();
        }
        if (polities == null) {
            polities = new ArrayList<>();
        }
        if (templates == null) {
            templates = new ArrayList<>();
        }

        ConcurrentHashMap<String, TbAipLabel> aipLabelMap = new ConcurrentHashMap<>();
        ConcurrentHashMap<String, TbAipPolicy> aipPolicyMap = new ConcurrentHashMap<>();
        ConcurrentHashMap<String, TbAipTemplate> aipTemplateMap = new ConcurrentHashMap<>();

        List<TbAipLabel> aipLabels = this.mapper.selectAipLabels();
        List<TbAipPolicy> aipPolicies = this.mapper.selectAipPolicies();
        List<TbAipTemplate> aipTemplates = this.mapper.selectAipTemplates();
        log.error("{}", aipLabels);
        log.error("{}", aipPolicies);
        log.error("{}", aipTemplates);

        aipLabels.forEach(obj -> aipLabelMap.put(obj.getLabelGuid(), obj));
        aipPolicies.forEach(obj -> aipPolicyMap.put(obj.getPolicyGuid(), obj));
        aipTemplates.forEach(obj -> aipTemplateMap.put(obj.getTemplateGuid(), obj));

        ConcurrentHashMap<String, AipLabel> labelMap = new ConcurrentHashMap<>();
        ConcurrentHashMap<String, AipLabel> policyMap = new ConcurrentHashMap<>();
        ConcurrentHashMap<String, AipTemplate> templateMap = new ConcurrentHashMap<>();

        labels.forEach(obj -> {
            labelMap.put(obj.getId(), obj);
            TbAipLabel dbObj = aipLabelMap.get(obj.getId());
            if (dbObj == null) {
                this.mapper.insertAipLabel(TbAipLabel.builder()
                        .labelId(1)
                        .labelGuid(obj.getId())
                        .labelName(obj.getName())
                        .labelDesc(obj.getDescription())
                        .useYn(true)
                        .build());
            }
            else {
                if (dbObj.isChanged(obj)) {
                    dbObj.setLabelName(obj.getName());
                    dbObj.setLabelDesc(obj.getDescription());
                    this.mapper.updateAipLabel(dbObj);
                }
            }
        });
        this.repo.setLabelMap(labelMap);

        polities.forEach(obj -> {
            policyMap.put(obj.getId(), obj);
            TbAipPolicy dbObj = aipPolicyMap.get(obj.getId());
            if (dbObj == null) {
                this.mapper.insertAipPolicie(TbAipPolicy.builder()
                        .policyId(1)
                        .policyGuid(obj.getId())
                        .policyName(obj.getName())
                        .policyDesc(obj.getDescription())
                        .useYn(true)
                        .build());
            }
            else {
                if (dbObj.isChanged(obj)) {
                    dbObj.setPolicyName(obj.getName());
                    dbObj.setPolicyDesc(obj.getDescription());
                    this.mapper.updateAipPolicie(dbObj);
                }
            }
        });
        this.repo.setPolicyMap(policyMap);

        templates.forEach(obj -> {
            templateMap.put(obj.getId(), obj);
            TbAipTemplate dbObj = aipTemplateMap.get(obj.getId());
            if (dbObj == null) {
                this.mapper.insertAipTemplate(TbAipTemplate.builder()
                        .templateId(1)
                        .templateGuid(obj.getId())
                        .templateName(obj.getName())
                        .templateDesc(obj.getDescription())
                        .useYn(true)
                        .build());
            }
            else {
                if (dbObj.isChanged(obj)) {
                    dbObj.setTemplateName(obj.getName());
                    dbObj.setTemplateDesc(obj.getDescription());
                    this.mapper.updateAipTemplate(dbObj);
                }
            }
        });
        this.repo.setTemplateMap(templateMap);

        return GeneralResponse.builder()
                .errorCode(0)
                .effectCount(labels.size() + polities.size() + templates.size())
                .errorMessage("Success")
                .build();
    }
}
