package com.friday.custody.controller;

import com.alibaba.fastjson.JSONObject;
import com.friday.custody.common.valid.InsertData;
import com.friday.custody.dto.*;
import com.friday.custody.service.basicService.*;
import com.friday.custody.service.basicService.impl.TenantEscrowAuthorizationInfoServiceImpl;
import com.friday.custody.service.logicService.LogicInternalService;
import com.friday.custody.service.logicService.impl.DaasBuriedPointRecordInfoServiceImpl;
import com.friday.custody.service.tenantService.TenantService;
import com.friday.custody.service.trustService.mailHandleService.multiVersionService.impl.HandlerVersionTxtServiceImpl;
import com.friday.custody.vo.ConvertibleBondsIssuedVo;
import com.friday.custody.vo.TongyiCeliverableBondVo;
import com.friday.custody.vo.TongyiConvertibleBondsVo;
import com.friday.custody.vo.TongyiUnissuedDataVo;
import com.friday.custody.entity.ProductDataEntity;
import com.friday.custody.exception.RRException;
import com.friday.custody.req.ConvertibleBondsIssuedReq;
import com.friday.custody.req.GetDataByTableNameAndSqlReq;
import com.friday.custody.req.MarketToBeIssuedReq;
import com.friday.custody.utils.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;

/**
 * 对内Controller
 */
@RestController
@RequestMapping("/custody/internal")
@Slf4j
@Api("提供给内部使用的接口")
public class WebInternalController {
    @Autowired
    private LogicInternalService logicInternalService;

    @Autowired
    private DaasBuriedPointRecordInfoServiceImpl daasBuriedPointRecordInfoService;

    //    @PostMapping("/saveTenants")
//    @ApiOperation(value = "(单个)租户开立", notes = "用于创建单个租户", httpMethod = "POST")
//    public R saveTenants(@Validated({InsertData.class}) @RequestBody TenantInfoVO vo) {
//        return logicInternalService.saveTenant(vo);
//    }



    @PostMapping("/queryOriginData")
    @ApiOperation(value = "查询原始数据接口", notes = "用于查询原始数据接口", httpMethod = "POST")
    public R queryOriginData(@RequestHeader(value = "admin", required = false)
                             @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                             @RequestHeader(value = "accountKey", required = false)
                             @ApiParam(name = "accountKey", value = "账户Key") String accountKey,
                             @RequestParam(required = false) @ApiParam(name = "type", value = "接口类型") String type,
                             @RequestParam(required = false) @ApiParam(name = "trustNo", value = "托管编号") String trustNo,
                             @RequestParam(required = false) @ApiParam(name = "pageNo", value = "当前页数") Integer pageNo,
                             @RequestParam(required = false) @ApiParam(name = "pageSize", value = "分页条数") Integer pageSize) {
        return logicInternalService.queryOriginData(tenantName, accountKey, type, trustNo, pageNo, pageSize);
    }

    @PostMapping("/initLaterData")
    @ApiOperation(value = "新增表的初始化", notes = "用于新增的单独表的初始化", httpMethod = "POST")
    public R initLaterData(
            @RequestHeader(value = "admin", required = false)
            @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
            @RequestHeader(value = "accountKey", required = false)
            @ApiParam(name = "accountKey", value = "账户Key") String accountKey,
            @RequestParam(required = false) @ApiParam(name = "versionStr", value = "版本号") String versionStr) {
        return logicInternalService.initLaterData(tenantName, accountKey, versionStr);
    }

    @PostMapping("/initByAppointedTrustNoAndMouth")
    public R initByAppointedTrustNoAndMouth(@RequestParam(required = false) @ApiParam(name = "month", value = "更新月数") int month,
                                            @RequestHeader("admin") @ApiParam(name = "admin", value = "租户名(登记编号)") String admin,
                                            @RequestHeader("trustNo") @ApiParam(name = "trustNo", value = "托管号码") String trustNo,
                                            @RequestHeader("appKey") @ApiParam(name = "appKey", value = "授权账号") String appKey) {
        return logicInternalService.initByAppointedTrustNoAndMouth(month, admin, trustNo, appKey);
    }

    @PostMapping("/initDataByOne")
    public R initDataByOne(@RequestParam(required = false) @ApiParam(name = "month", value = "更新月数") int month,
                                            @RequestHeader("admin") @ApiParam(name = "admin", value = "租户名(登记编号)") String admin,
                                            @RequestHeader("trustNo") @ApiParam(name = "trustNo", value = "托管号码") String trustNo,
                                            @RequestHeader("appKey") @ApiParam(name = "appKey", value = "授权账号") String appKey,
                                            @RequestParam("type") @ApiParam(name = "type", value = "要更新的标准表") String type) {
        return logicInternalService.initGtjaDataByOne(month, admin, trustNo, appKey, type);
    }

    @PostMapping("/updateData20min")
    @ApiOperation(value = "更新频率为半个小时的数据", notes = "用于更新每半个小时更新的数据", httpMethod = "POST")
    public R updateData20min() {
        return logicInternalService.updateData20min();
    }


    @PostMapping("/updateData1h")
    @ApiOperation(value = "更新频率为一个小时的数据", notes = "用于更新每一个小时更新的数据", httpMethod = "POST")
    public R updateData60min() {
        return logicInternalService.updateData1h();
    }

    @Autowired
    private TenantService tenantService;


    @PostMapping("/updateDataDicZxFndBasicInfoCy")
    @ApiOperation(value = "更新资讯数据字典", notes = "用于更新资讯数据字典数据")
    public R updateDataDicZxFndBasicInfoCy() {
        return logicInternalService.updateDataDicZxFndBasicInfoCy();
    }

    @PostMapping("/initDataZx")
    @ApiOperation(value = "初始化资讯数据", notes = "用于初始化资讯数据")
    public R initDataZx() {
        return logicInternalService.initDataZx();
    }

    @PostMapping("/updateDataZx")
    @ApiOperation(value = "更新资讯数据", notes = "用于更新资讯数据")
    public R updateDataZx() {
        return logicInternalService.updateDataZx();
    }

    @PostMapping("/updateNetValueData")
    @ApiOperation(value = "更新净值表数据", notes = "用于更新净值表数据")
    public R updateNetValueData() {
        return logicInternalService.updateNetValueData();
    }

    /**
     * loopTime 12 、 1
     *
     * @param loopTime
     * @return
     */
    @PostMapping("/updateZhongxTotalAsset")
    public R updateZhongxTotalAsset(@RequestParam(required = true) int loopTime) {
        return logicInternalService.updateZhongxTotalAsset(loopTime);
    }

    @PostMapping("/queryDaasRecord")
    @ApiOperation(value = "查询埋点记录数据", notes = "此接口用于查询调用daas系统接口记录信息")
    public R queryDaasRecord(@RequestBody @ApiParam(name = "params", value = "封装请求参数") String params) {
        return daasBuriedPointRecordInfoService.queryDaasRecord(params);
    }

    @PostMapping("/updateSWMgData")
    @ApiOperation(value = "更新申万募集户,托管户流水数据", notes = "此接口用于更新申万募集户,托管户流水数据")
    public R updateSWMgData() {
        return logicInternalService.updateSWMgDataDaily();
    }

    @Resource(name = "tenantEscrowAuthorizationInfoService")
    private TenantEscrowAuthorizationInfoServiceImpl tenantEscrowAuthorizationInfoServiceimpl;

    @Resource(name = "updateDataCJPool")
    private ExecutorService updateDataCJPool;


    @PostMapping("initByMail")
    @ApiOperation(value = "更新邮件数据", notes = "此接口用于更新读取邮件获取数据")
    public R initByMail(@RequestParam(required = false) @ApiParam(name = "date", value = "时间参数") String date,
                        @RequestParam(required = false) @ApiParam(name = "flag", value = "是否全量，传递参数即为全量，带_all的文件") String flag,
                        @RequestHeader("admin") @ApiParam(name = "admin", value = "租户名(登记编号)") String admin,
                        @RequestHeader("trustNo") @ApiParam(name = "trustNo", value = "托管编号") String trustNo,
                        @RequestHeader("appKey") @ApiParam(name = "appKey", value = "授权账号") String appKey) {

        return logicInternalService.initByMail(date, admin, trustNo, appKey, flag);
    }

    @PostMapping("/queryTheCustodian")
    @ApiOperation(value = "查询托管人信息", notes = "此接口用于查询托管人详细信息")
    public R<DataTrustDto> queryTheCustodian(
            @RequestParam(value = "trustNo", required = false) @ApiParam(name = "trustNo", value = "托管编号") String trustNo,
            @RequestHeader(value = "admin")
            @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
            @RequestHeader(value = "accountKey")
            @ApiParam(name = "accountKey", value = "账户Key") String accountKey
            ) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<DataTrustDto> list = logicInternalService.queryTheCustodian("admin", trustNo, "appKey");
        return R.ok("查询托管人信息成功！").put("data", list);
    }

    @PostMapping("/queryAdministrator")
    @ApiOperation(value = "查询管理人信息", notes = "此接口用于查询管理人详细信息")
    public R<TrustNoMonitorDto> queryAdministrator(
            @RequestParam(value = "admin", required = false) @ApiParam(name = "admin", value = "租户名(登记编号)") String admin,
            @RequestHeader(value = "admin")
            @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
            @RequestHeader(value = "accountKey")
            @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<TrustNoMonitorDto> list = logicInternalService.queryAdministrator(admin, "", "");
        return R.ok("查询管理人信息成功！").put("data", list);
    }

    @Autowired
    TongyiUnissuedDataService tongyiUnissuedDataService;

    @PostMapping("/queryMarketToBeIssued")
    @ApiOperation(value = "全市场待发行项目", notes = "此接口用于查询全市场待发行项目数据")
    public R<ArrayList<TongyiUnissuedDataVo>> queryMarketToBeIssued(@Validated({InsertData.class}) @RequestBody MarketToBeIssuedReq req,
                                                                    @RequestHeader(value = "admin")
                                                                    @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                                    @RequestHeader(value = "accountKey")
                                                                        @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //全市场待发行项目
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        R<ArrayList<TongyiUnissuedDataVo>> result = tongyiUnissuedDataService.queryMarketToBeIssued(req);
        stopWatch.stop();
        log.info("全市场待发行项目-接口耗时{}ms", stopWatch.getLastTaskTimeMillis());
        return result;
    }

    @Autowired
    TongyiDirectionalupDataService tongyiDirectionalupDataService;

    @PostMapping("/queryFixedIncreaseIssued")
    @ApiOperation(value = "【定增】部分", notes = "此接口用于查询【定增】部分数据")
    public R<List<ConvertibleBondsIssuedVo>> queryFixedIncreaseIssued(@Validated({InsertData.class}) @RequestBody ConvertibleBondsIssuedReq req,
                                                                      @RequestHeader(value = "admin")
                                                                      @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                                      @RequestHeader(value = "accountKey")
                                                                          @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        //【定增】部分
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        R<List<ConvertibleBondsIssuedVo>> result = tongyiDirectionalupDataService.queryFixedIncreaseIssued(req);
        stopWatch.stop();
        log.info("定增-接口耗时{}ms", stopWatch.getLastTaskTimeMillis());
        return result;

    }

    @Autowired
    TongyiConvertibleBondsDataService tongyiConvertibleBondsDataService;
    @Autowired
    TongyiDirectionalConvertibleBondsService tongyiDirectionalConvertibleBondsService;

    @PostMapping("/queryIssuedConvertibleBonds")
    @ApiOperation(value = "【可转债】部分", notes = "此接口用于查询【可转债】部分数据")
    public R<ArrayList<TongyiConvertibleBondsVo>> queryIssuedConvertibleBonds(@Validated({InsertData.class}) @RequestBody ConvertibleBondsIssuedReq req,
                                                                              @RequestHeader(value = "admin")
                                                                              @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                                              @RequestHeader(value = "accountKey")
                                                                                  @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        //【可转债】部分
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        R<ArrayList<TongyiConvertibleBondsVo>> r = new R<>();
        if ("0".equals(req.getType())) {
            r = tongyiDirectionalConvertibleBondsService.queryDirectionalConvertibleBonds(req);
        } else {
            r = tongyiConvertibleBondsDataService.queryIssuedConvertibleBonds(req);
        }
        stopWatch.stop();
        log.info("可转债-接口耗时{}ms", stopWatch.getLastTaskTimeMillis());
        return r;
    }

    @Autowired
    TongyiCeliverableBondDataService tongyiCeliverableBondDataService;

    @PostMapping("/queryDeliveraBlebondsIssued")
    @ApiOperation(value = "【可交债】已发行", notes = "此接口用于查询【可交债】已发行数据")
    public R<ArrayList<TongyiCeliverableBondVo>> queryDeliveraBlebondsIssued(@Validated({InsertData.class}) @RequestBody ConvertibleBondsIssuedReq req,
                                                                             @RequestHeader(value = "admin")
                                                                             @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                                             @RequestHeader(value = "accountKey")
                                                                                 @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        //【可交债】已发行
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        R<ArrayList<TongyiCeliverableBondVo>> result = tongyiCeliverableBondDataService.queryDeliveraBlebondsIssued(req);
        stopWatch.stop();
        log.info("可交债-接口耗时{}ms", stopWatch.getLastTaskTimeMillis());
        return result;
    }

    @Autowired
    UpdateTongyiTemporaryTableService updateTongyiTemporaryTableService;

    @PostMapping("/updateTongyiTemporaryTable")
    @ApiOperation(value = "手动更新通怡临时表", notes = "此接口用于手动更新通怡临时表")
    public R<String> updateTongyiTemporaryTable(@RequestHeader(value = "admin")
                                                    @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                @RequestHeader(value = "accountKey")
                                                    @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        Boolean b = updateTongyiTemporaryTableService.updateTongyiTemporaryTable();
        if (b) {
            return R.ok("通怡临时表更新成功");
        } else {
            return R.error("通怡临时表更新失败");
        }
    }

    @PostMapping("/rpaGetAdminNo")
    @ApiOperation(value = "获取管理人编号", notes = "此接口用于提供管理人编号给rpa")
    public R<List<String>> rpaGetAdminNo(@RequestHeader(value = "admin")
                                             @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                         @RequestHeader(value = "accountKey")
                                             @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<String> adminNoList = logicInternalService.rpaGetAdminNo();
        return R.ok("获取管理人列表成功").put("data", adminNoList);
    }

    @PostMapping("/saveProductData")
    @ApiOperation(value = "保存管理人信息", notes = "此接口用于保存管理人信息")
    public R<List<ProductDataEntity>> saveProductData(@RequestBody JSONObject jsonObject,
                                                      @RequestHeader(value = "admin")
                                                      @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                      @RequestHeader(value = "accountKey")
                                                      @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<ProductDataEntity> productDataEntities = logicInternalService.saveProductData(jsonObject);
        return R.ok("保存管理人信息成功").put("data", productDataEntities);
    }


    @Autowired
    HandlerVersionTxtServiceImpl handlerVersionTxtService;
    @PostMapping("/handleMailTxtTest")
    @ApiOperation(value = "解析txt")
    public R handleMailTest(
                        @RequestHeader("admin") @ApiParam(name = "admin", value = "租户名(登记编号)") String admin,
                        @RequestHeader("trustNo") @ApiParam(name = "trustNo", value = "托管编号")  String trustNo,
                        @RequestHeader("version") @ApiParam(name = "trustNo", value = "版本号")  String version
                        ) {
        handlerVersionTxtService.processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto.builder().trustNo(trustNo).tenantName(admin).build(), null, trustNo, null, version);
        return R.ok();
    }
    @Autowired
    TableInfoService tableInfoService;
    @PostMapping("/getTableName")
    @ApiOperation(value = "获取表名表注释", notes = "此接口用于获取表名表注释")
    public R<List<TableNameDto>> getTableName(
            @RequestHeader(value = "admin")
            @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
            @RequestHeader(value = "accountKey")
            @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<TableNameDto> tableNameDtos = tableInfoService.listTable();
        return R.ok("获取表名表注释成功").put("total",tableNameDtos.size()).put("data", tableNameDtos);
    }
    @PostMapping("/getTableStructure")
    @ApiOperation(value = "获取表结构", notes = "此接口用于获取表结构")
    public R<List<TableStructureDto>> getTableStructure(@RequestParam(value = "tableName")
                                                       @ApiParam(name = "tableName", value = "表名", required = true) String tableName,
                                                        @RequestHeader(value = "admin")
                                                        @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                        @RequestHeader(value = "accountKey")
                                                            @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<TableStructureDto> tableStructureDtos = tableInfoService.listTableColumn(tableName);
        return R.ok("获取表结构成功").put("total",tableStructureDtos.size()).put("data", tableStructureDtos);
    }
    @PostMapping("/getDataByTableNameAndSql")
    @ApiOperation(value = "获取表数据", notes = "此接口用于获取表数据")
    public R<QueryBySQLDto> getDataByTableNameAndSql(@RequestBody GetDataByTableNameAndSqlReq req,
                                                     @RequestHeader(value = "admin")
                                                     @ApiParam(name = "admin", value = "租户名(登记编号)") String tenantName,
                                                     @RequestHeader(value = "accountKey")
                                                         @ApiParam(name = "accountKey", value = "账户Key") String accountKey) {
        //校验租户名和密码
        checkTenantInfo(tenantName,accountKey);
        List<QueryBySQLDto> dataByTableNameAndSql = tableInfoService.getDataByTableNameAndSql(req);
        return R.ok("获取表数据成功").put("total",dataByTableNameAndSql.size()).put("data", dataByTableNameAndSql);
    }


    /**
     * 校验账号密码正确性
     * @param tenantName 账号
     * @param accountKey 密码
     */
    private void checkTenantInfo(String tenantName, String accountKey) {
        R<TenantInfoDto> tenantInfoDtoR = tenantService.queryTenant(TenantInfoDto.builder().tenantName(tenantName).accountKey(accountKey).build());
        if (Objects.isNull(tenantInfoDtoR.getData())) {
            throw new RRException("租户名或密码错误！");
        }
    }
}
