package com.cyksj.web.controller.mirror;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.cyksj.common.EnvCommonService;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.common.util.IoKit;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.model.entity.ChatgptSession;
import com.cyksj.model.entity.ChatgptUser;
import com.cyksj.model.entity.MidjourneyUser;
import com.cyksj.model.request.gpt.ConversationRequest;
import com.cyksj.model.response.ConversationLimitResponse;
import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
import com.cyksj.model.views.ChatGptUserView;
import com.cyksj.model.views.ChatgptCarInfoView;
import com.cyksj.model.views.ChatgptConversionLimitView;
import com.cyksj.service.chatgpt.ChatGptAccountService;
import com.cyksj.service.midjourney.MidjourneyAccountService;
import com.cyksj.web.util.StpUserUtil;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Set;

/**
 * /server/镜像服务
 *
 * @author chan
 * @date 2024/3/19 14:41
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/applets/mirror")
public class MirrorController {

    private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();

    private final ChatGptAccountService chatGptAccountService;

    private final HttpServletResponse response;

    private final HttpServletRequest request;

    private final BeanSearcher beanSearcher;

    private final MidjourneyAccountService midjourneyAccountService;

    private final EnvCommonService envCommonService;

    @Value("${midjourney.url}")
    private String midjourneyHost;

    @Value("${midjourney.drawUrl}")
    private String midjourneyDrawUrl;


    /**
     * GPT车票跳转登录
     *
     * @param relationId 车票id
     */
    @GetMapping("/chatGptMirror/{relationId}")
    public Result<String> chatGptMirror(@PathVariable Long relationId) throws IOException {
        Long userId = StpUserUtil.getLoginIdAsLong();
        return GatewayResponse.SUCCESS.newBuilder().toResult(chatGptAccountService.getLoginUrl(userId, relationId));
    }

    /**
     * GPT车票跳转登录
     *
     * @param userToken 用户token
     * @param carId     车票id
     * @return 登陆结果
     */
    @RequestMapping("/gpt/oauth")
    public Result<String> gptOauth(@RequestParam("usertoken") String userToken, @RequestParam("carid") String carId) {
        try {
            log.info("用户通过userToken:{}访问镜像车队carId:{}", userToken, carId);
            ChatgptUser user = chatGptAccountService.findByUserTokenAndExpireTimeAfter(userToken, LocalDateTime.now());
            if (user == null) {
                return GatewayResponse.SUCCESS.newBuilder().setMsg("用户不存在或已过期").setCode(0).toResult();
            }

            ChatgptSession session = chatGptAccountService.checkSession(carId);
            if (session.getIsCar()) {
                log.info("用户:{}通过userToken:{}访问镜像车队carId:{}成功", user.getName(), userToken, carId);
                return GatewayResponse.SUCCESS.newBuilder().setMsg("登陆成功").setCode(1).toResult();
            }
        } catch (Exception e) {
            log.error("服务器错误", e);
            return GatewayResponse.FAIL.newBuilder().setMsg("服务器错误").setCode(0).toResult();
        }
        return GatewayResponse.FAIL.newBuilder().setMsg("服务器错误").setCode(0).toResult();
    }


    /**
     * GPT车队跳转登录
     *
     * @param carId 车队id
     */
    @GetMapping("/chatGptMirror/{relationId}/{carId}")
    public Result<String> chatGPtCarLogin(@PathVariable Long relationId, @PathVariable String carId) throws IOException {
        Long userId = StpUserUtil.getLoginIdAsLong();
        chatGptAccountService.checkCarAccount(userId, relationId);
        String url = chatGptAccountService.getCarLoginUrl(userId, relationId, carId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(url);
    }

    @GetMapping("/gpt/genTitleSync")
    public Result<String> genTitleSync(String messageId) {
        //1.从request获取请求头Authorization 并取 值内 'Bearer ' 后的值为usertoken
        String authorization = request.getHeader("Authorization");
        String carid = request.getHeader("Carid");
        String userToken = authorization.substring(7);
        TASK_EXECUTOR.execute(() -> {
            chatGptAccountService.genTitleSync(messageId, carid, userToken);
        });
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }


    /**
     * 会话限制
     */
    @RequestMapping("/gpt/conversation/limit")
    public ChatgptConversionLimitView conversationLimit(@RequestParam(value = "isCar", defaultValue = "false") Boolean isCar, @RequestBody ConversationRequest conversationRequest) {
        //1.从request获取请求头Authorization 并取 值内 'Bearer ' 后的值为usertoken
        String authorization = request.getHeader("Authorization");
        String carid = request.getHeader("Carid");
        conversationRequest.setCarId(carid);
        String userToken = authorization.substring(7);
        //2.根据usertoken 查询 chatgpt_user 表中的记录
        ChatgptUser user = chatGptAccountService.findByUserTokenAndExpireTimeAfter(userToken, LocalDateTime.now());
        //3.如果记录不存在，返回状态码 401
        if (user == null) {
            response.setStatus(401);
        }
        if(StringUtils.isNotBlank(conversationRequest.getCarId())){
            //4.获取gpt-4 的规则限制
            //text-davinci-002-render-sha 3.5
            ConversationLimitResponse conversationLimitResponse = chatGptAccountService.conversationLimit(userToken, conversationRequest.getModel(), conversationRequest.getCarId(), user, isCar);

            if (conversationLimitResponse.isLimited()) {
                response.setStatus(400);
                //String json = "{\"detail\":{\"message\":\"您的账号已达到GPT-4的使用上限。您现在可以继续使用默认模型，或者重试在\",\"code\":\"model_cap_exceeded\",\"clears_in\":2687}}";
                ChatgptConversionLimitView chatgptConversionLimitView = new ChatgptConversionLimitView();
                ChatgptConversionLimitView.Detail detail = new ChatgptConversionLimitView.Detail();
                detail.setMessage("您目前的套餐已达到GPT-4的使用上限。您可以继续使用3.5，预计 " + DateUtil.format(new Date(conversationLimitResponse.getNextAvailableTime()), "yyyy-MM-dd HH:mm:ss") + " 恢复");
                chatgptConversionLimitView.setDetail(detail);
                return chatgptConversionLimitView;
            } else {
                response.setStatus(200);
            }
            //5.获取 conversationRequest 中的model 字段，判断是否为 gpt-4 如果为gpt-4 执行 查看是否达到限制方法
            //6.如果达到限制，返回状态码 429 并返回文本 xxx
        }

        return new ChatgptConversionLimitView();
    }

    /**
     * 对话成功后记录次数
     */
    @RequestMapping("/gpt/conversation/notifyUrl")
    public void conversationNotifyUrl(@RequestParam(value = "isCar", defaultValue = "false") Boolean isCar, @RequestBody ConversationRequest conversationRequest) {
        //1.从request获取请求头Authorization 并取 值内 'Bearer ' 后的值为usertoken
        String authorization = request.getHeader("Authorization");
        String carid = request.getHeader("Carid");
        conversationRequest.setCarId(carid);
        String userToken = authorization.substring(7);
        //2.根据usertoken 查询 chatgpt_user 表中的记录
        ChatgptUser user = chatGptAccountService.findByUserTokenAndExpireTimeAfter(userToken, LocalDateTime.now());
        //3.如果记录不存在，返回状态码 401
        if (user == null) {
            return;
        }
        if(StringUtils.isNotBlank(conversationRequest.getCarId())){
            TASK_EXECUTOR.execute(() -> {
                chatGptAccountService.saveConversationRecord(userToken, conversationRequest);
            });
        }
    }


    /**
     * 获取车队列表
     *
     * @param relationId
     * @return
     */
    @GetMapping("/gpt/cars")
    public Result<Set<ChatgptCarInfoView>> getCarInfoList(Long relationId,@RequestParam(defaultValue = "10") Integer limit,@RequestParam(defaultValue = "false") Boolean isPlus) {
        long userId = StpUserUtil.getLoginIdAsLong();
        //查看用户是否存在车票
        ChatgptUser carChatGptUser = chatGptAccountService.getCarChatGptUser(userId, relationId);
        if (carChatGptUser == null) {
            throw BusinessRuntimeException.getInstance("您还未购买车票");
        }
        Set<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(),10, isPlus);
        for (ChatgptCarInfoView chatgptCarInfoView : carInfoList) {
            Double score = BigDecimal.valueOf(chatgptCarInfoView.getScore()).multiply(BigDecimal.valueOf(0.5)).setScale(0, RoundingMode.DOWN).doubleValue();
            chatgptCarInfoView.setScore(score);
            if (!"停运".equals(chatgptCarInfoView.getStatus())) {
                chatgptCarInfoView.setStatus(score >= 50 ? "繁忙" : "空闲");
            }
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult(carInfoList);
    }


    /**
     * 获取gpt车票信息
     */
    @GetMapping("/gpt/userInfo")
    public Result<ChatGptUserView> getUserInfo(Long relationId) {
        long userId = StpUserUtil.getLoginIdAsLong();
        ChatGptUserView user = chatGptAccountService.getUserInfo(userId, relationId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(user);
    }

    /**
     * 获取车队历史记录
     */
    @GetMapping("/gpt/car/history")
    public Result<SearchResult<ChatGptUserConversationRecordHistoryView>> getCarHistory(Long relationId) {
        long userId = StpUserUtil.getLoginIdAsLong();
        ChatgptUser carChatGptUser = chatGptAccountService.getCarChatGptUser(userId, relationId);
        if (carChatGptUser == null) {
            throw BusinessRuntimeException.getInstance("车票出现了异常.");
        }
        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()).field("userToken", carChatGptUser.getUserToken());
        SearchResult<ChatGptUserConversationRecordHistoryView> search = beanSearcher.search(ChatGptUserConversationRecordHistoryView.class, builder.build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
    }

    /**
     * oai触发车队限制
     */
    @GetMapping("/gpt/car/limited")
    public Result<String> carLimited(String carId, Long expTime, @RequestParam(defaultValue = "false") Boolean isTeam) {
        String authorization = request.getHeader("Authorization");
        String userToken = "";
        if(StringUtils.isNotBlank(authorization)){
            try {
                userToken = authorization.substring(7);
            }catch (Exception e){
               log.error("获取用户token失败",e);
               return GatewayResponse.SUCCESS.newBuilder().toResult();
            }
        }

        String finalUserToken = userToken;
        TASK_EXECUTOR.execute(()->{
            chatGptAccountService.carLimited(carId, finalUserToken, expTime,isTeam);
        });
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }


    /**
     * 根据userToken获取gpt车票信息
     */
    @GetMapping("/gpt/userInfoWithToken")
    public Result<ChatGptUserView> getUserInfoWithToken(String userToken) {
        ChatGptUserView user = chatGptAccountService.getUserInfoWithToken(userToken);
        return GatewayResponse.SUCCESS.newBuilder().toResult(user);
    }

    /**
     * 根据userToken GPT车队跳转登录
     *
     * @param carId 车队id
     */
    @GetMapping("/chatGptMirrorWithToken/{userToken}/{carId}")
    public Result<String> chatGPtCarLoginWithToken(@PathVariable String userToken, @PathVariable String carId) {
        chatGptAccountService.checkCarAccountWithToken(userToken);
        String url = chatGptAccountService.getCarLoginUrlWithToken(userToken, carId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(url);
    }

    /**
     * 根据userToken获取车队列表
     */
    @GetMapping("/gpt/cars/withToken")
    public Result<Set<ChatgptCarInfoView>> getCarInfoListWithToken(String userToken,@RequestParam(defaultValue = "10") Integer limit, @RequestParam(defaultValue = "false") Boolean isPlus) {
        //查看用户是否存在车票
        ChatgptUser carChatGptUser = chatGptAccountService.getCarChatGptUserWithToken(userToken);
        if (carChatGptUser == null) {
            throw BusinessRuntimeException.getInstance("您还未购买车票");
        }
        Set<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(), limit, isPlus);
        return GatewayResponse.SUCCESS.newBuilder().toResult(carInfoList);
    }

    /**
     * 根据userToken获取车队历史记录
     */
    @GetMapping("/gpt/car/history/withToken")
    public Result<SearchResult<ChatGptUserConversationRecordHistoryView>> getCarHistory(String userToken) {
        ChatgptUser carChatGptUser = chatGptAccountService.getCarChatGptUserWithToken(userToken);
        if (carChatGptUser == null) {
            throw BusinessRuntimeException.getInstance("车票出现了异常.");
        }
        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()).field("userToken", carChatGptUser.getUserToken());
        SearchResult<ChatGptUserConversationRecordHistoryView> search = beanSearcher.search(ChatGptUserConversationRecordHistoryView.class, builder.build());
        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
    }



    /**
     * MJ车票跳转登录
     *
     * @param relationId 车票id
     */
    @GetMapping("/midjourneyMirror/{relationId}")
    public Result<String> midjourneyMirror(@PathVariable Long relationId) {
        Long userId = StpUserUtil.getLoginIdAsLong();
        MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(userId, relationId);
        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyHost + (EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8081":"/8082") +"/api/applets/mirror/midjourneyMirrorWithToken/" + midjourneyUser.getUserToken());
    }

    @GetMapping("/midjourneyMirrorWithToken/{userToken}")
    public void midjourneyMirrorWithToken(@PathVariable String userToken) throws IOException {
        Cookie cookie = new Cookie("userToken", userToken);
        cookie.setMaxAge(31536000);
        cookie.setPath("/");
        response.addCookie(cookie);
        response.sendRedirect(midjourneyDrawUrl);
    }
}
