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.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.mapper.BizGroupMapper;
import com.handong.smartservice.mapper.DeviceMapper;
import com.handong.smartservice.mapper.GoodsMapper;
import com.handong.smartservice.mapper.TerminalMapper;


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

    private final  TerminalMapper terminalMapper;
    private final  DeviceMapper deviceMapper;
    private final  BizGroupMapper bizGroupMapper;
    

    public TerminalService(TerminalMapper terminalMapper, DeviceMapper deviceMapper, BizGroupMapper bizGroupMapper) {
        this.terminalMapper = terminalMapper;
        this.deviceMapper = deviceMapper;
        this.bizGroupMapper = bizGroupMapper;
    }

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

        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 != null && 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");
            }
        }

        List<Map<String, Object>> listMap = (List<Map<String, Object>>)terminalMapper.selectTerminal(false, is_excel, offset, limit, is_group_access, 
            biz_group_id, null, state, date_start, date_end);
        mapResult.put("list", listMap);
        
        Long totalCount = _AG.getNumberFromQuery("COUNT(*)", terminalMapper.selectTerminal(true, is_excel, offset, limit, is_group_access, 
            biz_group_id, null, state, date_start, date_end));
        mapResult.put("totalCount", totalCount);
        mapResult.put("offset", offset);
        return mapResult;
    }

    @Transactional
    public CtResponse addOrModifyTerminal(boolean isModify, Long addType, Long biz_group_id, Long terminal_id, String name, String uid1, Long type) {
        CtResponse result = new CtResponse();

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

            terminalMapper.updateTerminal(terminal_id, name, uid1, type, null, 2L);
            DbLogger.insert(2L, "카드단말기 정보변경, terminal_id: " + terminal_id, 2L);
        }
        else {
            if (terminalMapper.selectExistTerminal(name, uid1, type) != null) {
                result.setErrCode(ErrorCode.ALREADY_EXIST);
                return result;
            }

            Map<String, Object> params = new HashMap<>();
            params.put("name", name);
            params.put("gid", 2L); //TempCode

            logger.info("addType = " + addType);
            /* oldVer
            if (addType == 1L) {
                logger.info("addType2 = " + addType);
                if (deviceMapper.insertDevice(params) == 0) {
                    result.setErrCode(ErrorCode.INVALID_PARAMETER);
                    return result;
                }
                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);
                    return result;
                }
            }
            */
            if (addType != 1L)
                params.put("state", 5L);
            else
                params.put("state", 1L);

            if (deviceMapper.insertDevice(params) == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
                return result;
            }
            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);
                return result;
            }
            //

            params.put("uid1", uid1);
            params.put("type", type);
            params.put("gid", 2L); //TempCode

            if (terminalMapper.insertTerminal(params) == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
                return result;
            }
            DbLogger.insert(2L, "카드단말기 추가, TID: " + uid1, 2L);

            Long new_terminal_id = _AG.toLong((BigInteger)params.get("terminal_id"));

            if (terminalMapper.insertTerminalBizGroup(biz_group_id, new_terminal_id) == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
                return result;
            }

            result.put("result", Map.of("terminal_id", new_terminal_id));
        }
        
        return result;
    }

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

        Map<String, Object> mapTerminal = terminalMapper.selectTerminalById(terminal_id);
        if (mapTerminal != null) {
            Long device_id = (Long)mapTerminal.get("device_id");
            if (device_id != null) {
                int changed = deviceMapper.deleteDevice(device_id);
                changed = deviceMapper.deleteDeviceBizGroup(biz_group_id, device_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 = terminalMapper.deleteTerminal(terminal_id);
        if (changed == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        DbLogger.insert(2L, "카드단말기 삭제, terminal_id: " + terminal_id, 2L);

        changed = terminalMapper.deleteTerminalBizGroup(biz_group_id, terminal_id);   // delete n:n relation
        if (changed == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        
        return result;
    }

    public CtResponse terminalState(String uid1, Long type, Long state) {
        CtResponse result = new CtResponse();

        if (terminalMapper.terminalState(uid1, type, state) == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        DbLogger.insert(1L, "카드단말기 상태 변경, TID: " + uid1 + ", state: " + state, 2L);

        return result;
    }
}
