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.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.component.RcTreeBizGroup;
import com.handong.smartservice.mapper.BizGroupMapper;
import com.handong.smartservice.mapper.OperatingHistoryMapper;


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

    @Autowired BizGroupMapper bizGroupMapper;


    public Map<String, Object> getBizGroupList(Long offset, Long limit, String date_start, String date_end, 
                String name, String biz_reg_num, String email, String phone, String address) {
        Map<String, Object> mapResult = new HashMap<>();

        List<Map<String, Object>> listMap = (List<Map<String, Object>>)bizGroupMapper.selectBizGroup(0L, false, offset, limit, 
            date_start, date_end, name, biz_reg_num, email, phone, address);
        mapResult.put("list", listMap);
        
        Long totalCount = _AG.getNumberFromQuery("COUNT(*)", bizGroupMapper.selectBizGroup(0L, true, offset, limit, 
            date_start, date_end, name, biz_reg_num, email, phone, address));
        mapResult.put("totalCount", totalCount);
        mapResult.put("offset", offset);

        if (listMap.size() == 0)
            return mapResult;
        
        // get BizGroup Tree part
        //
        List<Long> listBizGroupId = listMap.stream()
            .map(item -> (Long)item.get("biz_group_id"))
            .filter(Objects::nonNull)
            .map(Long::valueOf)
            .collect(Collectors.toList());        
        List<Map<String, Object>> listTreeDb = bizGroupMapper.selectBizGroupParentTree(listBizGroupId);

        // Covert for react rc-tree
        List<Map<String, Object>> listRcTree = RcTreeBizGroup.convertDb2RcTree(listTreeDb);

        mapResult.put("tree", listRcTree);
        return mapResult;
    }

    public CtResponse addOrModifyBizGroup(boolean isModify, Long biz_group_id, Long pid, Long top_group_id, String name, String biz_reg_num, String email, String phone, String ceo, String address) {
        CtResponse result = new CtResponse();

        //if (bizGroupMapper.selectExistBizGroup(biz_group_id, biz_reg_num) != null) {
        //    result.setErrCode(ErrorCode.ALREADY_EXIST);
        //    return result;
        //}

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

            bizGroupMapper.updateBizGroup(biz_group_id, pid, name, biz_reg_num, email, phone, ceo, address);
            DbLogger.insert(2L, "사업자그룹정보 수정", 2L);
        }
        else {
            Map<String, Object> params = new HashMap<>();
            params.put("pid", pid);
            params.put("name", name);
            params.put("biz_reg_num", biz_reg_num);
            params.put("gid", 2L);  //TempCode
            params.put("email", email);
            params.put("phone", phone);
            params.put("ceo", ceo);
            params.put("address", address);

            if (bizGroupMapper.insertBizGroup(params) == 0) {
                result.setErrCode(ErrorCode.INVALID_PARAMETER);
            }
            else {
                DbLogger.insert(2L, "사업자그룹 추가, 사업자명: " + name + ", 사업자번호: " + biz_reg_num, 2L);
                result.put("result", Map.of("biz_group_id", params.get("biz_group_id")));
            }
        }
        
        return result;
    }

    @Transactional
    public CtResponse removeBizGroup(String ids) {
        CtResponse result = new CtResponse();

        List<Long> arrId = Arrays.stream(ids.split(","))
            .map(Long::parseLong)
            .collect(Collectors.toList());

        int changed = bizGroupMapper.changeStateBizGroup(arrId, 2);
        //result.setErrCode(ErrorCode.QUERY_ERROR);
        if (changed > 0) {
            bizGroupMapper.changePidBizGroup(arrId, null);
        }
        DbLogger.insert(2L, "사업자그룹 삭제, 사업자명: " + ids, 2L);
        
        return result;
    }

    // ver2
    public CtResponse getBizGroup2(boolean isDbRoot, Long pid, Long top_group_id, String date_start, String date_end, String name, String biz_reg_num) {
        CtResponse result = new CtResponse();

        if (isDbRoot == true) {
            List<Map<String, Object>> listTreeDb = (List<Map<String, Object>>)bizGroupMapper.selectRootNode(isDbRoot, top_group_id, date_start, date_end, name, biz_reg_num);
            
            // Covert for react rc-tree
            List<Map<String, Object>> listRcTree = RcTreeBizGroup.convertDb2RcTree(listTreeDb);
            result.put("result", Map.of("tree", listRcTree));
            return result;
        }

        List<Map<String, Object>> listTreeDb = (List<Map<String, Object>>)bizGroupMapper.selectBizGroupChildTree(true, pid, top_group_id, date_start, date_end, name, biz_reg_num);
        
        // Covert for react rc-tree
        List<Map<String, Object>> listRcTree = RcTreeBizGroup.convertDb2RcTree(listTreeDb);
        result.put("result", Map.of("tree", listRcTree));
        return result;
    }

    public CtResponse getBizGroup3(Long biz_group_id) {
        CtResponse result = new CtResponse();

        // get BizGroup Tree part
        List<Map<String, Object>> listTreeDb = bizGroupMapper.selectBizGroupTree(true, biz_group_id, null, null, null, null);

        // Covert for react rc-tree
        List<Map<String, Object>> listRcTree = RcTreeBizGroup.convertDb2RcTree(listTreeDb);

        result.put("result", Map.of("tree", listRcTree));
        return result;
    }
}
