package com.cyksj.web.controller.manage.account;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Jsons;
import com.cyksj.common.util.StringUtil;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.ChatgptSessionMapper;
import com.cyksj.model.dto.ChatGptChangePasswordDto;
import com.cyksj.model.dto.ChatgptChangeNodesDto;
import com.cyksj.model.entity.ChatgptSession;
import com.cyksj.model.entity.SysConfig;
import com.cyksj.model.excel.ExcelGptMirrorAccountData;
import com.cyksj.model.excel.ExcelGptSessionAccountData;
import com.cyksj.model.views.ChatgptCarSessionView;
import com.cyksj.redis.RedisService;
import com.cyksj.service.chatgpt.ChatGptAccountService;
import com.cyksj.service.mail.CommonMailService;
import com.cyksj.service.mail.YhMailService;
import com.cyksj.service.sys.SysConfigService;
import com.cyksj.web.util.EasyExcelUtils;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Optional;

/** admin/镜像车队账号管理
 * 项目名: yhlxj
 * 文件名: CmsGptCarController
 * 创建者: JavaZou
 * 创建时间:2024/4/12 15:12
 */
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/manage/account/gptCar")
@RestController
public class CmsGptCarController {
	private final ChatGptAccountService chatGptAccountService;

	private final ChatgptSessionMapper chatgptSessionMapper;

	private final RedisService redisService;

	private final BeanSearcher beanSearcher;

	private final HttpServletRequest request;

	private final YhMailService yhMailService;

	private final SysConfigService sysConfigService;

	private final CommonMailService commonMailService;

	/**
	 * 获取镜像车队账号列表
	 */
	@GetMapping("/get")
	public Result<SearchResult<ChatgptCarSessionView>> getMirrorCarSession() {
		SearchResult<ChatgptCarSessionView> search = beanSearcher.search(ChatgptCarSessionView.class, MapUtils.flatBuilder(request.getParameterMap())
				.orderBy(ChatgptCarSessionView::getId).desc()
				.build());
		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
	}

	/**
	 * 编辑镜像车队账号列表
	 */
	@PutMapping("/update")
	public Result<String> updateMirrorCarSession(@RequestBody ChatgptSession chatgptSession) {
		Long id = chatgptSession.getId();
		ChatgptSession dbChatSession = chatgptSessionMapper.selectById(id);
		if (StrUtil.equals(chatgptSession.getOfficialSession(), dbChatSession.getOfficialSession())) {
			if (!ObjectUtil.equal(dbChatSession.getEmail(), chatgptSession.getEmail()) || !ObjectUtil.equal(dbChatSession.getPassword(), chatgptSession.getPassword())) {
				String gptSession = chatGptAccountService.getGptSession(dbChatSession.getEmail(), dbChatSession.getPassword());
				chatgptSession.setOfficialSession(gptSession);
			}
		}
		Integer selectCount = chatgptSessionMapper.selectCount(Wrappers.lambdaQuery(ChatgptSession.class)
				.and(e -> e.eq(ChatgptSession::getEmail, chatgptSession.getEmail())
						.or().eq(ChatgptSession::getCarId, chatgptSession.getCarId()))
				.ne(ChatgptSession::getId, chatgptSession.getId()));
		if (selectCount > 0) {
			throw BusinessRuntimeException.getInstance("请检验车队ID或账号是否已存在");
		}
		refresh(chatgptSession.getId());
		chatgptSessionMapper.updateById(chatgptSession);
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 删除镜像车队账号
	 */
	@DeleteMapping("/delete/{id}")
	public Result<String> deleteMirrorCarSession(@PathVariable Long id) {
		Optional.ofNullable(chatgptSessionMapper.selectById(id))
				.ifPresent(e -> {
					String carId = e.getCarId();
					if (StrUtil.isNotBlank(carId)) {
						chatgptSessionMapper.deleteById(e.getId());

						String highCarChatKey = RedisService.key.CHATGPT_CAR_HIGH_CHAT.getName() + carId;
						String lowCarChatKey = RedisService.key.CHATGPT_CAR_LOW_CHAT.getName() + carId;
						//从zSet中删除车队
						String carScoresKey = RedisService.key.CHATGPT_CAR_SCORES.getName();
						redisService.zRemove(carScoresKey, carId);
						redisService.del(highCarChatKey);
						redisService.del(lowCarChatKey);
					}
				});
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 新增镜像车队账号
	 */
	@PostMapping("/post/mirror/car/session")
	public Result<String> postMirrorCarSession(@RequestBody ChatgptSession chatgptSession) throws Exception {
		Integer selectCount = chatgptSessionMapper.selectCount(Wrappers.lambdaQuery(ChatgptSession.class)
				.eq(chatgptSession.getCarId() != null, ChatgptSession::getCarId, chatgptSession.getCarId()).or().eq(ChatgptSession::getEmail, chatgptSession.getEmail()));
		if (selectCount > 0) {
			throw BusinessRuntimeException.getInstance("请检验车队ID或账号是否已存在");
		}
		String gptSession = null;
		if (StrUtil.isBlank(chatgptSession.getOfficialSession())) {
			gptSession = chatGptAccountService.getGptSession(chatgptSession.getEmail(), chatgptSession.getPassword());
			chatgptSession.setIsCar(true);
			chatgptSession.setOfficialSession(gptSession);
		}
		chatgptSessionMapper.insert(chatgptSession);
		if (gptSession != null && StringUtils.isBlank(chatgptSession.getCarId())) {
			JSONObject jsonObject = new JSONObject(gptSession);
			String planType = jsonObject.getJSONObject("accountCheckInfo").getStr("plan_type");
			if ("plus".equals(planType)) {
				chatgptSession.setCarId("P" + chatgptSession.getId());
				chatgptSession.setCarName("P" + chatgptSession.getId());
			} else if ("team".equals(planType)) {
				chatgptSession.setCarId("T" + chatgptSession.getId());
				chatgptSession.setCarName("T" + chatgptSession.getId());
			} else {
				chatgptSession.setCarId("P" + chatgptSession.getId());
				chatgptSession.setCarName("P" + chatgptSession.getId());
				chatgptSession.setIsPlus(0);
			}
		}else {
			chatgptSession.setIsPlus(0);
			chatgptSession.setStatus(0);
			chatgptSession.setCarId("P" + chatgptSession.getId());
			chatgptSession.setCarName("P" + chatgptSession.getId());
		}
		refresh(chatgptSession.getId());
		chatgptSessionMapper.updateById(chatgptSession);

		//同步session的会员类型
		if (StrUtil.isNotEmpty(chatgptSession.getOfficialSession())) {
			String officialSession = chatgptSession.getOfficialSession();
			JSONObject session = Jsons.parseObject(officialSession, JSONObject.class);
			String accessToken = session.getStr("accessToken");
			if (StrUtil.isNotEmpty(accessToken)) {
				getGptAccountInfo(request, chatgptSession.getId(), accessToken);
			}
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	@PostMapping("/post/mirror/changePassword")
	public Result<String> changePassword(@RequestBody ChatGptChangePasswordDto chatGptChangePasswordDto){
		Long chatgptSessionId = chatGptChangePasswordDto.getChatgptSessionId();
		ChatgptSession chatgptSession = chatgptSessionMapper.selectById(chatgptSessionId);
		if(chatgptSession == null){
			throw BusinessRuntimeException.getInstance("车队不存在");
		}

		HttpRequest request = HttpRequest.post("http://85.113.70.93:8282/change");
		request.form("url", chatGptChangePasswordDto.getUrl());
		if(StringUtils.isBlank(chatGptChangePasswordDto.getPassword())){
			chatGptChangePasswordDto.setPassword(RandomUtil.randomString(12));
		}
		request.form("newpassword", chatGptChangePasswordDto.getPassword());
		request.form("proxy", "nKeghbxuT2R2QO7G:2pSJmJSZln2CPGJ2_country-us_streaming-1@geo.iproyal.com:12321");
		String body = request.execute().body();
		JSONObject jsonResponse = new JSONObject(body);
		int code = jsonResponse.getInt("code");

		// Handle response
		if (code == 1) {
			//修改密码
			chatgptSession.setPassword(chatGptChangePasswordDto.getPassword());
			refresh(chatgptSession.getId());
			chatgptSessionMapper.updateById(chatgptSession);
			return GatewayResponse.SUCCESS.newBuilder().toResult();
		} else {
			throw BusinessRuntimeException.getInstance("修改密码错误");
		}
	}


	/**
	 * 刷新gpt得officialSession
	 */
	@PutMapping("/flush/officialSession/{id}")
	public Result<String> flushOfficialSession(@PathVariable Long id) {
		ChatgptSession dbChatSession = chatgptSessionMapper.selectById(id);
		if (dbChatSession != null) {
			String gptSession = chatGptAccountService.getGptSession(dbChatSession.getEmail(), dbChatSession.getPassword());
			dbChatSession.setOfficialSession(gptSession);
			refresh(dbChatSession.getId());
			chatgptSessionMapper.updateById(dbChatSession);
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 导出gpt镜像账号
	 */
	@GetMapping("/export/mirror/account")
	public void export(HttpServletResponse response) {
		List<ExcelGptMirrorAccountData> dataList = beanSearcher.searchAll(ExcelGptMirrorAccountData.class, MapUtils.flatBuilder(request.getParameterMap()).build());
		dataList.forEach(data -> {
			String officialSession = data.getOfficialSession();
			if (StrUtil.isNotEmpty(officialSession)) {
				try {
					JSONObject body = Jsons.parseObject(officialSession, JSONObject.class);
					JSONObject accountCheckInfo = body.getJSONObject("accountCheckInfo");
					String expiresAt = accountCheckInfo.getStr("expires_at");
					data.setExpiryTime(DateUtil.parse(expiresAt));
				} catch (Exception e) {
				}
			}
		});
		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelGptMirrorAccountData.class, dataList, "gpt镜像账号", "gpt镜像账号", ExcelTypeEnum.XLS, null);
	}

	/**
	 * 查看gpt验证码
	 */
	@GetMapping("/get/account/verifyCode")
	public Result<String> getAccountVerifyCode(Long id) {
		ChatgptSession chatgptSession = chatgptSessionMapper.selectById(id);
		String account = chatgptSession.getEmail();
		if (StrUtil.isNotEmpty(chatgptSession.getRelateEmail())) {
			account = chatgptSession.getRelateEmail();
		}
		String code = yhMailService.getGptCode(account);
		JSONObject re = new JSONObject();
		re.putOpt("code", code);
		return GatewayResponse.SUCCESS.newBuilder().toResult(re.toString());
	}

	/**
	 * 读取GPT重置密码链接
	 */
	@GetMapping("/read/resetPassword/link")
	public Result<String> readResetPwdResetLink(Long id) {
		ChatgptSession chatgptSession = chatgptSessionMapper.selectById(id);
		String account = chatgptSession.getEmail();
		String relateEmail = chatgptSession.getRelateEmail();
		if (StrUtil.isNotEmpty(relateEmail)) {
			account = relateEmail;
		}
		String linkUrl = yhMailService.readResetPwdResetLink(account);
		return GatewayResponse.SUCCESS.newBuilder().toResult(linkUrl);
	}

	private void refresh(Long id){
		try {
			SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "mirror_gpt_domain"));
			List<String> array = new JSONArray(one.getSysValue()).toList(String.class);
			array.forEach((domain)->{
				String url = domain + "/backend-api/car/refresh?carId=" + id;
				HttpUtil.get(url);
			});
		}catch (Exception e) {
			log.error("刷新车队token异常:{}", StringUtil.getErrorText(e));
		}
	}

	/**
	 * gpt更换节点
	 */
	@PostMapping("/changeNodes")
	public Result<String> changeNodes(@RequestBody ChatgptChangeNodesDto node){
		SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "gpt_car_nodes_list"));
		List<String> nodeList = new JSONArray(one.getSysValue()).toList(String.class);
		if (nodeList.contains(node.getNode())) {
			//修改目前使用gpt节点值
			sysConfigService.update(Wrappers.lambdaUpdate(SysConfig.class).eq(SysConfig::getSysKey,"gpt_car_nodes").set(SysConfig::getSysValue, node.getNode()));
			SysConfig domainConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "mirror_gpt_domain"));
			List<String> domainList = new JSONArray(domainConfig.getSysValue()).toList(String.class);
			domainList.forEach((domain)->{
				HttpUtil.get(domain + "/backend-api/car/changeNodes");
			});
			log.info("切换成功");
			return GatewayResponse.SUCCESS.newBuilder().toResult();
		}else {
			throw BusinessRuntimeException.getInstance("该节点不存在！");
		}
	}

	/**
	 * 获取 gpt用户信息
	 */
	@GetMapping("/getGptAccountInfo")
	public Result<String> getGptAccountInfo(HttpServletRequest request, Long id, String accessToken) {
		if (StringUtils.isBlank(accessToken)) {
			ChatgptSession chatgptSession = chatgptSessionMapper.selectById(id);
			String officialSession = chatgptSession.getOfficialSession();
			JSONObject jsonObject = new JSONObject(officialSession);
			String accessTokenJson = jsonObject.getStr("accessToken");
			if (StringUtils.isBlank(accessTokenJson)) {
				throw BusinessRuntimeException.getInstance("缺少accessToken");
			} else {
				accessToken = accessTokenJson;
			}
		}
		log.info("accessToken:{}", accessToken);
		HttpRequest httpRequest = new HttpRequest("https://chat-chan-87jztgkf257d.xyhelper.org/backend-api/accounts/check/v4-2023-04-27?timezone_offset_min=0");
		httpRequest.header("User-Agent", request.getHeader("User-Agent"));
		httpRequest.header("Authorization", accessToken);
		try (HttpResponse execute = httpRequest.execute()) {
			if (execute.getStatus() == 200) {
				String result = execute.body();
				chatgptSessionMapper.update(null, Wrappers.lambdaUpdate(ChatgptSession.class).eq(ChatgptSession::getId, id).set(ChatgptSession::getAccountInfo, result));
				JSONObject resObj = new JSONObject(result);
				JSONObject entitlement = resObj.getJSONObject("accounts").getJSONObject("default").getJSONObject("entitlement");
				String subscriptionPlan = entitlement.getStr("subscription_plan");
				if (StrUtil.isNotEmpty(subscriptionPlan)) {
					if (subscriptionPlan.contains("chatgptpro")) {
						chatgptSessionMapper.update(null, Wrappers.lambdaUpdate(ChatgptSession.class).eq(ChatgptSession::getId, id).set(ChatgptSession::getType, "Pro"));
					}
					if (subscriptionPlan.contains("chatgptplusplan")) {
						chatgptSessionMapper.update(null, Wrappers.lambdaUpdate(ChatgptSession.class).eq(ChatgptSession::getId, id).set(ChatgptSession::getType, "Plus"));
					}
				} else {
					chatgptSessionMapper.update(null, Wrappers.lambdaUpdate(ChatgptSession.class).eq(ChatgptSession::getId, id).set(ChatgptSession::getType, "普通"));
				}
				JSONArray accountOrdering = resObj.getJSONArray("account_ordering");
				if (accountOrdering.size() > 1) {
					chatgptSessionMapper.update(null, Wrappers.lambdaUpdate(ChatgptSession.class).eq(ChatgptSession::getId, id).set(ChatgptSession::getType, "Team"));
				}
				return GatewayResponse.SUCCESS.newBuilder().toResult(entitlement.getStr("expires_at"));
			} else {
				if (execute.getStatus() == 401) {
					throw BusinessRuntimeException.getInstance("token失效");
				}
				throw BusinessRuntimeException.getInstance(execute.body());
			}
		}

	}

	/**
	 * 下载GPT镜像车队模板
	 */
	@GetMapping("/export/gpt/session/template")
	public void getGptSessionTemplate(HttpServletResponse response) {
		EasyExcelUtils.createTemplateExcel(response, ExcelGptSessionAccountData.class, "导入GPT镜像车队账号模板", "导入GPT镜像车队账号模板", ExcelTypeEnum.XLSX, null);
	}

	/**
	 * 上传GPT镜像车队
	 */
	@PostMapping("/import/gpt/session")
	public Result<String> importGptSession(MultipartFile file) throws IOException {
		EasyExcel.read(file.getInputStream(), ExcelGptSessionAccountData.class, new AnalysisEventListener<ExcelGptSessionAccountData>() {
			@Override
			public void invoke(ExcelGptSessionAccountData data, AnalysisContext analysisContext) {
				ChatgptSession session = new ChatgptSession();
				BeanUtil.copyProperties(data, session);
				session.setStatus(0);
				if ("有效".equals(data.getStatusStr())) {
					session.setStatus(1);
				}
				//生成gptSession
				try {
					postMirrorCarSession(session);
				} catch (Exception e) {

				}
			}
			@Override
			public void doAfterAllAnalysed(AnalysisContext analysisContext) {

			}
		}).sheet().doRead();
		return GatewayResponse.SUCCESS.newBuilder().toResult();
	}

	/**
	 * 获取GPT改密链接
	 */
	@GetMapping("/get/change/pwd/link")
	public Result<String> getChangePwdLink(Long id) throws Exception {
		ChatgptSession chatgptSession = chatgptSessionMapper.selectById(id);
		String link = commonMailService.getGptChangePwdLink(chatgptSession.getEmail(), chatgptSession.getEmailPassword());
		return GatewayResponse.SUCCESS.newBuilder().toResult(link);
	}

}
