package com.yc.ship.module.trade.controller.app.order;

import com.yc.ship.framework.common.pojo.CommonResult;
import com.yc.ship.framework.operatelog.core.annotations.OperateLog;
import com.yc.ship.module.trade.controller.admin.order.vo.order.PayOrderReqVO;
import com.yc.ship.module.trade.controller.admin.order.vo.order.PayOrderRespVO;
import com.yc.ship.module.trade.framework.annotation.PlatTenantEnv;
import com.yc.ship.module.trade.service.pay.TradeOrderPayService;
import com.yc.ship.module.trade.service.refund.TradeRefundService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.*;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import static com.yc.ship.framework.operatelog.core.enums.OperateTypeEnum.TRADE;


/**
 * &#064;Description ：交易服务controller
 *
 * @author ：qsl
 * &#064;Date ：2025/6/17 20:52
 */
@Tag(name = "交易服务controller")
@RestController
@RequestMapping("/trade")
@Validated
@Slf4j
public class TradeOrderController {

    @Resource
    private TradeRefundService tradeRefundService;
    @Resource
    private TradeOrderPayService tradeOrderPayService;


    @PostMapping("/payNotify")
    @Operation(summary = "支付通知")
    @OperateLog(type = TRADE)
    public String payNotify(@RequestParam Map<String, Object> map) {
        CommonResult<?> commonResult = tradeOrderPayService.handlePayNotify(map);
        log.error("支付成功通知，参数{},返回参数{}", map, commonResult.isSuccess());
        return commonResult.isSuccess() ? "success" : "fail";
    }

    @PostMapping("/deposiPayNotify")
    @Operation(summary = "定金支付通知")
    @OperateLog(type = TRADE)
    public String deposiPayNotify(@RequestParam Map<String, Object> map) {
        CommonResult<?> commonResult = tradeOrderPayService.handleDeposiPayNotify(map);
        log.error("定金支付通知，参数{},返回参数{}", map, commonResult.isSuccess());
        return commonResult.isSuccess() ? "success" : "fail";
    }

    @PostMapping("/bcPayNotify")
    @Operation(summary = "补缴费用支付通知")
    @OperateLog(type = TRADE)
    public String bcPayNotify(@RequestParam Map<String, Object> map) {
        CommonResult<?> commonResult = tradeOrderPayService.handleBcPayNotify(map);
        log.error("补差价支付通知，参数{},返回参数{}", map, commonResult.isSuccess());
        return commonResult.isSuccess() ? "success" : "fail";
    }

    @PostMapping("/refundNotify")
    @Operation(summary = "退款通知")
    @OperateLog(type = TRADE)
    public String refundNotify(@RequestParam Map<String, Object> map) {
        CommonResult<?> commonResult = tradeRefundService.handleRefundNotify(map);
        return commonResult.isSuccess() ? "success" : "fail";
    }

    @GetMapping("/payOrderQuery")
    @Operation(summary = "支付反查，0待支付(轮询) 1已支付 2未支付 8888已支付等待结果(轮询) ")
    @OperateLog(type = TRADE)
    @PlatTenantEnv
    public CommonResult<?> payOrderQuery(@RequestParam Long payOrderId) {
        return tradeOrderPayService.payOrderQuery(payOrderId);
    }

    @GetMapping("/queryOrderContract")
    @Operation(summary = "查询合同URL")
    @OperateLog(type = TRADE)
    @PlatTenantEnv
    public CommonResult<?> queryOrderContract(@RequestParam Long payOrderId) {
        return tradeOrderPayService.queryOrderContract(payOrderId);
    }

    @PostMapping("/payOuterOrder")
    @Operation(summary = "外部订单支付")
    @OperateLog(type = TRADE)
    public CommonResult<PayOrderRespVO> payOuterOrder(@Valid @RequestBody PayOrderReqVO payOrderReqVO) {
        CommonResult<PayOrderRespVO> commonResult = tradeOrderPayService.payOuterOrder(payOrderReqVO);
        return commonResult;
    }


    @GetMapping("/test")
    @Operation(summary = "测试报文发送")
    @OperateLog(type = TRADE)
    public String test() {
        try {
            String serverAddress = "10.1.10.105";
            // 服务器地址
            int serverPort = 15999;
            // 服务器端口号
            // 1. 获取当前时间，用于组装公共包头流水与日期
            Date now = new Date();
            String reqDate = new SimpleDateFormat("yyyyMMdd").format(now);
            String reqTime = new SimpleDateFormat("HHmmss").format(now);
            // 构造请求方流水号 (保证唯一性)
            String reqSeqNo = new SimpleDateFormat("yyyyMMddHHmmss").format(now) + "0001";
//            File socketDataFile = new File("/data/publish/yl-ota/a.xml");
//            if (!socketDataFile.exists()) {
//                System.err.println("输入文件路径不存在！");
//                return "输入文件路径不存在！";
//            }
//            //1。读取上送文件
//            String xmlData = FileDeal.fileRead(socketDataFile);
//        String xmlData = "<ap>\n" +
//                "    <CCTransCode>CMLT40</CCTransCode>\n" +
//                "    <Corp>\n" +
//                "        <DbLogAccName>测试2</DbLogAccName>\n" +
//                "        <IntTyp>2</IntTyp>\n" +
//                "        <DbIntType>V</DbIntType>\n" +
//                "        <DbRatType>0</DbRatType>\n" +
//                "        <DbAddType>C1</DbAddType>\n" +
//                "        <DbRatAdd>1</DbRatAdd>\n" +
//                "        <CrIntType>V</CrIntType>\n" +
//                "        <CrAddType>C1</CrAddType>\n" +
//                "        <CrRatType>00002000</CrRatType>\n" +
//                "        <CrRatAdd>0</CrRatAdd>\n" +
//                "        <PmtHd>01</PmtHd>\n" +
//                "        <ActInf>1</ActInf>\n" +
//                "    </Corp>\n" +
//                "    <Cmp>\n" +
//                "        <DbProv>17</DbProv>\n" +
//                "        <DbAccNo>000000</DbAccNo>\n" +
//                "        <DbCur>CNY</DbCur>\n" +
//                "        <CrLogAccNo>000000</CrLogAccNo>\n" +
//                "        <DbLogAccNo>000000</DbLogAccNo>\n" +
//                "        <LogAccBkOInd>1</LogAccBkOInd>\n" +
//                "        <AuthAmt>1000</AuthAmt>\n" +
//                "        <StatInd>1</StatInd>\n" +
//                "    </Cmp>\n" +
//                "</ap>"; // XML数据字符串（如上所示）
            String xmlData = "<ap>\n" +
                    "  <CCTransCode>CMLT40</CCTransCode>\n" +
                    "  <ProductID>ICC</ProductID>\n" +
                    "  <ChannelType>ERP</ChannelType>\n" +
                    "  <CorpNo>17999953800000028</CorpNo>\n" +
                    "  <OpNo></OpNo>\n" +
                    "  <AuthNo></AuthNo>\n" +
                    "  <ReqSeqNo>" + reqSeqNo + "</ReqSeqNo>\n" +
                    "  <ReqDate>" + reqDate + "</ReqDate>\n" +
                    "  <ReqTime>" + reqTime + "</ReqTime>\n" +
                    "  <Sign></Sign>\n" +
                    "  <Corp>\n" +
                    "    <DbLogAccName>1</DbLogAccName>\n" +
                    "    <IntTyp>0</IntTyp>\n" +
                    "    <DbIntType>F</DbIntType>\n" +
                    "    <DbRit>0.00</DbRit>\n" +
                    "    <DbAddType>1</DbAddType>\n" +
                    "    <DbRatType>00002000</DbRatType>\n" +
                    "    <DbRatPct>0.00</DbRatPct>\n" +
                    "    <DbRatAdd>0.00</DbRatAdd>\n" +
                    "    <CrIntType>F</CrIntType>\n" +
                    "    <CrRit>0.00</CrRit>\n" +
                    "    <CrAddType>1</CrAddType>\n" +
                    "    <CrRatType>00002000</CrRatType>\n" +
                    "    <CrRatPct>0.00</CrRatPct>\n" +
                    "    <CrRatAdd>0.00</CrRatAdd>\n" +
                    "    <PmtHd>01</PmtHd>\n" +
                    "    <ActInf>0</ActInf>\n" +
                    "  </Corp>\n" +
                    "  <Cmp>\n" +
                    "    <DbProv>17</DbProv>\n" +
                    "    <DbAccNo>342101046484369</DbAccNo>\n" +
                    "    <DbCur>01</DbCur>\n" +
                    "    <CrLogAccNo>0000000000</CrLogAccNo>\n" +
                    "    <LogAccBkOInd>0</LogAccBkOInd>\n" +
                    "  </Cmp>\n" +
                    "</ap>";

            // 3. 按照约定编码报文 (ERP上送报文必须为GBK字符集)
            byte[] xmlBytes = xmlData.getBytes("GBK");

            // 4. 构造7字节包头
            // 第1字节为加密标志（0-不加密），后6字节为数据包长度（包含加密标志位），不足6位在右边用空格补足
            int packetLen = xmlBytes.length;
            String lengthStr = String.format("%-6s", packetLen);
            String headerStr = "0" + lengthStr;
            byte[] headerBytes = headerStr.getBytes("GBK");

            // 拼接完整的待发送字节数组
            byte[] fullPacket = new byte[headerBytes.length + xmlBytes.length];
            System.arraycopy(headerBytes, 0, fullPacket, 0, headerBytes.length);
            System.arraycopy(xmlBytes, 0, fullPacket, headerBytes.length, xmlBytes.length);

            Socket socket = new Socket(serverAddress, serverPort);
            // 连接成功后的处理逻辑
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(fullPacket);
            outputStream.flush();

            BufferedReader clientInBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
            String clinetInStr = null;
            String clinetInStrData = null;
            while ((clinetInStrData = clientInBufferedReader.readLine()) != null) {
                clinetInStr = clinetInStr + clinetInStrData;
            }
            System.err.println(clinetInStr);
            socket.close();
            SAXReader sax = new SAXReader();
            Document inClinetDoc = sax.read(new StringReader(clinetInStr.substring(clinetInStr.indexOf("<"))));
            String formatReDoc = null;
            if (inClinetDoc != null) {
                StringWriter strWriter = new StringWriter();
                OutputFormat format = new OutputFormat("  ", true);
                format.setNewLineAfterDeclaration(false);
                XMLWriter writer = new XMLWriter(strWriter, format);
                writer.write(inClinetDoc);
                writer.flush();
                writer.close();
                formatReDoc = strWriter.getBuffer().toString();
                System.err.println("返回报文:" + clinetInStr);
                String txa_return_data = "返回报文:" + "\n" + clinetInStr.substring(0, clinetInStr.indexOf("<")) + formatReDoc;
                System.err.println(txa_return_data);
                return txa_return_data;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "失败";
    }

}
