package com.zjt.web;

import com.alibaba.fastjson.JSON;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.zjt.entity.*;
import com.zjt.service.MaterialType;
import com.zjt.service.TmenuService;
import com.zjt.service.TroleService;
import com.zjt.service.TuserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/user")
public class UserController {

	private static final String ADMIN_ROLE = "admin";
	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
	private static final String ID_PREFIX = "S";

	@Resource
	private MaterialType materialType;

	@Resource
	private TroleService troleService;

	@Resource
	private TuserService tuserService;

	@Resource
	private TmenuService tmenuService;

	@RequestMapping("list")
	public String select(String id, String storeCode, String createtime, String receive, Model model, HttpSession session) {
		Tuser users = (Tuser) session.getAttribute("currentUser");
		List<cgmaterial> collect1;
		String id1 = "";

		if (StringUtils.isNotEmpty(id)) {
			id1 = id.substring(1);
		}

		SimpleDateFormat sdf1 = new SimpleDateFormat(DATE_FORMAT);
		if (StringUtils.isNotEmpty(createtime)) {
			String[] split1 = createtime.split(" - ");
			if (StringUtils.isNotEmpty(storeCode)) {
				if (ADMIN_ROLE.equals(users.getTrueName())) {
					collect1 = materialType.selectDataBy(id1, storeCode, split1[0], split1[1], receive);
				} else {
					collect1 = materialType.selectDataBy(id1, users.getUserName(), split1[0], split1[1], receive);
				}
			} else {
				if (ADMIN_ROLE.equals(users.getTrueName())) {
					collect1 = materialType.selectDataBy(id1, "", split1[0], split1[1], receive);
				} else {
					collect1 = materialType.selectDataBy(id1, users.getUserName(), split1[0], split1[1], receive);
				}
			}
		} else {
			if (StringUtils.isNotEmpty(storeCode)) {
				if (ADMIN_ROLE.equals(users.getTrueName())) {
					collect1 = materialType.selectDataBy(id1, storeCode, "", "", receive);
				} else {
					collect1 = materialType.selectDataBy(id1, users.getUserName(), "", "", receive);
				}
			} else {
				if (ADMIN_ROLE.equals(users.getTrueName())) {
					collect1 = materialType.selectDataBy(id1, "", "", "", receive);
				} else {
					collect1 = materialType.selectDataBy(id1, users.getUserName(), "", "", receive);
				}
			}
		}
		model.addAttribute("listcg", collect1);

		Predicate<cgmaterial> predicate = a -> {
			if (!ADMIN_ROLE.equals(users.getTrueName())) {
				return a.getUsername().equals(users.getTrueName());
			}
			return true;
		};

		Predicate<cgmaterial> predicate2 = a -> {
			if (StringUtils.isNotEmpty(createtime)) {
				String[] split = createtime.split(" - ");
				SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
				String createTimeStr = sdf.format(a.getCreatetime());
				return createTimeStr.compareTo(split[0]) > 0 && createTimeStr.compareTo(split[1]) < 0;
			}
			return true;
		};

		Predicate<cgmaterial> predicate4 = a -> StringUtils.isEmpty(storeCode) || a.getStore().equals(storeCode);
		Predicate<cgmaterial> predicate5 = a -> StringUtils.isEmpty(id) || (ID_PREFIX + a.getId()).equals(id.replace(",", ""));

		// 合并所有过滤条件
		List<cgmaterial> collect = collect1.stream()
				.filter(predicate)
				.filter(predicate2)
				.filter(predicate4)
				.filter(predicate5)
				.collect(Collectors.toList());

		return "mypackage/selectcg";
	}

	@RequestMapping("input")
	public String input() {
		return "mypackage/input";
	}

	@RequestMapping("test")
	public String test() {
		return "mypackage/test";
	}

	@RequestMapping("insert")
	public String insert(@RequestParam("list") String userList, HttpSession session) {
		List<cgmaterial> cgmaterials = JSON.parseArray(userList, cgmaterial.class);
		Tuser user = (Tuser) session.getAttribute("currentUser");
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		String s = user.getId() + "" + df.format(new Date());

		Consumer<cgmaterial> consumer = materialType::insertCg;

		cgmaterials.stream()
				.filter(a -> a.getMaterialcode() != null && a.getWz() != null && a.getLy() != null)
				.map(a -> {
					a.setId(Long.parseLong(s));
					a.setUsername(user.getTrueName());
					a.setCreatetime(new Date());
					a.setStore(user.getUserName());
					return a;
				})
				.forEach(consumer);

		return "mypackage/test";
	}

	@ResponseBody
	@PostMapping("/login")
	public Map<String, Object> login(String imageCode, @Valid Tuser user, BindingResult bindingResult, HttpSession session) {
		Map<String, Object> map = new HashMap<>();
		if (StringUtils.isEmpty(imageCode)) {
			map.put("success", false);
			map.put("errorInfo", "请输入验证码！");
			return map;
		}
		if (!session.getAttribute("checkcode").equals(imageCode)) {
			map.put("success", false);
			map.put("errorInfo", "验证码输入错误！");
			return map;
		}
		if (bindingResult.hasErrors()) {
			map.put("success", false);
			map.put("errorInfo", bindingResult.getFieldError().getDefaultMessage());
			return map;
		}

		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword());
		try {
			subject.login(token);
			if (!subject.isAuthenticated()) {
				map.put("success", false);
				map.put("errorInfo", "认证失败！");
				return map;
			}

			String userName = (String) SecurityUtils.getSubject().getPrincipal();
			Example tuserExample = new Example(Tuser.class);
			tuserExample.or().andEqualTo("userName", userName);
			Tuser currentUser = tuserService.selectByExample(tuserExample).get(0);
			session.setAttribute("currentUser", currentUser);

			List<Trole> roleList = troleService.selectRolesByUserId(currentUser.getId());
			map.put("roleList", roleList);
			map.put("roleSize", roleList.size());
			map.put("success", true);
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			map.put("success", false);
			map.put("errorInfo", "用户名或者密码错误！");
			return map;
		}
	}

	@ResponseBody
	@PostMapping("/saveRole")
	public Map<String, Object> saveRole(Integer roleId, HttpSession session) {
		Map<String, Object> map = new HashMap<>();
		Trole currentRole = troleService.selectByKey(roleId);
		session.setAttribute("currentRole", currentRole);

		putTmenuOneClassListIntoSession(session);

		map.put("success", true);
		return map;
	}

	@GetMapping("/logout")
	public String logout() {
		SecurityUtils.getSubject().logout();
		return "redirect:/tologin";
	}

	@ResponseBody
	@GetMapping("/loadMenuInfo")
	public String loadMenuInfo(HttpSession session, Integer parentId) {
		putTmenuOneClassListIntoSession(session);

		Trole currentRole = (Trole) session.getAttribute("currentRole");
		String json = getAllMenuByParentId(parentId, currentRole.getId()).toString();
		return json;
	}

	private JsonObject getAllMenuByParentId(Integer parentId, Integer roleId) {
		JsonObject resultObject = new JsonObject();
		JsonArray jsonArray = getMenuByParentId(parentId, roleId);

		for (int i = 0; i < jsonArray.size(); i++) {
			JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
			Example example = new Example(Tmenu.class);
			example.or().andEqualTo("pId", jsonObject.get("id").getAsString());

			if (tmenuService.selectCountByExample(example) == 0) {
				continue;
			} else {
				resultObject.add(jsonObject.get("title").getAsString(), getAllMenuJsonArrayByParentId(jsonObject.get("id").getAsInt(), roleId));
			}
		}
		return resultObject;
	}

	private JsonArray getAllMenuJsonArrayByParentId(Integer parentId, Integer roleId) {
		JsonArray jsonArray = getMenuByParentId(parentId, roleId);

		for (int i = 0; i < jsonArray.size(); i++) {
			JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
			Example example = new Example(Tmenu.class);
			example.or().andEqualTo("pId", jsonObject.get("id").getAsString());

			if (tmenuService.selectCountByExample(example) == 0) {
				continue;
			} else {
				jsonObject.add("children", getAllMenuJsonArrayByParentId(jsonObject.get("id").getAsInt(), roleId));
			}
		}
		return jsonArray;
	}

	private JsonArray getMenuByParentId(Integer parentId, Integer roleId) {
		HashMap<String, Object> paraMap = new HashMap<>();
		paraMap.put("pid", parentId);
		paraMap.put("roleid", roleId);
		List<Tmenu> menuList = tmenuService.selectByParentIdAndRoleId(paraMap);

		JsonArray jsonArray = new JsonArray();
		for (Tmenu menu : menuList) {
			JsonObject jsonObject = new JsonObject();
			jsonObject.addProperty("id", menu.getId());
			jsonObject.addProperty("title", menu.getName());
			jsonObject.addProperty("spread", false);
			jsonObject.addProperty("icon", menu.getIcon());
			if (StringUtils.isNotEmpty(menu.getUrl())) {
				jsonObject.addProperty("href", menu.getUrl());
			}
			jsonArray.add(jsonObject);
		}
		return jsonArray;
	}

	public void putTmenuOneClassListIntoSession(HttpSession session) {
		Example example = new Example(Tmenu.class);
		example.or().andEqualTo("pId", 1);
		List<Tmenu> tmenuOneClassList = tmenuService.selectByExample(example);
		session.setAttribute("tmenuOneClassList", tmenuOneClassList);
	}
}
