package com.ruoyi.lsfx.client;

import com.ruoyi.lsfx.constants.LsfxConstants;
import com.ruoyi.lsfx.domain.request.DeleteFilesRequest;
import com.ruoyi.lsfx.domain.request.FetchInnerFlowRequest;
import com.ruoyi.lsfx.domain.request.GetBankStatementRequest;
import com.ruoyi.lsfx.domain.request.GetFileUploadStatusRequest;
import com.ruoyi.lsfx.domain.request.GetTokenRequest;
import com.ruoyi.lsfx.domain.response.*;
import com.ruoyi.lsfx.exception.LsfxApiException;
import com.ruoyi.lsfx.util.HttpUtil;
import com.ruoyi.lsfx.util.MD5Util;
import com.ruoyi.lsfx.util.ObjectUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 流水分析平台客户端
 */
@Slf4j
@Component
public class LsfxAnalysisClient {

    @Resource
    private HttpUtil httpUtil;

    @Value("${lsfx.api.base-url}")
    private String baseUrl;

    @Value("${lsfx.api.app-id}")
    private String appId;

    @Value("${lsfx.api.app-secret}")
    private String appSecret;

    @Value("${lsfx.api.client-id}")
    private String clientId;

    @Value("${lsfx.api.endpoints.get-token}")
    private String getTokenEndpoint;

    @Value("${lsfx.api.endpoints.upload-file}")
    private String uploadFileEndpoint;

    @Value("${lsfx.api.endpoints.fetch-inner-flow}")
    private String fetchInnerFlowEndpoint;

    @Value("${lsfx.api.endpoints.check-parse-status}")
    private String checkParseStatusEndpoint;

    @Value("${lsfx.api.endpoints.get-bank-statement}")
    private String getBankStatementEndpoint;

    @Value("${lsfx.api.endpoints.get-file-upload-status}")
    private String getFileUploadStatusEndpoint;

    @Value("${lsfx.api.endpoints.delete-files}")
    private String deleteFilesEndpoint;

    /**
     * 获取Token
     */
    public GetTokenResponse getToken(GetTokenRequest request) {
        log.info("【流水分析】获取Token请求: projectNo={}, entityName={}", request.getProjectNo(), request.getEntityName());
        long startTime = System.currentTimeMillis();

        try {
            String secretCode = MD5Util.generateSecretCode(
                request.getProjectNo(),
                request.getEntityName(),
                appSecret
            );

            // 构建form-data参数（使用ObjectUtil简化代码）
            Map<String, Object> params = ObjectUtil.toMapIgnoreNull(request);
            // 添加特殊字段
            params.put("appId", appId);
            params.put("appSecretCode", secretCode);
            params.put("role", request.getRole() != null ? request.getRole() : LsfxConstants.DEFAULT_ROLE);
            params.put("analysisType", request.getAnalysisType() != null ? request.getAnalysisType() : LsfxConstants.ANALYSIS_TYPE);

            String url = baseUrl + getTokenEndpoint;
            GetTokenResponse response = httpUtil.postFormData(url, params, null, GetTokenResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】获取Token成功: projectId={}, 耗时={}ms", response.getData().getProjectId(), elapsed);
            } else {
                log.warn("【流水分析】获取Token响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】获取Token失败: projectNo={}, error={}", request.getProjectNo(), e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】获取Token未知异常: projectNo={}", request.getProjectNo(), e);
            throw new LsfxApiException("获取Token失败: " + e.getMessage(), e);
        }
    }

    /**
     * 上传文件
     */
    public UploadFileResponse uploadFile(Integer groupId, File file) {
        return uploadFile(groupId, file, file.getName());
    }

    /**
     * 上传文件
     */
    public UploadFileResponse uploadFile(Integer groupId, File file, String uploadFileName) {
        String multipartFileName = StringUtils.hasText(uploadFileName) ? uploadFileName : file.getName();
        log.info("【流水分析】上传文件请求: groupId={}, fileName={}", groupId, multipartFileName);
        long startTime = System.currentTimeMillis();

        try {
            String url = baseUrl + uploadFileEndpoint;

            Map<String, Object> params = new HashMap<>();
            params.put("groupId", groupId);
            params.put("files", HttpUtil.namedFileResource(file, multipartFileName));

            Map<String, String> headers = new HashMap<>();
            headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

            UploadFileResponse response = httpUtil.uploadFile(url, params, headers, UploadFileResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】上传文件成功: uploadStatus={}, 耗时={}ms",
                    response.getData().getUploadStatus(), elapsed);
            } else {
                log.warn("【流水分析】上传文件响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】上传文件失败: groupId={}, error={}", groupId, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】上传文件未知异常: groupId={}", groupId, e);
            throw new LsfxApiException("上传文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 拉取行内流水
     */
    public FetchInnerFlowResponse fetchInnerFlow(FetchInnerFlowRequest request) {
        log.info("【流水分析】拉取行内流水请求: groupId={}, customerNo={}", request.getGroupId(), request.getCustomerNo());
        long startTime = System.currentTimeMillis();

        try {
            String url = baseUrl + fetchInnerFlowEndpoint;

            // 构建form-data参数（使用ObjectUtil简化代码）
            Map<String, Object> params = ObjectUtil.toMapIgnoreNull(request);

            Map<String, String> headers = new HashMap<>();
            headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

            FetchInnerFlowResponse response = httpUtil.postFormData(url, params, headers, FetchInnerFlowResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】拉取行内流水完成: logId={},耗时={}ms", response.getData(), elapsed);
            } else {
                log.warn("【流水分析】拉取行内流水响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】拉取行内流水失败: groupId={}, error={}", request.getGroupId(), e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】拉取行内流水未知异常: groupId={}", request.getGroupId(), e);
            throw new LsfxApiException("拉取行内流水失败: " + e.getMessage(), e);
        }
    }

    /**
     * 检查文件解析状态
     */
    public CheckParseStatusResponse checkParseStatus(Integer groupId, String inprogressList) {
        log.info("【流水分析】检查文件解析状态: groupId={}, inprogressList={}", groupId, inprogressList);
        long startTime = System.currentTimeMillis();

        try {
            String url = baseUrl + checkParseStatusEndpoint;

            // 构建form-data参数
            Map<String, Object> params = new HashMap<>();
            params.put("groupId", groupId);
            params.put("inprogressList", inprogressList);

            Map<String, String> headers = new HashMap<>();
            headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

            CheckParseStatusResponse response = httpUtil.postFormData(url, params, headers, CheckParseStatusResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】检查解析状态完成: parsing={}, pendingList.size={}, 耗时={}ms",
                    response.getData().getParsing(),
                    response.getData().getPendingList() != null ? response.getData().getPendingList().size() : 0,
                    elapsed);
            } else {
                log.warn("【流水分析】检查解析状态响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】检查解析状态失败: groupId={}, error={}", groupId, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】检查解析状态未知异常: groupId={}", groupId, e);
            throw new LsfxApiException("检查解析状态失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取银行流水(新版接口)
     * 注意: 需要传入logId参数,参数名已从pageNum改为pageNow
     *
     * @param request 请求参数(groupId, logId, pageNow, pageSize)
     * @return 流水明细列表
     */
    public GetBankStatementResponse getBankStatement(GetBankStatementRequest request) {
        log.info("【流水分析】获取银行流水请求: groupId={}, logId={}, pageNow={}, pageSize={}",
            request.getGroupId(), request.getLogId(), request.getPageNow(), request.getPageSize());
        long startTime = System.currentTimeMillis();

        try {
            String url = baseUrl + getBankStatementEndpoint;

            // 构建form-data参数（使用ObjectUtil简化代码）
            Map<String, Object> params = ObjectUtil.toMapIgnoreNull(request);

            Map<String, String> headers = new HashMap<>();
            headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

            GetBankStatementResponse response = httpUtil.postFormData(url, params, headers, GetBankStatementResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】获取银行流水成功: totalCount={}, 耗时={}ms",
                    response.getData().getTotalCount(), elapsed);
            } else {
                log.warn("【流水分析】获取银行流水响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】获取银行流水失败: groupId={}, logId={}, error={}",
                request.getGroupId(), request.getLogId(), e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】获取银行流水未知异常: groupId={}, logId={}",
                request.getGroupId(), request.getLogId(), e);
            throw new LsfxApiException("获取银行流水失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取单个文件上传状态(接口5)
     * 用途: 获取文件解析后的主体名称和账号等信息
     *
     * 关键判断:
     * - status=-5 且 uploadStatusDesc="data.wait.confirm.newaccount" 表示解析成功
     * - enterpriseNameList仅有一个空字符串""时,表示流水文件未生成主体
     *
     * @param request 请求参数(groupId必填, logId可选)
     * @return 文件上传状态信息
     */
    public GetFileUploadStatusResponse getFileUploadStatus(GetFileUploadStatusRequest request) {
        log.info("【流水分析】获取文件上传状态: groupId={}, logId={}",
            request.getGroupId(), request.getLogId());
        long startTime = System.currentTimeMillis();

        try {
            String url = baseUrl + getFileUploadStatusEndpoint;

            // GET请求,构建查询参数
            Map<String, Object> params = new HashMap<>();
            params.put("groupId", request.getGroupId());
            if (request.getLogId() != null) {
                params.put("logId", request.getLogId());
            }

            Map<String, String> headers = new HashMap<>();
            headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

            GetFileUploadStatusResponse response = httpUtil.get(url, params, headers,
                GetFileUploadStatusResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】获取文件上传状态成功: logId数量={}, 耗时={}ms",
                    response.getData().getLogs() != null ? response.getData().getLogs().size() : 0,
                    elapsed);
            } else {
                log.warn("【流水分析】获取文件上传状态响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】获取文件上传状态失败: groupId={}, error={}",
                request.getGroupId(), e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】获取文件上传状态未知异常: groupId={}",
                request.getGroupId(), e);
            throw new LsfxApiException("获取文件上传状态失败: " + e.getMessage(), e);
        }
    }

    /**
     * 删除文件/主体(接口6)
     * 用途: 删除解析失败或不需要的流水文件
     *
     * 使用场景:
     * - 文件解析失败时清理文件
     * - 删除错误上传的文件
     *
     * @param request 请求参数(groupId, logIds, userId必填)
     * @return 删除结果
     */
    public DeleteFilesResponse deleteFiles(DeleteFilesRequest request) {
        log.info("【流水分析】删除文件请求: groupId={}, logIds={}, userId={}",
            request.getGroupId(), Arrays.toString(request.getLogIds()), request.getUserId());
        long startTime = System.currentTimeMillis();

        try {
            String url = baseUrl + deleteFilesEndpoint;

            // 构建form-data参数
            Map<String, Object> params = new HashMap<>();
            params.put("groupId", request.getGroupId());
            params.put("logIds", request.getLogIds());  // 数组
            params.put("userId", request.getUserId());

            Map<String, String> headers = new HashMap<>();
            headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);

            DeleteFilesResponse response = httpUtil.postFormData(url, params, headers,
                DeleteFilesResponse.class);

            long elapsed = System.currentTimeMillis() - startTime;
            if (response != null && response.getData() != null) {
                log.info("【流水分析】删除文件成功: message={}, 耗时={}ms",
                    response.getData().getMessage(), elapsed);
            } else {
                log.warn("【流水分析】删除文件响应异常: 耗时={}ms", elapsed);
            }

            return response;
        } catch (LsfxApiException e) {
            log.error("【流水分析】删除文件失败: groupId={}, error={}",
                request.getGroupId(), e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("【流水分析】删除文件未知异常: groupId={}",
                request.getGroupId(), e);
            throw new LsfxApiException("删除文件失败: " + e.getMessage(), e);
        }
    }
}
