package com.apobates.forum.thrones.admin.controller;

import com.apobates.forum.core.service.TopicActionCollectionService;
import java.util.Collections;
import java.util.List;
import java.util.Map;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.event.elderly.IpLocation;
import com.apobates.forum.event.elderly.MemberActionDescriptor;
import com.apobates.forum.event.utils.IpMatchLocationResult;
import com.apobates.forum.member.MemberProfileBean;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.member.entity.MemberActiveRecords;
import com.apobates.forum.member.entity.MemberGroupEnum;
import com.apobates.forum.member.entity.MemberOnline;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.member.entity.MemberSocialInfo;
import com.apobates.forum.member.service.MemberActiveRecordsService;
import com.apobates.forum.member.service.MemberOnlineService;
import com.apobates.forum.member.service.MemberService;
import com.apobates.forum.member.service.MemberSocialInfoService;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.thrones.admin.controller.form.MemberLeaderForm;
import com.apobates.forum.thrones.admin.controller.form.MemberPassportForm;
import com.apobates.forum.thrones.admin.exception.ResourceNotFoundException;
import com.apobates.forum.thrones.admin.vo.MemberActionBean;
import com.apobates.forum.utils.lang.CommonBean;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.DateTimeUtils;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.lang.EnumArchitecture;
import eu.bitwalker.useragentutils.UserAgent;
import java.util.HashMap;
import java.util.Optional;
import javax.validation.Valid;
import org.springframework.validation.BindingResult;

/**
 * 会员控制器
 *
 * @author xiaofanku@live.cn
 * @since 20190321
 */
@Controller
@RequestMapping(value = "/member")
public class AdminMemberController {
    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberSocialInfoService memberSocialInfoService;
    @Autowired
    private TopicActionCollectionService topicActionCollectionService;
    @Autowired
    private MemberActiveRecordsService memberActiveRecordsService;
    @Autowired
    private MemberOnlineService memberOnlineService;
    @Value("${site.pageSize}")
    private int pageSize;
    
    // 最近注册的会员
    @GetMapping(path = "/")
    public String listPage(HttpServletRequest request, Model model) {
        model.addAttribute("rs", memberService.getRecent(pageSize).collect(Collectors.toList()));
        return "admin/member/index";
    }
    
    // 会员首页
    @GetMapping(path = "/{id}.xhtml")
    public String homePage(@PathVariable("id") long memberId, HttpServletRequest request, Model model) {
        Member m = memberService.get(memberId).orElseThrow(()->new ResourceNotFoundException("指定的会员不存在或暂时无法访问"));
        model.addAttribute("member", m);
        //会员等级信息
        Map<ForumActionEnum, Long> rawdata = topicActionCollectionService.statsMemberAllAction(memberId);
        MemberProfileBean memberProfile = memberService.calcMemberProfileBean(m.getId(), rawdata).orElseGet(MemberProfileBean::guest);
        Map<String,String> profile = new HashMap<>();
        Optional<MemberOnline> mo = memberOnlineService.get(memberId);
        if (mo.isPresent()) {
            try{
                profile.put("activeDateTime", DateTimeUtils.formatClock(mo.get().getActiveDateTime()));
            }catch(Exception e){
                profile.put("activeDateTime", "-");
            }
        }
        model.addAttribute("profile", memberProfile.toMergeMap(profile));
        return "admin/member/view";
    }
    
    // 社交信息
    @GetMapping(path = "/social")
    public String socialPage(
            @RequestParam("member") long memberId,
            HttpServletRequest request,
            Model model) {
        MemberSocialInfo rs = memberSocialInfoService.getByMember(memberId).orElseThrow(()->new ResourceNotFoundException("指定会员的社交信息不存在或暂时无法访问"));
        model.addAttribute("social", rs);
        return "admin/member_social/index";
    }
    
    // 整体:根据登录帐号查看会员
    @GetMapping(path = "/search", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<Long, String> lookMember(@RequestParam("names") String names, HttpServletRequest request, Model model) {
        //是否以@开头
        if (!Commons.isNotBlank(names) || !names.startsWith("@")) {
            return Collections.emptyMap();
        }
        String memberNames = names.substring(1);
        long memberId = memberService.existMemberNames(memberNames);
        return Map.ofEntries(Map.entry(memberId, memberNames));
    }
    
    // 任命版主时根据登录帐号
    @GetMapping(path = "/suggest", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<CommonBean> suggestMember(@RequestParam("names") String names, HttpServletRequest request, Model model) {
        return memberService.searchByNames(names, pageSize).map(mb -> new CommonBean(mb.getId(), mb.getNames())).collect(Collectors.toList());
    }
    //校验uid时的
    @GetMapping(path = "/detection/uid")
    @ResponseBody
    public TipMessage checkMemberUID(
            @RequestParam("value") String uidString,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        long memberId = Commons.stringToLong(uidString.substring(1), 0L);
        if (memberId <= 0) {
            return TipMessage.ofError("会员不接受消息");
        }
        Member m = memberService.get(memberId).orElse(null);
        if (null == m || mbean.getMid() == m.getId()) {
            return TipMessage.ofError("会员不存在");
        }
        return TipMessage.ofSuccess(m.getNickname());
    }
    //编辑密码
    @GetMapping(path = "/passport")
    public String editForm(@RequestParam("id") long id, HttpServletRequest request, Model model) {
        MemberPassportForm form = new MemberPassportForm();
        form.setRecord(id);
        model.addAttribute("form", form);
        return "admin/member/passport";
    }
    
    @PostMapping(path = "/passport")
    public String editAction(
            @ModelAttribute("form") MemberPassportForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Optional<Boolean> symbol = memberService.resetPswd(form.getLongRecord(), form.getNewpswd(), getDescriptorInstance(request, form.getToken()));
        if (symbol.orElse(false)) {
            return "redirect:/member/";
        }
        model.addAttribute("errors", "修改会员密码操作失败");
        model.addAttribute("form", form);
        return "admin/member/passport";
    }
    
    //新社区经理
    @GetMapping(path = "/create")
    public String createTopicForm(
            HttpServletRequest request,
            Model model) {
        MemberLeaderForm form = new MemberLeaderForm();
        model.addAttribute("form", form);
        return "admin/member/create";
    }
    
    @PostMapping(path = "/create")
    public String createTopicAction(
            HttpServletRequest request,
            MemberSessionBean mbean,
            @Valid @ModelAttribute("form") MemberLeaderForm form,
            BindingResult bindingResult,
            Model model) {
        if (bindingResult.hasErrors()) {
            model.addAttribute("form", form);
            return "admin/member/create";
        }
        boolean symbol = memberService.create(
                form.getNames(),
                form.getPswd(),
                form.getNickname(),
                form.getEnumRole(),
                getDescriptorInstance(request, form.getToken()))>0;
        if (symbol) {
            return "redirect:/member/";
        }
        model.addAttribute("errors", "新增社区经理操作失败");
        model.addAttribute("form", form);
        return "admin/member/create";
    }
    //会员角色
    @GetMapping(path = "/role/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<Integer, String> getAllRoles(HttpServletRequest request, Model model) {
        return EnumArchitecture.getInstance(MemberRoleEnum.class);
    }
    //会员组
    @GetMapping(path = "/group/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<Integer, String> getAllGroup(HttpServletRequest request, Model model) {
        //滤掉0,-1,-2
        return EnumArchitecture.getInstance(MemberGroupEnum.class);
    }
    //指定会员的操作记录
    @GetMapping(path = "/action/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<MemberActionBean> getMemberOperateAction(
            @RequestParam("id") long memberId,
            @RequestParam("names") String names,
            HttpServletRequest request,
            Model model) {
        List<MemberActiveRecords> rs = memberActiveRecordsService.getByMember(memberId, names, pageSize).collect(Collectors.toList());
        return rs.stream().map(MemberActionBean::new).collect(Collectors.toList());
    }
    public static MemberActionDescriptor getDescriptorInstance(HttpServletRequest request, String token){
        final String referrer = request.getHeader("referer");
        final String ipAddr = Commons.getRequestIp(request);
        final String operateToken = Commons.isNotBlank(token) ? token : "-";
        final String agent = request.getHeader("User-Agent");
        //
        return new MemberActionDescriptor() {
            @Override
            public String getToken() {
                return operateToken;
            }
            
            @Override
            public IpLocation location() {
                return new IpMatchLocationResult(ipAddr);
            }
            
            @Override
            public String getReferrer() {
                return referrer;
            }
            
            @Override
            public String getDevice() {
                return UserAgent.parseUserAgentString(agent).getOperatingSystem().getName();
            }
            
            @Override
            public String getAgent() {
                return agent;
            }
        };
    }
}