package com.tsi.api.server.service;

import com.tsi.api.server.controller.result.TscApiResultCode;
import com.tsi.api.server.dto.SystemStatusDto;
import com.tsi.api.server.error.TscSsipApiErrorCode;
import com.tsi.api.server.mybatis.TscSsipApiMapper;
import com.tsi.api.server.mybatis.TsiDatabaseMapper;
import com.tsi.api.server.mybatis.vo.AbstractDbmsVo;
import com.tsi.api.server.mybatis.vo.AlarmOccrVo;
import com.tsi.api.server.repository.TsiAlarmManager;
import com.tsi.api.server.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
@Transactional(rollbackFor = {Exception.class})
public class TscSsipApiService {

    private final TscSsipApiMapper tscSsipApiMapper;
    private final TsiDatabaseMapper tsiDatabaseMapper;

    public TscSsipApiService(TscSsipApiMapper tscSsipApiMapper, TsiDatabaseMapper tsiDatabaseMapper) {
        this.tscSsipApiMapper = tscSsipApiMapper;
        this.tsiDatabaseMapper = tsiDatabaseMapper;
    }

    @Transactional(readOnly = true)
    public List<NodeVo> getNodeInfoList() {
        return tscSsipApiMapper.getNodeInfoList();
    }

    @Transactional(readOnly = true)
    public AuthorizedVo getApiAuthorizedInfo(String apiId, String apiToken) {
        return tscSsipApiMapper.getApiAuthorizedInfo(apiId, apiToken);
    }

    public TscApiResultCode getTscAuthorizedInfo(String apiId, String apiToken, String remoteIP) {

        AuthorizedVo authorized = getApiAuthorizedInfo(apiId, apiToken);
        if (authorized == null) {
            // 등록되지 않은 사용자
            return TscApiResultCode.FAIL_APITOKEN_AUTH;
        }
        else {
            if (authorized.getIsAuthorized() == 0) {
                // 키 유효기간이 지남
                return TscApiResultCode.FAIL_APITOKEN_EXPIRED;
            }
            else {
                // ip address 체크
                String[] ipAddrs = authorized.getAccessIpAddress().replaceAll(" ", "").split(",");
                Set<String> setIpAddrs = new HashSet<>(Arrays.asList(ipAddrs));
                if (setIpAddrs.contains("*") || setIpAddrs.contains(remoteIP)) {
                    return TscApiResultCode.SUCCESS;
                }
            }
        }
        return TscApiResultCode.FAIL_UNREGI_IPADDR;
    }

    public TscSsipApiErrorCode getAuthorizedInfo(String apiId, String apiToken, String remoteIP) {

        AuthorizedVo authorized = getApiAuthorizedInfo(apiId, apiToken);
        if (authorized == null) {
            // 등록되지 않은 사용자
            return TscSsipApiErrorCode.UNREGISTERED_APITOKEN;
        }
        else {
            if (authorized.getIsAuthorized() == 0) {
                // 키 유효기간이 지남
                return TscSsipApiErrorCode.APITOKEN_EXPIRED;
            }
            else {
                // ip address 체크
                String[] ipAddrs = authorized.getAccessIpAddress().replaceAll(" ", "").split(",");
                Set<String> setIpAddrs = new HashSet<>(Arrays.asList(ipAddrs));
                if (setIpAddrs.contains("*") || setIpAddrs.contains(remoteIP)) {
                    return TscSsipApiErrorCode.SUCCESS;
                }
            }
        }
        return TscSsipApiErrorCode.DENIED_IPADDR;
    }

    public KafkaAuthorizedVo getApiKafkaAuthorizedInfo(String apiToken) {
        return tscSsipApiMapper.getApiKafkaAuthorizedInfo(apiToken);
    }
    public KafkaAuthorizedVo getKafkaAuthorizedInfo(String apiToken, String remoteIP, boolean checkIpAddr) {

        KafkaAuthorizedVo authorized = getApiKafkaAuthorizedInfo(apiToken);
        if (authorized == null) {
            // 등록되지 않은 사용자
            authorized = new KafkaAuthorizedVo();
            authorized.setErrorCode(TscSsipApiErrorCode.UNREGISTERED_APITOKEN);
        }
        else {
            if (authorized.getIsAuthorized() == 0) {
                // 키 유효기간이 지남
                authorized.setErrorCode(TscSsipApiErrorCode.APITOKEN_EXPIRED);
            }
            else {
                // ip address 체크
                if (checkIpAddr) {
                    String[] ipAddrs = authorized.getAccessIpAddress().replaceAll(" ", "").split(",");
                    Set<String> setIpAddrs = new HashSet<>(Arrays.asList(ipAddrs));
                    if (setIpAddrs.contains("*") || setIpAddrs.contains(remoteIP)) {
                        authorized.setErrorCode(TscSsipApiErrorCode.SUCCESS);
                        return authorized;
                    }
                }
                else {
                    authorized.setErrorCode(TscSsipApiErrorCode.SUCCESS);
                    return authorized;
                }
            }
        }
        authorized.setErrorCode(TscSsipApiErrorCode.DENIED_IPADDR);
        return authorized;
    }

    public BrokerVo getBrokerInfo(String apiToken) {
        return tscSsipApiMapper.getBrokerInfo(apiToken);
    }

    public int insertInvokeHs(ApiInvokeVo invokeVo, boolean isAlarm) {
        int result = 0;
        Date date = new Date();
        SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
        invokeVo.setEventDt(sdf.format(date));
        if (isAlarm) {
            TsiAlarmConfigVo alarmConfig = null;
            String alarmCode = TsiAlarmConfigVo.API_01;
            if (invokeVo.getApiId().contains("kafka")) {
                alarmConfig = TsiAlarmManager.getInstance().get(TsiAlarmConfigVo.KAFKA_03);
                alarmCode = TsiAlarmConfigVo.KAFKA_03;
            }
            else {
                alarmConfig = TsiAlarmManager.getInstance().get(TsiAlarmConfigVo.API_01);
            }
            if (alarmConfig != null) {
                AlarmOccrVo alarm = new AlarmOccrVo(AbstractDbmsVo.DBMS_ALARM_OCCR_HS);
                alarm.setAlarmCode(alarmCode);
                alarm.setAlarmTarget(invokeVo.getApiId());
                alarm.setAlarmValue(invokeVo.getApiToken() + ", " + String.valueOf(invokeVo.getError()));
                try {
                    result = tsiDatabaseMapper.insertAlarmOccrHs(alarm);
                } catch (Exception e) {
                    log.error("insertAlarmOccrHs: {}, {}", alarm, e.getMessage());
                }
            }
        }
        try {
            // 같은 곳에서 1초이내에 요청하는 경우 이력 Dup Key Error 발생(20221005)
            result = tscSsipApiMapper.insertInvokeHs(invokeVo);
        } catch(Exception e) {
            log.error("insertAlarmOccrHs: {}, {}", invokeVo, e.getMessage());
        }
        return result;
    }

    public int updateSystemInfo(SystemStatusDto info){
        int result = 0;
        try {
            tscSsipApiMapper.insertSystemInfo(info);
        } catch(Exception e) {
            log.error("insertSystemInfo: {}, {}", info, e.getMessage());
        }
        return result;
    }
    public int insertSystemStatusHs(SystemStatusVo info) {
        int result = 0;
        try {
            result = tscSsipApiMapper.insertSystemStatusHs(info);
        } catch (Exception e) {
            log.error("insertSystemStatusHs: {}, {}", info, e.getMessage());
        }
        return result;
    }
}
