package com.apobates.forum.trident.controller;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.apobates.forum.core.api.service.AlbumService;
import com.apobates.forum.core.api.service.BoardGroupService;
import com.apobates.forum.core.api.service.BoardTopicCategoryIndexService;
import com.apobates.forum.core.api.service.TopicService;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.BoardTopicCategoryIndex;
import com.apobates.forum.core.entity.ForumReportTypeEnum;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.event.elderly.MemberActionDescriptor;
import com.apobates.forum.trident.OnlineDescriptor;
import com.apobates.forum.trident.controller.form.MemberPassworResetForm;
import com.apobates.forum.trident.controller.form.MemberPasswordLostForm;
import com.apobates.forum.trident.controller.helper.FeedbackPlugTopic;
import com.apobates.forum.member.api.service.MemberService;
import com.apobates.forum.member.api.service.MemberSocialInfoService;
import com.apobates.forum.member.entity.MemberSocialInfo;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.ip.IPMatcher;
import com.apobates.forum.utils.lang.EnumArchitecture;
/**
 * 主控制器
 * 
 * @author xiaofanku@live.cn
 * @since 20190306
 */
@Controller
public class MainController {
	@Autowired
	private MemberSocialInfoService memberSocialInfoService;
	@Autowired
	private MemberService memberService;
	@Autowired
	private TopicService topicService;
	@Autowired
	private AlbumService albumService;
	@Autowired
	private BoardGroupService boardGroupService;
	@Autowired
	private BoardTopicCategoryIndexService boardTopicCategoryIndexService;
	@Value("${site.dec.salt}")
	private String globalDecSalt;
	@Value("${site.domain}")
	private String siteDomain;
	
	// 随便看看(站内动态)
	@GetMapping(path="/home")
	@OnlineDescriptor(action=ForumActionEnum.COMMON_CASUAL)
	public String home(
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model) {
		List<Topic> rs = topicService.getRecentRelateContent(10).stream().sorted(Comparator.comparing(Topic::getRankingDateTime).reversed()).collect(Collectors.toList());
		model.addAttribute("rs", rs);
		return "default/index";
	}
	// [图片版]随便看看(站内动态)
	@GetMapping(path="/home/album")
	@OnlineDescriptor(action=ForumActionEnum.COMMON_CASUAL)
	public String coverHome(
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model) {
		model.addAttribute("rs", albumService.getRecent(12).collect(Collectors.toList()));
		return "default/index_album";
	}
	
	// 所有版块
	@GetMapping(path = "/board/home")
	@OnlineDescriptor(action=ForumActionEnum.BOARD_HOME)
	public String listBoard(MemberSessionBean mbean, HttpServletRequest request, Model model) {
		List<BoardGroup> rs = boardGroupService.getAllUsedAndBoard(true);
		model.addAttribute("rs", rs);
		return "default/board/index";
	}
	
	// 找回密码:第一步
	@GetMapping(path="/lostPswd")
	public String resetPswdOneStepForm(
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			HttpServletRequest request, 
			Model model) {
		MemberPasswordLostForm form = new MemberPasswordLostForm();
		form.setToken(token);
		model.addAttribute("form", form);
		return "index";
	}
	@PostMapping(path="/lostPswd")
	public String resetPswdOneStepAction(
			@ModelAttribute("form") MemberPasswordLostForm form, 
			HttpServletRequest request, 
			Model model) {
		Optional<MemberSocialInfo> rmsi = memberSocialInfoService.getByMember(form.getNames(), form.getEmail(), globalDecSalt);
		if (!rmsi.isPresent()) {
			model.addAttribute("form", form);
			//
			model.addAttribute("errors", "请确认帐号是否已与邮箱关联");
			return "index";
		}
		long mid = rmsi.get().getMemberId();
		String v = Base64Utils.encodeToString(encodeJsonString(mid, form.getToken(), 3, System.currentTimeMillis()).getBytes());
		return String.format("redirect:/rsetPswd?token=%s&id=%d&v=%s", form.getToken(), mid, v);
	}
	
	// 找回密码:第二步
	@GetMapping(path="/rsetPswd")
	public String resetPswdTwoStepForm(
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			@RequestParam("id") long memberId, 
			@RequestParam("v") String hashValue, 
			HttpServletRequest request, 
			Model model) {
		MemberPassworResetForm form = new MemberPassworResetForm();
		form.setToken(token);
		form.setRecord(memberId);
		form.setDisi(hashValue);
		model.addAttribute("form", form);
		return "rsetPswd";
	}
	@PostMapping(path="/rsetPswd")
	public String resetPswdTwoStepAction(
			@ModelAttribute("form") MemberPassworResetForm form, 
			HttpServletRequest request, 
			Model model) {
		if (!Commons.isNotBlank(form.getDisi())) {
			model.addAttribute("form", form);
			//
			model.addAttribute("errors", "操作需要的参数丢失");
			return "rsetPswd";
		}
		Map<String, String> disiMap = decodeJsonString(new String(Base64Utils.decodeFromString(form.getDisi())), 4);
		if (disiMap.isEmpty()) {
			model.addAttribute("form", form);
			//
			model.addAttribute("errors", "参数信息不完整");
			return "rsetPswd";
		}
		//
		long finishTimeMills = System.currentTimeMillis();
		long startTimeMills = 0;
		try {
			startTimeMills = Long.valueOf(disiMap.get("timestamp"));
		} catch (Exception e) {
			startTimeMills = finishTimeMills;
		}
		//
		if (finishTimeMills == startTimeMills || finishTimeMills - startTimeMills > 360000) {
			model.addAttribute("form", form);
			//
			model.addAttribute("errors", "操作已经超时,请在3分钟内完成");
			return "rsetPswd";
		}
		if (memberService.resetPswd(form.getLongRecord(), form.getConfirmpswd(), MemberActionDescriptor.getInstance(request, form.getToken())).orElse(false)) {
			//--------------------------------------------------
			// 密码变化通知
			//--------------------------------------------------
			return "redirect:/rsetPswd/success.xhtml";
		}
		//
		model.addAttribute("errors", "重置密码操作失败,请稍候重新尝试");
		return "rsetPswd";
	}
	
	// 找回密码:第三步
	@GetMapping(path="/rsetPswd/success.xhtml")
	public String rsetPswdSuccess(HttpServletRequest request, Model model) throws IllegalAccessException {
		//来源页判断 http Referer:site.domain{http://center.test.com}/rsetPswd
		String reqRef = request.getHeader("referer");
		if(null == reqRef || !reqRef.equals(siteDomain+"/rsetPswd")){
			throw new IllegalAccessException("非法的请求路径");
		}
		return "rsetPswd_success";
	}

	private String encodeJsonString(long mid, String token, int limit, long timestamp) {
		Map<String, String> data = new HashMap<>();
		data.put("mid", mid + "");
		data.put("token", token);
		data.put("limit", limit + "");
		data.put("timestamp", timestamp + "");
		return Commons.toJson(data);
	}

	private Map<String, String> decodeJsonString(String jsonString, int keySize) {
		Map<String, String> data = Commons.fromString(jsonString);
		if (data == null || data.isEmpty() || data.size() != keySize) {
			return Collections.emptyMap();
		}
		return data;
	}

	// 举报回复的类别
	@GetMapping(path = "/report/type", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public Map<Integer,String> getReportType(HttpServletRequest request, Model model){
		return EnumArchitecture.getInstance(ForumReportTypeEnum.class);
	}
	
	//意见反馈
	@PostMapping(path = "/feedback", produces = "application/json;charset=UTF-8")
	@ResponseBody
	@OnlineDescriptor(action=ForumActionEnum.COMMON_FEEDBACK, isAjax=true)
	public TipMessage feedback(
			@RequestParam("title")String title, 
			@RequestParam("content")String content, 
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model){
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, token);
		Optional<BoardTopicCategoryIndex> btc = boardTopicCategoryIndexService.getFeedbackRelativeRecord();
		if (!btc.isPresent()) {
			return TipMessage.ofError("未知的存储目标");
		}
		return TipMessage.Builder.of(()->topicService.plug(new FeedbackPlugTopic(aec, title, content, btc.get())).isPresent()).success("感谢您反馈的意见或建议").error("操作失败");
	}
	
	@GetMapping(path = "/ip")
	public String ipQuery(
			@RequestParam(value = "addr", required = false, defaultValue = "")String ipAddr, 
			HttpServletRequest request, 
			Model model){
		String result = "";
		if(Commons.isNotBlank(ipAddr)){
			try{
				Optional<String> data = IPMatcher.getInstance().matchToString(ipAddr);
				if(!data.isPresent()){
					result = "*";
				}else{
					result = data.get();
				}
			}catch(Exception e){
				result = "undefined";
			}
		}
		model.addAttribute("result", result);
		return "ip_query";
	}
}
