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.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

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.GoodsMapper;


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

    private final GoodsMapper goodsMapper;
    private final BizGroupMapper bizGroupMapper;
    private final DeviceMapper deviceMapper;


    public GoodsService(GoodsMapper goodsMapper, BizGroupMapper bizGroupMapper, DeviceMapper deviceMapper) {
        this.goodsMapper = goodsMapper;
        this.bizGroupMapper = bizGroupMapper;
        this.deviceMapper = deviceMapper;
    }

    public Map<String, Object> getGoodsList(Boolean is_excel, Long offset, Long limit, Boolean is_group_access, Long biz_group_id, Long device_id, Long state, 
                String code, String name, String vendor, 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>>)goodsMapper.selectGoods(false, is_excel, offset, limit, is_group_access,
            biz_group_id, device_id, state, code, name, vendor, date_start, date_end);
        mapResult.put("list", listMap);
        
        Long totalCount = _AG.getNumberFromQuery("COUNT(*)", goodsMapper.selectGoods(true, is_excel, offset, limit, is_group_access, 
            biz_group_id, device_id, state, code, name, vendor, date_start, date_end));
        mapResult.put("totalCount", totalCount);
        mapResult.put("offset", offset);
        return mapResult;
    }

    public CtResponse addOrModifyGoods(boolean isModify, Long biz_group_id, Long goods_id, String code, String name, Long price, Long inventory, String vendor) {
        CtResponse result = new CtResponse();

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

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

            goodsMapper.updateGoods(biz_group_id, goods_id, code, name, price, inventory, vendor, userInfo.getGid());
            DbLogger.insert(2L, "상품정보 수정, goods_id: " + goods_id, 2L);
        }
        else {
            if (goodsMapper.selectExistGoods(biz_group_id, code, name) != null) {
                result.setErrCode(ErrorCode.ALREADY_EXIST);
                return result;
            }

            if (price == null)
                price = 0L;

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

            goodsMapper.insertGoods(params);
            DbLogger.insert(2L, "상품정보 추가, code: " + code + ", name: " + name, userInfo.getGid());
        }
        
        return result;
    }

    public CtResponse removeGoods(String ids) {
        CtResponse result = new CtResponse();

        List<Long> arrId = Arrays.stream(ids.split(","))
            .map(Long::parseLong)
            .collect(Collectors.toList());
        
        int changed = goodsMapper.deleteGoods(arrId);
        //if (changed == 0) {
            //result.setErrCode(ErrorCode.QUERY_ERROR);
        //}
        
        return result;
    }

    //
    public Map<String, Object> getDeviceGoodsList(Long device_id, String slot, Long goods_id) {
        Map<String, Object> mapResult = new HashMap<>();

        Map<String, Object> mapDevice = deviceMapper.selectDeviceById(device_id);
        mapResult.put("device_name", mapDevice.get("name"));

        List<Map<String, Object>> listMap = (List<Map<String, Object>>)goodsMapper.selectGoodsByDevice(false, device_id);
        mapResult.put("goods_list", listMap);

        List<Map<String, Object>> listMap2 = (List<Map<String, Object>>)goodsMapper.selectDeviceGoods(device_id, slot, goods_id);
        mapResult.put("device_goods_list", listMap2);
        
        if (listMap.size() > 0) {
            Map<String, Object> mapTemplate = getGoodsTemplateByBizGroupId((Long)listMap.get(0).get("biz_group_id"));
            mapResult.put("goods_template_list", mapTemplate.get("goods_template_list"));
        }
        
        return mapResult;
    }

    public CtResponse addDeviceGoods(Long device_id, List<Map<String, String>> device_goods) {
        CtResponse result = new CtResponse();

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

        if (goodsMapper.insertDeviceGoods(device_id, device_goods) == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        DbLogger.insert(2L, "무인기기 상품 추가, device_id: " + device_id, userInfo.getGid());
        return result;
    }

    public CtResponse deleteDeviceGoods(Long device_id, List<Map<String, String>> device_goods) {
        CtResponse result = new CtResponse();

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

        //for (Map<String, Object> item : device_goods) {
        //    item.put("device_id", device_id);
        //}
        if (goodsMapper.deleteDeviceGoods(device_id, device_goods) == 0) {
            result.setErrCode(ErrorCode.QUERY_ERROR);
        }
        DbLogger.insert(2L, "무인기기 상품 삭제, device_id: " + device_id, userInfo.getGid());

        return result;
    }

    public Map<String, Object> getGoodsTemplateByBizGroupId(Long biz_group_id) {
        Map<String, Object> mapResult = new HashMap<>();

        List<Map<String, Object>> listMap = (List<Map<String, Object>>)goodsMapper.selectGoodsTemplateByBizGroupId(biz_group_id);
        
        Map<Object, Map<String, Object>> templateMap = new HashMap<>();
        
        for (Map<String, Object> item : listMap) {
            Object templateId = item.get("goods_template_id");
            
            if (!templateMap.containsKey(templateId)) {
                Map<String, Object> template = new HashMap<>();
                template.put("goods_template_id", templateId);
                template.put("template_name", item.get("template_name"));
                template.put("template_reg_time", item.get("template_reg_time"));
                template.put("goods_template_elements", new ArrayList<Map<String, Object>>());
                template.put("template_inventory", item.get("template_inventory"));
                template.put("template_inventory_max", item.get("template_inventory_max"));
                template.put("template_inventory_alarm", item.get("template_inventory_alarm"));
                templateMap.put(templateId, template);
            }
            
            Map<String, Object> element = new HashMap<>();
            element.put("goods_template_element_id", item.get("goods_template_element_id"));
            element.put("slot", item.get("slot"));
            element.put("goods_id", item.get("goods_id"));
            element.put("inventory", item.get("inventory"));
            element.put("idx", item.get("idx"));
            element.put("inventory_max", item.get("inventory_max"));
            element.put("inventory_alarm", item.get("inventory_alarm"));
            
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> elements = (List<Map<String, Object>>)templateMap.get(templateId).get("goods_template_elements");
            elements.add(element);
        }
        
        List<Map<String, Object>> groupedList = new ArrayList<>(templateMap.values());
        mapResult.put("goods_template_list", groupedList);
        return mapResult;
    }

    public Map<String, Object> getGoodsTemplateById(Long goods_template_id) {
        Map<String, Object> mapResult = new HashMap<>();

        List<Map<String, Object>> templateElements = goodsMapper.selectGoodsTemplateById(goods_template_id);
        mapResult.put("goods_template_elements", templateElements);

        List<Map<String, Object>> goodsList = goodsMapper.selectGoodsByBizGroupId((Long)templateElements.get(0).get("biz_group_id"));
        mapResult.put("goods_list", goodsList);

        return mapResult;
    }

    public CtResponse addGoodsTemplate(Long biz_group_id, String goods_template_name, Map<String, Object> goods_template_inventory, List<Map<String, String>> goods_template_elements) {
        CtResponse result = new CtResponse();

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

        try {
            Map<String, Object> params = new HashMap<>();
            params.put("biz_group_id", biz_group_id);
            params.put("name", goods_template_name);
            params.put("inventory", (Integer)goods_template_inventory.get("inventory"));
            params.put("inventory_max", (Integer)goods_template_inventory.get("inventory_max"));
            params.put("inventory_alarm", (Integer)goods_template_inventory.get("inventory_alarm"));

            goodsMapper.insertGoodsTemplate(params);
            
            Long goods_template_id = _AG.toLong((BigInteger)params.get("goods_template_id"));

            if (goods_template_id == null || goods_template_id == 0) {
                result.setErrCode(ErrorCode.QUERY_ERROR);
                return result;
            }

            if (goods_template_elements != null && goods_template_elements.size() > 0) {
                if (goodsMapper.insertGoodsTemplateElements(goods_template_id, goods_template_elements) == 0) {
                    result.setErrCode(ErrorCode.QUERY_ERROR);
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            result.setErrCode(ErrorCode.INVALID_PARAMETER);
        }

        return result;
    }

    public CtResponse removeGoodsTemplate(Long goods_template_id) {
        CtResponse result = new CtResponse();

        if (goods_template_id == null || goods_template_id == 0) {
            result.setErrCode(ErrorCode.INVALID_PARAMETER);
            return result;
        }

        try {
            goodsMapper.deleteGoodsTemplateElements(goods_template_id);
            goodsMapper.deleteGoodsTemplate(goods_template_id);
        }
        catch (Exception e) {
            e.printStackTrace();
            result.setErrCode(ErrorCode.INVALID_PARAMETER);
        }

        return result;
    }
}
