package com.chinaweal.aiccs.door.service.impl;

import com.alibaba.fastjson.JSON;
import com.chinaweal.aiccs.aiccs.business.entity.TSTaskList;
import com.chinaweal.aiccs.aiccs.business.service.TSTaskListService;
import com.chinaweal.aiccs.common.constant.BaseDataConstant;
import com.chinaweal.aiccs.door.dto.JgmhDebugPushResult;
import com.chinaweal.aiccs.door.entity.PortalTodoPushRecord;
import com.chinaweal.aiccs.door.service.IJgmhPortalTodoService;
import com.chinaweal.aiccs.door.service.PortalTodoPushRecordService;
import com.chinaweal.aiccs.outside.api.JgmhDoorApi;
import com.chinaweal.aiccs.outside.dto.JgmhTodoItemDto;
import com.chinaweal.aiccs.outside.dto.JgmhTodoRequestDto;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aiccs.redis.RedisService;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.dtflys.forest.http.ForestResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class JgmhPortalTodoServiceImpl implements IJgmhPortalTodoService {

    @Value("${jgmhDoor.enableTask}")
    private boolean enableTask;
    @Value("${jgmhDoor.appId}")
    private String appId;
    @Value("${jgmhDoor.redirectUrl}")
    private String redirectUrl;
    @Value("${jgmhDoor.mobileRedirectUrl:}")
    private String mobileRedirectUrl;

    @Resource
    private JgmhDoorApi jgmhDoorApi;
    @Resource
    private PortalTodoPushRecordService pushRecordService;
    @Resource
    private TSTaskListService taskListService;
    @Resource
    private TUsersService tUsersService;
    @Resource
    private RedisService redisService;

    private static final String TOKEN_CACHE_KEY = "JGMH_DOOR_TOKEN";

    /**
     * 信用修复业务类型白名单
     * 与 TSTaskListMapper.xml 中 repairTaskQuery 的过滤条件保持一致
     */
    private static final List<String> CREDIT_REPAIR_BUSTYPES = Arrays.asList(
            BaseDataConstant.EXPTLIST_TYPE_REMOVE,              // "7"  企业经营异常名录信用修复
            BaseDataConstant.EXPTLIST_TYPE_INDIVIDUAL_RESTORE,  // "12" 个体户经营异常名录信用修复
            BaseDataConstant.EXPTLIST_TYPE_FARMER_REMOVE,       // "14" 农专社经营异常名录信用修复
            BaseDataConstant.CREDIT_REPAIR_ILLEGAL_BIZ,         // "33" 严重违法失信信用修复
            BaseDataConstant.BUSINESS_TYPE_REM_PUNISH           // "27" 行政处罚信用修复
    );

    /** 外网申请标识 */
    private static final String ORIGIN_OUTER = "1";

    /** 待受理状态 */
    private static final String BUSSTATUS_TOSIGN = BaseDataConstant.BUSINESS_STATUS_TOSIGN; // "-1"

    /**
     * 获取token（带Redis缓存，有效期2小时，提前刷新）
     */
    public String getToken() {
        String token = redisService.get(TOKEN_CACHE_KEY);
        if (StringUtils.isNotBlank(token)) {
            return token;
        }

        ForestResponse<String> response = jgmhDoorApi.getToken();
        if (response.isSuccess()) {
            token = response.getResult().trim();
            redisService.set(TOKEN_CACHE_KEY, token, 7000);
            return token;
        }
        throw new BusinessException("获取统一监管门户token失败: " + response.getResult());
    }

    /**
     * 获取本地用户对应的统一监管门户用户ID
     * 映射链路：signuserid → t_users.IMSUSERCODE → USERSID
     */
    private String getPortalUserId(String localUserId) {
        TUsers tUser = tUsersService.getById(localUserId);
        if (tUser == null || StringUtils.isBlank(tUser.getImsusercode())) {
            return null;
        }
        return tUser.getImsusercode();
    }

    /**
     * 创建待推送记录（工作流启动时调用）
     *
     * 三重过滤条件：
     * 1. BUSTYPE in ('7','12','14','33','27') — 信用修复业务
     * 2. ORIGIN = '1'                         — 外网申请
     * 3. BUSSTATUS = '-1'                      — 待受理状态
     *
     * 三个条件必须同时满足，任一不满足则跳过
     */
    @Override
    public void createPushRecord(TSTaskList taskListModel) {
        if (!enableTask) return;

        // 过滤条件1：仅限信用修复业务
        if (!CREDIT_REPAIR_BUSTYPES.contains(taskListModel.getBustype())) {
            log.debug("统一监管门户待办推送：非信用修复业务，跳过。tasklistid={}, bustype={}",
                    taskListModel.getTasklistid(), taskListModel.getBustype());
            return;
        }

        // 过滤条件2：仅限外网申请
        if (!ORIGIN_OUTER.equals(taskListModel.getOrigin())) {
            log.debug("统一监管门户待办推送：非外网申请，跳过。tasklistid={}, origin={}",
                    taskListModel.getTasklistid(), taskListModel.getOrigin());
            return;
        }

        // 过滤条件3：仅限待受理状态
        if (!BUSSTATUS_TOSIGN.equals(taskListModel.getBusstatus())) {
            log.debug("统一监管门户待办推送：非待受理状态，跳过。tasklistid={}, busstatus={}",
                    taskListModel.getTasklistid(), taskListModel.getBusstatus());
            return;
        }

        // 获取门户用户ID
        String portalUserId = getPortalUserId(taskListModel.getSignuserid());
        if (portalUserId == null) {
            log.info("统一监管门户待办推送：用户未关联IMS账号，signuserid={}", taskListModel.getSignuserid());
            return;
        }

        // 创建推送记录
        // DBSXID 使用 tasklistid（因为只有2步且无回退，不存在多人共享问题）
        PortalTodoPushRecord record = new PortalTodoPushRecord();
        record.setTasklistid(taskListModel.getTasklistid());
        record.setBustype(taskListModel.getBustype());
        record.setDbsxid(taskListModel.getTasklistid());
        record.setDbsxmc(taskListModel.getBusname());
        record.setDbsxzt(1); // 待办
        record.setUsersid(portalUserId);
        record.setPushstatus("0"); // 待推送
        record.setPushcount(0);
        record.setCreatetime(LocalDateTime.now());
        record.setUpdatetime(LocalDateTime.now());
        pushRecordService.save(record);

        log.info("统一监管门户待办推送：创建推送记录，tasklistid={}, bustype={}, usersid={}",
                taskListModel.getTasklistid(), taskListModel.getBustype(), portalUserId);
    }

    /**
     * 用户点击"办理"后调用，将待办标记为已办
     *
     * 调用时机：TSTaskListServiceImpl.updateWorkFlow() 中 busstatus 从 "-1"（待受理）变为 "0"（在办）时
     * 不直接推送，只更新推送记录状态，重置为待推送，下次定时任务推送状态变更
     */
    @Override
    public void onHandleTodo(String tasklistid) {
        if (!enableTask) return;

        PortalTodoPushRecord record = pushRecordService.lambdaQuery()
                .eq(PortalTodoPushRecord::getTasklistid, tasklistid)
                .eq(PortalTodoPushRecord::getDbsxzt, 1) // 当前是待办状态
                .one();

        if (record == null) return;

        record.setDbsxzt(2); // 已办
        record.setPushstatus("0"); // 重置为待推送
        record.setUpdatetime(LocalDateTime.now());
        pushRecordService.updateById(record);

        log.info("统一监管门户待办推送：用户点击办理，标记为已办，tasklistid={}", tasklistid);
    }

    /**
     * 批量推送待办事项（定时任务调用）
     */
    @Override
    public void pushPendingTodoItems() {
        if (!enableTask) return;

        List<PortalTodoPushRecord> pendingRecords = pushRecordService.lambdaQuery()
                .in(PortalTodoPushRecord::getPushstatus, "0", "2")
                .lt(PortalTodoPushRecord::getPushcount, 3)
                .list();

        if (pendingRecords.isEmpty()) {
            log.info("统一监管门户待办推送：无待推送记录");
            return;
        }

        log.info("统一监管门户待办推送：待推送记录数={}", pendingRecords.size());

        String token = getToken();

        List<JgmhTodoItemDto> items = new ArrayList<>();
        for (PortalTodoPushRecord record : pendingRecords) {
            JgmhTodoItemDto item = buildTodoItem(record);
            if (item != null) {
                items.add(item);
            }
        }

        if (items.isEmpty()) {
            log.info("统一监管门户待办推送：无有效推送数据");
            return;
        }

        JgmhTodoRequestDto requestDto = new JgmhTodoRequestDto();
        requestDto.setData(items);

        try {
            ForestResponse<String> response = jgmhDoorApi.pushTodoItems(token, requestDto);
            if (response.isSuccess()) {
                for (PortalTodoPushRecord record : pendingRecords) {
                    record.setPushstatus("1");
                    record.setPushcount(record.getPushcount() + 1);
                    record.setLastpushtime(LocalDateTime.now());
                }
                log.info("统一监管门户待办推送：推送成功，记录数={}", pendingRecords.size());
            } else {
                markAsFailed(pendingRecords, response.getResult());
                log.error("统一监管门户待办推送：推送失败，响应={}", response.getResult());
            }
        } catch (Exception e) {
            markAsFailed(pendingRecords, e.getMessage());
            log.error("统一监管门户待办推送：推送异常", e);
        }

        pushRecordService.updateBatchById(pendingRecords);
    }

    /**
     * 组装推送数据项
     */
    private JgmhTodoItemDto buildTodoItem(PortalTodoPushRecord record) {
        TSTaskList taskList = taskListService.getById(record.getTasklistid());

        JgmhTodoItemDto item = new JgmhTodoItemDto();
        item.setDBSXID(record.getDbsxid());
        item.setDBSXMC(record.getDbsxmc());

        if (taskList != null) {
            item.setXXSM(taskList.getLinkname() + " - " + taskList.getBusname());
            item.setCJSJ(formatDateTime(taskList.getSendertime()));
            item.setJZSJ(formatDateTime(taskList.getDeadlineDate()));
        } else {
            record.setPushstatus("2");
            record.setPushcount(3);
            record.setPushmessage("关联的tstasklist记录不存在");
            record.setLastpushtime(LocalDateTime.now());
            return null;
        }

        item.setDBSXZT(record.getDbsxzt());
        item.setUSERSID(record.getUsersid());
        item.setDBDZURL(redirectUrl);
        item.setYDDDBURL(mobileRedirectUrl);
        item.setLYXTAPPID(appId);

        return item;
    }

    private void markAsFailed(List<PortalTodoPushRecord> records, String message) {
        for (PortalTodoPushRecord record : records) {
            record.setPushstatus("2");
            record.setPushcount(record.getPushcount() + 1);
            record.setPushmessage(message != null && message.length() > 500
                    ? message.substring(0, 500) : message);
            record.setLastpushtime(LocalDateTime.now());
        }
    }

    private String formatDateTime(LocalDateTime dateTime) {
        if (dateTime == null) return "";
        return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 【调试用】单笔推送指定 tasklistid 对应的待办数据到统一监管门户
     *
     * - 绕过三重过滤（不校验 bustype/origin/busstatus），可推送任意一笔待办
     * - 同步直接调用门户接口，不走定时任务
     * - 不写入推送记录表，不污染生产数据
     * - 返回详细的调试信息（请求体、响应体、耗时等）
     */
    @Override
    public JgmhDebugPushResult debugPushSingle(String tasklistid) {
        JgmhDebugPushResult result = new JgmhDebugPushResult();
        long startTime = System.currentTimeMillis();

        try {
            // 1. 校验入参
            if (StringUtils.isBlank(tasklistid)) {
                return result.setSuccess(false).setMessage("tasklistid 不能为空");
            }

            // 2. 查询 tstasklist 记录
            TSTaskList taskList = taskListService.getById(tasklistid);
            if (taskList == null) {
                return result.setSuccess(false)
                        .setMessage("tasklistid=" + tasklistid + " 对应的 tstasklist 记录不存在");
            }
            result.setTaskListPreview(buildTaskListPreview(taskList));

            // 3. 获取门户用户ID
            String portalUserId = getPortalUserId(taskList.getSignuserid());
            if (portalUserId == null) {
                return result.setSuccess(false)
                        .setMessage("当前 tasklistid 的签收人未关联 IMS 账号，无法推送。signuserid="
                                + taskList.getSignuserid());
            }

            // 4. 查询或临时构造推送记录（不写库）
            PortalTodoPushRecord record = pushRecordService.lambdaQuery()
                    .eq(PortalTodoPushRecord::getTasklistid, tasklistid)
                    .last("LIMIT 1")
                    .one();
            if (record == null) {
                record = new PortalTodoPushRecord();
                record.setTasklistid(tasklistid);
                record.setBustype(taskList.getBustype());
                record.setDbsxid(tasklistid);
                record.setDbsxmc(taskList.getBusname());
                record.setDbsxzt(1); // 默认按"待办"推送
                record.setUsersid(portalUserId);
            }

            // 5. 组装推送数据
            JgmhTodoItemDto item = buildTodoItem(record);
            if (item == null) {
                return result.setSuccess(false).setMessage("组装推送数据失败，请查看日志");
            }
            result.setTodoItemPreview(item);

            // 6. 获取 token（脱敏）
            String token = getToken();
            result.setToken(maskToken(token));

            // 7. 调用门户接口
            JgmhTodoRequestDto requestDto = new JgmhTodoRequestDto();
            requestDto.setData(Collections.singletonList(item));
            result.setRequestBody(JSON.toJSONString(requestDto));

            ForestResponse<String> response = jgmhDoorApi.pushTodoItems(token, requestDto);
            result.setHttpStatus(response.getStatusCode());
            result.setResponseBody(response.getResult());

            if (response.isSuccess()) {
                result.setSuccess(true)
                        .setMessage("HTTP 调用成功，请查看 responseBody 确认门户业务返回");
            } else {
                result.setSuccess(false)
                        .setMessage("HTTP 调用失败，HTTP=" + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("调试推送异常，tasklistid={}", tasklistid, e);
            result.setSuccess(false).setMessage("调试推送异常：" + e.getMessage());
        } finally {
            result.setDurationMs(System.currentTimeMillis() - startTime);
        }
        return result;
    }

    /** Token 脱敏：前4位 + **** + 后4位 */
    private String maskToken(String token) {
        if (StringUtils.isBlank(token) || token.length() <= 8) return "****";
        return token.substring(0, 4) + "****" + token.substring(token.length() - 4);
    }

    /** 提取 tstasklist 关键字段用于调试查看 */
    private Map<String, Object> buildTaskListPreview(TSTaskList t) {
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("tasklistid", t.getTasklistid());
        m.put("bustype", t.getBustype());
        m.put("busname", t.getBusname());
        m.put("origin", t.getOrigin());
        m.put("busstatus", t.getBusstatus());
        m.put("signuserid", t.getSignuserid());
        m.put("linkname", t.getLinkname());
        m.put("sendertime", t.getSendertime());
        m.put("deadlineDate", t.getDeadlineDate());
        return m;
    }
}
