package com.handong.smartservice.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.handong.smartservice._AG;
import com.handong.smartservice.component.CtResponse;
import com.handong.smartservice.component.DbLogger;
import com.handong.smartservice.component.ErrorCode;
import com.handong.smartservice.component.UserInfo;
import com.handong.smartservice.mapper.BizGroupMapper;
import com.handong.smartservice.mapper.DeviceMapper;
import com.handong.smartservice.mapper.TerminalMapper;


@Service
public class DeviceService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired DeviceMapper deviceMapper;
    @Autowired TerminalMapper terminalMapper;
    @Autowired BizGroupMapper bizGroupMapper;


    public DeviceService(DeviceMapper deviceMapper) {
        this.deviceMapper = deviceMapper;
    }

    public Map<String, Object> getDeviceList(Boolean is_excel, Long offset, Long limit, Boolean is_group_access, Long biz_group_id, String name, String date_start, String date_end) {
        Map<String, Object> mapResult = new HashMap<>();

        //OldVer
        //if (is_group_access == false) {
        //    List<Map<String, Object>> listForTopId = bizGroupMapper.selectBizGroup(biz_group_id, false, 0L, 1L, null, null, null, null, null, null, null);
        //    if (listForTopId.size() >= 0) {
        //        biz_group_id = (Long)listForTopId.get(0).get("top_group_id");
        //        if (biz_group_id == null)
        //            biz_group_id = (Long)listForTopId.get(0).get("biz_group_id");
        //    }
        //}
        if (is_group_access) {
            List<Map<String, Object>> listMap = (List<Map<String, Object>>)deviceMapper.selectDevice(false, is_excel, offset, limit, is_group_access,
                biz_group_id, name, date_start, date_end);
            mapResult.put("list", listMap);
        
            if (is_excel == false) {
                Long totalCount = _AG.getNumberFromQuery("COUNT(*)", deviceMapper.selectDevice(true, is_excel, offset, limit, is_group_access,
                    biz_group_id, name, date_start, date_end));
                mapResult.put("totalCount", totalCount);
                mapResult.put("offset", offset);
            }
        }
        else {
            List<Map<String, Object>> listMap = (List<Map<String, Object>>)deviceMapper.selectDevice2(false, is_excel, offset, limit,
                biz_group_id, name, date_start, date_end);
            mapResult.put("list", listMap);
        
            if (is_excel == false) {
                Long totalCount = _AG.getNumberFromQuery("COUNT(*)", deviceMapper.selectDevice2(true, is_excel, offset, limit,
                        biz_group_id, name, date_start, date_end));
                mapResult.put("totalCount", totalCount);
                mapResult.put("offset", offset);
            }
        }

        return mapResult;
    }

    public CtResponse addOrModifyDevice(boolean isModify, Long biz_group_id, Long new_biz_group_id, Long device_id, Long terminal_id, String name, String uid1, String manager_name) {
        CtResponse result = new CtResponse();

        UserInfo userInfo = (UserInfo)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (isModify) {
            if (device_id == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
                return result;
            }

            //OldVer
            //if (terminal_id != 0) {
            //    terminalMapper.updateTerminalRemoveDevice(device_id);
            //    terminalMapper.updateTerminalChangeDevice(terminal_id, device_id);
            //}
            Map<String, Object> mapTerminal = null;
            if (terminal_id != 0) {
                mapTerminal = terminalMapper.selectTerminalByDeviceId(device_id);
                if (mapTerminal != null) {
                    Long curr_terminal_id = (Long)mapTerminal.get("terminal_id"); // current terminal

                    Map<String, Object> mapNewTerminal = terminalMapper.selectTerminalById(terminal_id);
                    if (mapNewTerminal != null) {
                        Long new_device_id = (Long)mapNewTerminal.get("device_id"); // new device

                        Map<String, Object> mapNewDevice = deviceMapper.selectDeviceById(new_device_id);
                        if (mapNewDevice != null) {
                            String new_device_name = (String)mapNewDevice.get("name");
                            terminalMapper.updateTerminalChangeDevice(curr_terminal_id, new_device_id, 5L, new_device_name);
                        }
                    }
                }

                terminalMapper.updateTerminalChangeDevice(terminal_id, device_id, 1L, name);
            }

            if (new_biz_group_id != 0 && new_biz_group_id != biz_group_id) {
                deviceMapper.deleteDeviceBizGroup(biz_group_id, device_id);   // delete n:n relation
                deviceMapper.insertDeviceBizGroup(new_biz_group_id, device_id);

                if (mapTerminal != null)
                    mapTerminal = terminalMapper.selectTerminalByDeviceId(device_id);

                if (mapTerminal != null) {
                    terminal_id = (Long)mapTerminal.get("terminal_id"); // old terminal
                    if (terminal_id != null) {
                        terminalMapper.deleteTerminalBizGroup(biz_group_id, terminal_id);
                        terminalMapper.insertTerminalBizGroup(new_biz_group_id, terminal_id);
                    }
                }
            }

            deviceMapper.updateDevice(device_id, terminal_id, name, uid1, manager_name, userInfo.getGid());
            DbLogger.insert(2L, "무인기기 정보 수정, device_id: " + device_id, userInfo.getGid());
        }
        else {
            Map<String, Object> params = new HashMap<>();
            params.put("name", name);
            params.put("uid1", uid1);
            params.put("manager_name", manager_name);
            params.put("gid", 2L); //TempCode

            if (terminal_id != 0) {
                params.put("terminal_id", terminal_id);
            }

            if (deviceMapper.insertDevice(params) == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
                return result;
            }
            DbLogger.insert(2L, "무인기기 추가, 기기명: " + name + "TID: " + uid1, userInfo.getGid());
            
            Long new_device_id = _AG.toLong((BigInteger)params.get("device_id"));        
            
            if (deviceMapper.insertDeviceBizGroup(biz_group_id, new_device_id) == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
            }
            else {
                result.put("result", Map.of("biz_group_id", params.get("biz_group_id")));
            }
        }
        
        return result;
    }

    @Transactional
    //public CtResponse removeDevice(String ids) {
    public CtResponse removeDevice(Long biz_group_id, Long device_id) {
        CtResponse result = new CtResponse();

        UserInfo userInfo = (UserInfo)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        //terminalMapper.updateTerminalRemoveDevice(device_id);
        Map<String, Object> mapTerminal = terminalMapper.selectTerminalByDeviceId(device_id);
        if (mapTerminal != null) {
            Long terminal_id = (Long)mapTerminal.get("terminal_id");
            if (terminal_id != null) {
                int changed = terminalMapper.deleteTerminal(terminal_id);
                changed = terminalMapper.deleteTerminalBizGroup(biz_group_id, terminal_id);   // delete n:n relation
            }
        }

        //List<Long> arrId = Arrays.stream(ids.split(","))
        //    .map(Long::parseLong)
        //    .collect(Collectors.toList());
        //int changed = terminalMapper.changeStateTerminals(arrId, 2);
        int changed = deviceMapper.deleteDevice(device_id);
        if (changed == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        DbLogger.insert(2L, "무인기기 삭제, device_id: " + device_id, userInfo.getGid());

        changed = deviceMapper.deleteDeviceBizGroup(biz_group_id, device_id);   // delete n:n relation
        if (changed == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        
        return result;
    }

    public CtResponse configDevice(Long device_id) {
        CtResponse result = new CtResponse();

        int changed = deviceMapper.updateDeviceTerminalTime(device_id, null, null);
        if (changed == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        
        return result;
    }

    public Map<String, Object> selectDeviceByError(Long biz_group_id) {
        Map<String, Object> mapResult = new HashMap<>();
        
        List<Map<String, Object>> listMap = (List<Map<String, Object>>)deviceMapper.selectDeviceByError(biz_group_id);
        mapResult.put("list", listMap);

        return mapResult;
    }
}
