package com.liquidnet.client.admin.web.controller.zhengzai.goblin.artist;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.client.admin.common.annotation.Log;
import com.liquidnet.client.admin.common.core.controller.BaseController;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.core.page.TableDataInfo;
import com.liquidnet.client.admin.common.enums.BusinessType;
import com.liquidnet.client.admin.common.utils.ShiroUtils;
import com.liquidnet.client.admin.zhengzai.goblin.service.IGoblinArtistAuthAdminService;
import com.liquidnet.service.goblin.entity.GoblinArtistAuthApply;
import com.liquidnet.service.goblin.entity.GoblinStoreInfo;
import com.liquidnet.service.goblin.mapper.GoblinStoreInfoMapper;
import com.liquidnet.service.kylin.entity.KylinArtist;
import com.liquidnet.service.kylin.mapper.KylinArtistMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.liquidnet.client.admin.web.controller.zhengzai.goblin.artist.ArtistAdminHelper.*;

@Controller
@RequestMapping("goblin/artist/auth")
public class GoblinArtistAuthAdminController extends BaseController {
    private final String prefix = "zhengzai/goblin/artist/auth";

    @Autowired
    private IGoblinArtistAuthAdminService authAdminService;
    @Autowired
    private KylinArtistMapper kylinArtistMapper;
    @Autowired
    private GoblinStoreInfoMapper storeInfoMapper;

    @GetMapping()
    public String index() {
        return prefix + "/auth";
    }

    @RequiresPermissions("goblin:artist:auth:list")
    @RequestMapping("/list")
    @ResponseBody
    public TableDataInfo list(GoblinArtistAuthApply apply,
                              @RequestParam(required = false) String artistName,
                              @RequestParam(required = false) String storeName) {
        LambdaQueryWrapper<GoblinArtistAuthApply> qw = Wrappers.lambdaQuery(GoblinArtistAuthApply.class);
        if (apply.getStatus() != null) {
            qw.eq(GoblinArtistAuthApply::getStatus, apply.getStatus());
        }
        List<String> sids = findStoreIds(storeInfoMapper, storeName);
        if (sids != null) {
            if (sids.isEmpty()) return getDataTable(Collections.emptyList());
            qw.in(GoblinArtistAuthApply::getStoreId, sids);
        }
        List<String> aids = findArtistIds(kylinArtistMapper, artistName);
        if (aids != null) {
            if (aids.isEmpty()) return getDataTable(Collections.emptyList());
            qw.in(GoblinArtistAuthApply::getArtistId, aids);
        }
        qw.orderByDesc(GoblinArtistAuthApply::getCreatedAt);
        startPage();
        return getDataTable(withNames(authAdminService.list(qw)));
    }

    private List<Map<String, Object>> withNames(List<GoblinArtistAuthApply> list) {
        if (list.isEmpty()) return Collections.emptyList();
        Map<String, String> storeNames = storeNameMap(storeInfoMapper, idsOf(list, GoblinArtistAuthApply::getStoreId));
        Map<String, String> artistNames = artistNameMap(kylinArtistMapper, idsOf(list, GoblinArtistAuthApply::getArtistId));

        return list.stream().map(item -> {
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("applyId", item.getApplyId());
            row.put("storeId", item.getStoreId());
            row.put("storeName", storeNames.get(item.getStoreId()));
            row.put("artistId", item.getArtistId());
            row.put("artistName", artistNames.get(item.getArtistId()));
            row.put("status", item.getStatus());
            row.put("createdAt", formatTime(item.getCreatedAt()));
            row.put("reviewTime", formatTime(item.getReviewTime()));
            row.put("reviewerName", item.getReviewerName());
            row.put("authExpireAt", formatTime(item.getAuthExpireAt()));
            return row;
        }).collect(Collectors.toList());
    }

    @RequiresPermissions("goblin:artist:auth:info")
    @GetMapping("detail/{applyId}")
    @ResponseBody
    public AjaxResult detail(@PathVariable String applyId) {
        Map<String, Object> data = buildDetail(applyId);
        if (data == null) return AjaxResult.error("申请不存在");
        return AjaxResult.success(data);
    }

    @RequiresPermissions("goblin:artist:auth:info")
    @GetMapping("detailView/{applyId}")
    public String detailView(@PathVariable String applyId, ModelMap mmap) {
        Map<String, Object> data = buildDetail(applyId);
        if (data == null) return prefix + "/auth";
        mmap.put("apply", data);
        return prefix + "/detail";
    }

    private Map<String, Object> buildDetail(String applyId) {
        GoblinArtistAuthApply apply = authAdminService.getOne(
                new LambdaQueryWrapper<GoblinArtistAuthApply>()
                        .eq(GoblinArtistAuthApply::getApplyId, applyId).last("limit 1"));
        if (apply == null) return null;

        KylinArtist artist = kylinArtistMapper.selectOne(
                new LambdaQueryWrapper<KylinArtist>()
                        .eq(KylinArtist::getArtistId, apply.getArtistId()).last("limit 1"));
        GoblinStoreInfo store = storeInfoMapper.selectOne(
                new LambdaQueryWrapper<GoblinStoreInfo>()
                        .eq(GoblinStoreInfo::getStoreId, apply.getStoreId()).last("limit 1"));

        Map<String, Object> data = new LinkedHashMap<>();
        data.put("applyId", apply.getApplyId());
        data.put("status", apply.getStatus());
        data.put("createdAt", apply.getCreatedAt());
        data.put("applyTime", formatTime(apply.getCreatedAt()));
        data.put("artistId", apply.getArtistId());
        data.put("artistName", artist != null ? artist.getArtistName() : null);
        data.put("storeId", apply.getStoreId());
        data.put("storeName", store != null ? store.getStoreName() : null);
        data.put("reviewerName", apply.getReviewerName());
        data.put("reviewTime", formatTime(apply.getReviewTime()));
        data.put("reviewRemark", apply.getReviewRemark());
        data.put("rejectReason", apply.getRejectReason());
        data.put("authExpireAt", formatTime(apply.getAuthExpireAt()));

        List<String> urls = new ArrayList<>();
        if (StringUtils.isNotBlank(apply.getAttachmentUrls())) {
            try {
                urls = JsonUtils.fromJson(apply.getAttachmentUrls(), new TypeReference<List<String>>() {});
            } catch (Exception ignored) {}
        }
        data.put("attachmentUrls", urls != null ? urls : Collections.emptyList());
        return data;
    }

    @Log(title = "艺人授权:通过", businessType = BusinessType.UPDATE)
    @RequiresPermissions("goblin:artist:auth:approve")
    @PostMapping("approve")
    @ResponseBody
    public AjaxResult approve(@RequestParam String applyId,
                              @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime expireAt,
                              @RequestParam(required = false) String remark) {
        String reviewerName = ShiroUtils.getLoginName();
        String reviewerId = ShiroUtils.getUserId().toString();
        return toAjax(authAdminService.approve(applyId, expireAt, remark, reviewerId, reviewerName));
    }

    @Log(title = "艺人授权:驳回", businessType = BusinessType.UPDATE)
    @RequiresPermissions("goblin:artist:auth:reject")
    @PostMapping("reject")
    @ResponseBody
    public AjaxResult reject(@RequestParam String applyId, @RequestParam String reason) {
        String reviewerName = ShiroUtils.getLoginName();
        String reviewerId = ShiroUtils.getUserId().toString();
        return toAjax(authAdminService.reject(applyId, reason, reviewerId, reviewerName));
    }
}
