package xyz.luxnk.lproject.module;

import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.QueryResult;
import org.nutz.dao.pager.Pager;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.Scope;
import org.nutz.mvc.annotation.*;
import org.nutz.mvc.filter.CheckSession;
import xyz.luxnk.lproject.bean.UserInfo;
import xyz.luxnk.lproject.bean.UserProfile;
import xyz.luxnk.lproject.util.Toolkit;

import javax.servlet.http.HttpSession;
import java.util.Date;

@IocBean    // 声明Ioc容器中的一个Bean
@At("/user")    // 整个模块的路径前缀
@Ok("json:{locked: 'password|salt', ignoreNull:true}")  // 忽略password和salt属性，忽略空属性的json输出
@Fail("http:500")   // 抛出异常的话，就走500页面
@Filters(@By(type = CheckSession.class, args = {"me", "/"}))    // 检查当前Session是否带me这个属性
public class UserModule extends BaseModule {

    @At("/")
    @Ok("jsp:jsp.user.list")    // 真实路径是 /WEB-INF/jsp/user/list.jsp
    public void index() {}

    /**
     * 统计用户数
     * @return
     */
    @At
    public int count() {
        return dao.count(UserInfo.class);
    }

    /**
     * 用户登录
     * @param username
     * @param password
     * @param session
     * @return
     */
    @At
    @Filters()  // 覆盖UserModule类的@Filters设置，因为登录可不能要求是个已经登陆的Session
    public Object login(@Param("username")String username, @Param("password")String password, @Param("captcha")String captcha, @Attr(scope = Scope.SESSION, value = "nutz_captcha")String _captcha, HttpSession session) {
        NutMap re = new NutMap();
        if (!Toolkit.checkCaptcha(_captcha, captcha)) {
            return re.setv("ok", false).setv("msg", "验证码错误");
        }
        UserInfo userInfo = dao.fetch(UserInfo.class, Cnd.where("username", "=", username).and("password", "=", password));
        if (userInfo == null) {
            return re.setv("ok", false).setv("msg", "用户名或密码错误");
        } else {
            session.setAttribute("me", userInfo.getId());
            return re.setv("ok", true);
        }
    }

    /**
     * 用户登出
     * @param session
     */
    @At
    @Ok(">>:/") // 跟其他方法不同，这个方法完成后就跳转到首页了
    public void logout(HttpSession session) {
        session.invalidate();
    }

    /**
     * 校验用户信息
     * @param userInfo
     * @param create
     * @return
     */
    protected String checkUser(UserInfo userInfo, boolean create) {
        if (userInfo == null) {
            return "空对象";
        }
        if (create) {
            if (Strings.isBlank(userInfo.getUsername()) || Strings.isBlank(userInfo.getPassword()))
                return "用户名/密码不能为空";
        } else {
            if (Strings.isBlank(userInfo.getPassword()))
                return "密码不能为空";
        }
        String passwd = userInfo.getPassword().trim();
        if (6 > passwd.length() || passwd.length() > 12) {
            return "密码长度错误";
        }
        userInfo.setPassword(passwd);
        if (create) {
            int count = dao.count(UserInfo.class, Cnd.where("username", "=", userInfo.getUsername()));
            if (count != 0) {
                return "用户已经存在";
            }
        } else {
            if (Strings.isBlank(userInfo.getId())) {
                return "用户Id非法";
            }
        }
        if (userInfo.getUsername() != null) {
            userInfo.setUsername(userInfo.getUsername().trim());
        }
        return null;
    }

    /**
     * 新增用户
     * @param userInfo
     * @return
     */
    @At
    public Object add(@Param("..")UserInfo userInfo) {  // 两个点号是表示按对象属性一一设置
        NutMap re = new NutMap();
        String msg = checkUser(userInfo, true);
        if (msg != null) {
            return re.setv("ok", false).setv("msg", msg);
        }
        userInfo.setCreateTime(new Date());
        userInfo.setUpdateTime(new Date());
        userInfo = dao.insert(userInfo);
        return re.setv("ok", true).setv("data", userInfo);
    }

    /**
     * 更新用户
     * @param userInfo
     * @return
     */
    @At
    public Object update(@Param("..")UserInfo userInfo) {
       NutMap re = new NutMap();
       String msg = checkUser(userInfo, false);
       if (msg != null) {
           return re.setv("ok", false).setv("msg", msg);
       }
       userInfo.setUsername(null);  // 不允许更新用户名
       userInfo.setCreateTime(null);    // 不允许更新创建时间
       userInfo.setUpdateTime(new Date());  // 设置正确的更新时间
       dao.updateIgnoreNull(userInfo);  // 真正更新的其实只有password和salt
       return re.setv("ok", true);
    }

    /**
     * 删除用户
     * @param id
     * @param me
     * @return
     */
    @At
    @Aop(TransAop.READ_COMMITTED)
    public Object delete(@Param("id")String id, @Attr("me")String me) {
        if (me.equals(id)) {
            return new NutMap().setv("ok", false).setv("msg", "不能删除当前用户！");
        }
        dao.delete(UserInfo.class, id); // 再严谨一些的话，需要判断结果是否为>0
        dao.clear(UserProfile.class, Cnd.where("userId", "=", id));
        return new NutMap().setv("ok", true);
    }

    /**
     * 查询用户
     * @param name
     * @param pager
     * @return
     */
    @At
    public Object query(@Param("name")String name, @Param("..")Pager pager) {
        Cnd cnd = Strings.isBlank(name)? null : Cnd.where("name", "like", "%" + name + "%");
        QueryResult qr = new QueryResult();
        qr.setList(dao.query(UserInfo.class, cnd, pager));
        pager.setRecordCount(dao.count(UserInfo.class, cnd));
        qr.setPager(pager);
        return qr;  // 默认分页是第1页，每页20条
    }

}
