package com.zhiqiyun.open.mvc.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhiqiyun.open.annotation.Permission;
import com.zhiqiyun.open.core.models.place.PlaceBaseInfo;
import com.zhiqiyun.open.core.models.place.PlaceBaseInfoExtend;
import com.zhiqiyun.open.core.models.place.PlaceCategory;
import com.zhiqiyun.open.core.models.place.PlaceCategoryExtendColumn;
import com.zhiqiyun.open.core.models.user.OauthInfo;
import com.zhiqiyun.open.core.service.*;
import com.zhiqiyun.open.mvc.Result;
import com.zhiqiyun.open.mvc.params.place.QueryPlaceBaseInfoParam;
import com.zhiqiyun.open.mvc.params.place.SavePlaceBaseInfoExtendParam;
import com.zhiqiyun.open.mvc.params.place.SavePlaceBaseInfoParam;
import com.zhiqiyun.open.utils.DateUtil;
import com.zhiqiyun.open.utils.ServletContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/bz/data/info")
public class PlaceBaseInfoController {

    @Autowired
    private PlaceCategoryService placeCategoryService;

    @Autowired
    private PlaceCategoryExtendColumnService placeCategoryExtendColumnService;

    @Autowired
    private PlaceBaseInfoService placeBaseInfoService;

    @Autowired
    private PlaceBaseInfoExtendService placeBaseInfoExtendService;

    @Autowired
    private SequenceService sequenceService;

    @Autowired
    private OauthService oauthService;

    @Permission(value = "place.base.info.find", tags = "查询文旅场所")
    @PostMapping("/findPage")
    public Result findPage(@RequestBody QueryPlaceBaseInfoParam param) {

        QueryWrapper<PlaceBaseInfo> wrapper = new QueryWrapper<>();

        if (StringUtils.isNotBlank(param.getName())) {
            wrapper.like("name", param.getName());
        }
        Page<PlaceBaseInfo> page = param.getPage();
        page.addOrder(OrderItem.desc("id"));

        Page<PlaceBaseInfo> resultData = this.placeBaseInfoService.page(page, wrapper);

        for (PlaceBaseInfo baseInfo : resultData.getRecords()) {
            PlaceCategory category = this.placeCategoryService.getById(baseInfo.getCategoryId());
            baseInfo.setCategory(category);
        }

        return Result.instance(Result.Code.SUCCESS).setData(resultData);
    }

    @Permission(value = "place.base.info.add", tags = "新建文旅场所")
    @PostMapping("/save")
    public Result save(@Valid @RequestBody SavePlaceBaseInfoParam param) throws Exception {

        PlaceBaseInfo entity = new PlaceBaseInfo();
        BeanUtils.copyProperties(param, entity);

        OauthInfo oauthInfo = this.oauthService.getAuth(ServletContext.getAccessToken());

        entity.setCreatedTime(DateUtil.current());
        entity.setCreatedBy(oauthInfo.getId());

        entity.setUpdatedTime(DateUtil.current());
        entity.setUpdatedBy(oauthInfo.getId());
        entity.setId(this.sequenceService.nextId());

        List<PlaceBaseInfoExtend> listExtends = new ArrayList<>();
        if (param.getListExtends() != null) {
            for (SavePlaceBaseInfoExtendParam extendParam : param.getListExtends()) {
                PlaceBaseInfoExtend extend = new PlaceBaseInfoExtend();
                BeanUtils.copyProperties(extendParam, extend);
                listExtends.add(extend);
            }
        }

        this.placeBaseInfoService.save(entity, listExtends);

        return Result.instance(Result.Code.MESSAGE_SUCCESS);
    }

    @Permission(value = "place.base.info.edit", tags = "更新文旅场所")
    @PostMapping("/updateById")
    public Result updateById(Long id, @Valid @RequestBody SavePlaceBaseInfoParam param) {
        PlaceBaseInfo entity = new PlaceBaseInfo();
        BeanUtils.copyProperties(param, entity);

        OauthInfo oauthInfo = this.oauthService.getAuth(ServletContext.getAccessToken());

        entity.setUpdatedBy(oauthInfo.getId());
        entity.setUpdatedTime(DateUtil.current());
        entity.setId(id);

        List<PlaceBaseInfoExtend> listExtends = new ArrayList<>();
        if (param.getListExtends() != null) {
            for (SavePlaceBaseInfoExtendParam extendParam : param.getListExtends()) {
                PlaceBaseInfoExtend extend = new PlaceBaseInfoExtend();
                BeanUtils.copyProperties(extendParam, extend);
                listExtends.add(extend);
            }
        }

        log.info(JSON.toJSONString(listExtends));
        this.placeBaseInfoService.updateById(entity, listExtends);

        return Result.instance(Result.Code.MESSAGE_SUCCESS);
    }

    @Permission(value = "place.base.info.delete", tags = "删除文旅场所")
    @PostMapping("/deleteByIds")
    public Result deleteByIds(@RequestBody List<Long> ids) {
        this.placeBaseInfoService.removeByIds(ids);
        return Result.instance(Result.Code.MESSAGE_SUCCESS);
    }

    @Permission(value = "place.base.info.gis.map", tags = "分类组查询数量", writeLog = false)
    @PostMapping("/findByGroupByDataType")
    public Result findByGroupByDataType() {
        QueryWrapper<PlaceBaseInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("category_id, count(1) num");
        queryWrapper.groupBy("category_id");
        List<Map<String, Object>> listData = this.placeBaseInfoService.listMaps(queryWrapper);
        for (Map<String, Object> dataMap : listData) {
            Long categoryId = Long.valueOf(dataMap.get("category_id").toString());
            PlaceCategory category = this.placeCategoryService.getById(categoryId);
            dataMap.put("category", category);
        }
        return Result.instance(Result.Code.SUCCESS).setData(listData);
    }

    @ResponseBody
    @PostMapping("/findByMapBounds")
    public Result findByMapBounds(BigDecimal maxlng, BigDecimal maxlat, BigDecimal minlng, BigDecimal minlat, Long categoryId) {
        QueryWrapper<PlaceBaseInfo> queryWrapper = new QueryWrapper<>();
        if (maxlng != null) {
            queryWrapper.le("lng", maxlng);
        }
        if (maxlat != null) {
            queryWrapper.le("lat", maxlat);
        }
        if (minlng != null) {
            queryWrapper.ge("lng", minlng);
        }
        if (minlat != null) {
            queryWrapper.ge("lat", minlat);
        }
        if (categoryId != null) {
            queryWrapper.eq("category_id", categoryId);
        }

        List<PlaceBaseInfo> listData = this.placeBaseInfoService.list(queryWrapper);
        return Result.instance(Result.Code.SUCCESS).setData(listData);
    }

    @PostMapping("/findAllDataType")
    @Permission(value = {"place.base.info.edit", "place.base.info.add"}, tags = "获取文旅场所", writeLog = false)
    public Result findAllDataType() {
        List<PlaceCategory> listData = this.placeCategoryService.list();
        return Result.instance(Result.Code.SUCCESS).setData(listData);

    }

    @PostMapping("/findDataBaseInfoExtends")
    @Permission(value = {"place.base.info.edit", "place.base.info.add"}, tags = "获取文旅场所扩展字段", writeLog = false)
    public Result findDataBaseInfoExtends(Long baseInfoId, Long categoryId) {

        QueryWrapper<PlaceCategoryExtendColumn> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id", categoryId);
        List<PlaceCategoryExtendColumn> listData = this.placeCategoryExtendColumnService.list(queryWrapper);
        if (baseInfoId != null) {
            for (PlaceCategoryExtendColumn extendColumn : listData) {
                String id = DigestUtils.md5Hex(String.format("%s@%s", baseInfoId, extendColumn.getId()));
                PlaceBaseInfoExtend extend = this.placeBaseInfoExtendService.getById(id);
                if (extend != null) {
                    extendColumn.setFieldValue(extend.getFieldValue());
                }
            }
        }

        return Result.instance(Result.Code.SUCCESS).setData(listData);
    }

    @ResponseBody
    @PostMapping("/findSelectByKeyword")
    public Result findSelectBaseInfoByKeyword(String keyword) throws Exception {
        QueryWrapper<PlaceBaseInfo> queryWrapper = new QueryWrapper<>();

        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.like("id", keyword);
            queryWrapper.or();
            queryWrapper.like("name", keyword);
            queryWrapper.or();
            queryWrapper.like("brief", keyword);
            queryWrapper.or();
            queryWrapper.like("address", keyword);
            queryWrapper.or();
            queryWrapper.like("contacts", keyword);
            queryWrapper.or();
            queryWrapper.like("contact_number", keyword);
            queryWrapper.or();
            queryWrapper.inSql("category_id", "select id from place_category where name like '%" + keyword + "%'");
        }
        queryWrapper.last("limit 10");
        queryWrapper.orderByDesc("id");

        List<PlaceBaseInfo> listData = this.placeBaseInfoService.list(queryWrapper);
        for (PlaceBaseInfo baseInfo : listData) {
            PlaceCategory category = this.placeCategoryService.getById(baseInfo.getCategoryId());
            baseInfo.setCategory(category);
        }
        return Result.instance(Result.Code.SUCCESS).setData(listData);
    }
}
