package com.jfinal.club.my.doc;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.club.common.banner.BannersService;
import com.jfinal.club.common.controller.BaseController;
import com.jfinal.club.common.interceptor.FrontAuthInterceptor;
import com.jfinal.club.common.model.*;
import com.jfinal.club.download.DownloadService;
import com.jfinal.club.my.ct.UserCtService;
import com.jfinal.club.my.favorite.FavoriteService;
import com.jfinal.club.my.newsfeed.UsersInfoIntreceptor;
import com.jfinal.club.my.ques.QuestionsService;
import com.jfinal.club.reg.RegService;
import com.jfinal.club.sdk.MyWxPayConfig;
import com.jfinal.club.sdk.WXPay;
import com.jfinal.club.sdk.WXPayUtil;
import com.jfinal.club.util.Cons;
import com.jfinal.club.util.IdWorker;
import com.jfinal.core.ActionKey;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;
import com.sun.javafx.tk.RenderJob;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @ClassName UsersDocController
 * @Description TODO
 * @Author caolong
 * @Date 2020/3/17 17:21
 */
@Before(TypeIntreceptor.class)
public class UsersDocController extends BaseController {


    @Inject
    RegService regSrv;

    @Inject
    UsersDocService usersDocService;

    @Inject
    UserCtService userCtService;

    @Inject
    QuestionsService questionsService;

    @Inject
    DownloadService downloadService;

    @Inject
    BannersService bannersService;

    @Inject
    FavoriteService favoriteService;

    public void fileDetail( ) {
        Integer id = getInt("id");
        if (null == id) {
            renderText("");
        }

        Doc doc = usersDocService.getDocById(id);
        setAttr("doc", doc);

        Users user = usersDocService.getUserByDocId(id);
        setAttr("user", user);

        //可能喜欢
        Page< Doc > docByUsersLike = null;
        if (isLogin( )) {
            docByUsersLike = usersDocService.getDocByUsersLike(getloginUsersId( ), getParaToInt("p", 1));
        } else {
//            猜你喜欢
            docByUsersLike = usersDocService.getDocByUsersLike(0, getParaToInt("p", 1));
        }
        setAttr("docByUsersLike", docByUsersLike.getList( ));

        // 热门
        Page< Doc > docByUping = usersDocService.getDocByUping(getParaToInt("p", 1), 0, 50);
        setAttr("docByUping", docByUping.getList( ));

        //update count

        usersDocService.updateCount(1, id);


        render("file_detail.html");
    }

    public void fileStream( ) {
        Integer id = getInt("id");
        if (null == id) {
            renderText("");
        }

        Doc doc = usersDocService.getDocById(id);

        String webRootPath = PathKit.getWebRootPath( );
        String coverturl = doc.getCoverturl( );

        renderFile(Paths.get(webRootPath, coverturl).toFile( ));
    }

    /**
     * @return void
     * @Author Cc
     * @Description //TODO  文档前端首页
     * @Date 2020/3/18
     * @Param []
     **/
    public void docIndex( ) {
        Long countDoc = usersDocService.countDoc( );
        setAttr("allDoc", countDoc);
        Page< Doc > docLike = null;
        if (isLogin( )) {
            docLike = usersDocService.getDocByUsersLike(getloginUsersId( ), getParaToInt("p", 1));
            //文档下载个数和下载个数
            setAttr("docCount", usersDocService.countDocById(getloginUsersId( )));
            setAttr("countDownload", downloadService.countDownloadById(getloginUsersId( )));
        } else {
//            猜你喜欢
            docLike = usersDocService.getDocByUsersLike(0, getParaToInt("p", 1));
        }
        setAttr("docLike", docLike);
        // 热门
        Page< Doc > docByUping = usersDocService.getDocByUping(getParaToInt("p", 1), 0, 50);
        // 精品
        Page< Doc > docByUpingTop = usersDocService.getDocByUping(getParaToInt("p", 1), 1, 50);
        setAttr("docUping", docByUping);
        setAttr("docUpingTop", docByUpingTop);

        List< Record > records = usersDocService.docTypeList( );
        setAttr("doctypes", records);

        List< Doc > listDocListByType = usersDocService.docTypeListByType( );
        setAttr("listDocListByType", listDocListByType);

        setAttr("banners", bannersService.selectAllBanners( ));

        render("fl_index.html");
    }


    /**
     * @return void
     * @Author Cc
     * @Description //TODO 猜你喜欢ajax
     * @Date 2020/3/21
     * @Param []
     **/
    public void likeDoc( ) {
        int pageNum = getParaToInt("p") + 1;
        Page< Doc > docByUsersLike = null;
        if (isLogin( )) {
            docByUsersLike = usersDocService.getDocByUsersLike(getloginUsersId( ), getParaToInt("p", 1));
        } else {
//            猜你喜欢
            docByUsersLike = usersDocService.getDocByUsersLike(0, getParaToInt("p", 1));

        }
        //猜你喜欢循环功能 从第一页开始
        if (docByUsersLike.getList( ).size( ) == 0) {
            docByUsersLike = usersDocService.getDocByUsersLike(0, 1);
            pageNum = 1;
        }
        JSONObject object = new JSONObject( );
        object.put("data", docByUsersLike.getList( ));
        object.put("pageNum", pageNum);
        renderJson(object);
    }

    /**
     * @return void
     * @Author Cc
     * @Description //TODO  文档页面
     * @Date 2020/3/18
     * @Param []
     **/
    public void file( ) {
        //top 0普通文档1精品文档  lc 20200409
        int top = getInt("top", 0);
        int docTypeId = getInt("doctype", 0);

        Page< Doc > docTop;
        if (top == 0) {
            //查询普通文档
            docTop = usersDocService.getAllCommonDoc(getInt("p", 1), Cons.FRONT_PAGE_SIZE, docTypeId);
            //每个文档类型数量
            List< Record > countCommonDoc = usersDocService.getCountCommonDoc( );
            setAttr("hotdoc", countCommonDoc);
        } else {
            //精品文档
            docTop = usersDocService.getAllJingPinDoc(getInt("p", 1), Cons.FRONT_PAGE_SIZE, docTypeId);
            //每个精品类型的数量
            List< Record > countJingPinDoc = usersDocService.getCountJingPinDoc( );
            setAttr("hotdoc", countJingPinDoc);
        }

        Doctype docType = usersDocService.docTypeById(docTypeId);
        setAttr("docType", docType);
        setAttr("docTypeId", docTypeId);
        setAttr("top", top);
        setAttr("docTop", docTop);
        render("file.html");
    }


    /**
     * @return void
     * @Author Cc
     * @Description //TODO  搜索页面
     * @Date 2020/3/18
     * @Param [] type == 1 文件搜索页面
     **/
    public void searchList( ) {
        String text = getPara("text");
        int docType = 0;
        if (!StrKit.isBlank(getPara("rad"))) {
            docType = Integer.parseInt(getPara("rad"));
        }
        int type = Integer.parseInt(getPara("type"));
        if (type == 1) {
            Page< Doc > docList = usersDocService.getDocListAll(text, docType, getParaToInt("p", 1));
            setAttr("List", docList);
        } else if (type == 2) {
            Page< Userct > userCtListAll = userCtService.getUserCtListAll(text, 10, getParaToInt("p", 1));
            setAttr("List", userCtListAll);
        } else if (type == 3) {
            Page< Questions > questionsPage = questionsService.getUserCtListAll(text, 10, getParaToInt("p", 1));
            setAttr("List", questionsPage);
        }
        setAttr("rad", docType);
        setAttr("type", type);
        setAttr("text", text);
        render("search_list.html");
    }


    /**
     * 界面查询
     */
    @ActionKey("search")
    public void search( ) {
        //文件类型 1:pdf 2:word 3excel 4:ppt 5txt 6:其他
        Integer rad = getInt("rad", 0);
        String text = get("text", null);
        Integer types = getInt("types", 0);
        Page page = usersDocService.searchAll(getInt("p", 1), Cons.FRONT_PAGE_SIZE, types, text, rad);
        setAttr("List", page);
        setAttr("type", types);
        setAttr("text", text);
        render("search_list.html");
    }


    /**
     * @return void
     * @Author Cc
     * @Description //TODO  文档审核成功
     * @Date 2020/3/18
     * @Param []
     **/
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void fileSuccess( ) {
        Page< Doc > docList = usersDocService.getDocList(getloginUsersId( ), 1, getPara("text"), getParaToInt("p", 1));
        setAttr("docList", docList);
        setAttr("text", getPara("text"));
        setAttr("my_doc", true);
        render("file_success.html");
    }

    /**
     * @return void
     * @Author Cc
     * @Description //TODO  文档审核失败
     * @Date 2020/3/18
     * @Param []
     **/
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void fileFail( ) {
        Page< Doc > docList = usersDocService.getDocList(getloginUsersId( ), 2, getPara("text"), getParaToInt("p", 1));
        setAttr("docList", docList);
        setAttr("text", getPara("text"));
        setAttr("my_doc", true);
        render("file_fail.html");
    }

    /**
     * @return void
     * @Author Cc
     * @Description //TODO  文档待审核
     * @Date 2020/3/18
     * @Param []
     **/
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void index( ) {
        Page< Doc > docList = usersDocService.getDocList(getloginUsersId( ), 0, getPara("text"), getParaToInt("p", 1));
        setAttr("docList", docList);
        setAttr("text", getPara("text"));
        setAttr("my_doc", true);
        render("index.html");
    }

    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void delfile( ) {
        if (!StrKit.isBlank(getPara("id"))) {
            int id = Integer.parseInt(getPara("id"));
            Ret ret = usersDocService.deleteById(id);
            renderJson(ret);
        }
    }

    /**
     * @return void
     * @Author Cc
     * @Description //TODO 编辑文档页面跳转
     * @Date 2020/3/18
     * @Param []
     **/
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void fileUp( ) {
        keepPara("p");
        String docid = getPara("docid");
        if (!StrKit.isBlank(docid)) {
            Doc docById = usersDocService.getDocById(Integer.parseInt(docid));
            setAttr("doc", docById);
        }
        render("file_up.html");
    }

    /**
     * @return void
     * @Author Cc
     * @Description //TODO  文件发布/编辑
     * @Date 2020/3/18
     * @Param []
     **/
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void fileUps( ) {
        UploadFile uf = null;
        String types = "";
        try {
            uf = getFile("filenames", usersDocService.getAvatarTempDir( ), usersDocService.getAvatarMaxSize( ));
            types = getPara("types");
            if (uf == null) {
                if (!"1".equals(types)) {
                    renderJson(Ret.fail("msg", "请先选择上传文件"));
                    return;
                }
            }
        } catch (Exception e) {
            if (e instanceof com.jfinal.upload.ExceededSizeException) {
                renderJson(Ret.fail("msg", "文件大小超出范围"));
            } else {
                if (uf != null) {
                    // 只有出现异常时才能删除，不能在 finally 中删，因为后面需要用到上传文件
                    uf.getFile( ).delete( );
                }
                renderJson(Ret.fail("msg", e.getMessage( )));
            }
            return;
        }
        String reg = "^(([1-9][0-9]{0,14})|([0]{1})|(([0]\\.\\d{1,2}|[1-9][0-9]{0,14}\\.\\d{1,2})))$";
        String para = getPara("doc.docmoney");
        if (!para.matches(reg)) {
            renderJson(Ret.fail("msg", "金额输入有误!"));
            return;
        }
        Doc doc = getModel(Doc.class);
        if ("1".equals(types)) {
            if (uf != null) {
                Ret ret = usersDocService.uploadAvatar(getloginUsersId( ), uf);
                if (ret.isOk( )) {
                    String avatarUrl = ret.get("avatarUrl").toString( );
                    doc.setFiletype(Integer.parseInt(ret.get("filetype").toString( )));
                    Ret ret1 = usersDocService.updateDoc(doc, avatarUrl, getloginUsersId( ));
                    renderJson(ret1);
                } else {
                    renderJson(ret);
                }
            } else {
                Ret ret1 = usersDocService.updateDoc(doc, null, getloginUsersId( ));
                renderJson(ret1);
            }
        } else {
            Ret ret = usersDocService.uploadAvatar(getloginUsersId( ), uf);
            if (ret.isOk( )) {
                String avatarUrl = ret.get("avatarUrl").toString( );
                doc.setFiletype(Integer.parseInt(ret.get("filetype").toString( )));
                Ret ret1 = usersDocService.saveDoc(doc, avatarUrl, getloginUsersId( ), 0);
                renderJson(ret1);
                return;
            } else {
                renderJson(ret);
            }
        }
    }

    /**
     * 判断是否生成二维码
     * lc
     */
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void isCreateQrCode( ) {
        Integer id = getInt("id");
        Doc doc = usersDocService.getDocById(id);
        Doc doc1 = usersDocService.getByIdUserId(getloginUsersId( ), doc.getId( ));
        if (doc1 != null) {
            //直接下载
            renderJson(Ret.fail( ));
            return;
        }
        boolean qrCode = downloadService.createQrCode(getloginUsersId( ), id, doc.getDocmoney( ));
        if (qrCode) {
            //生成二维码
            renderJson(Ret.ok( ));
            return;
        } else {
            renderJson(Ret.fail( ));
        }

    }

    /**
     * 文档下载
     */
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void docDownload( ) {
        Doc doc = usersDocService.getDocById(getInt("id"));

        //文档对象为空
        if (doc == null) {
            renderJson(Ret.fail("fileError", "file not found"));
            return;
        }
        //文档需支付0费用,直接下载即可
        if (doc.getDocmoney( ) == 0 || doc.getDocmoney( ) == null) {
            //判断该用户是否生成过该文档订单 ,但没付款,更新订单号信息
            downloadService.getIfSave(getloginUsersId( ), doc.getId( ), doc.getDocname( ));
            usersDocService.updateCount(3, doc.getId( ));
            String download = PathKit.getWebRootPath( ) + doc.getDocurl( );
            renderFile(new File(download));
            return;
        }

        //如果已付过款
        Download dos = downloadService.getByUserIdDocIdPay(getloginUsersId( ), doc.getId( ));
        if (dos != null) {
            usersDocService.updateCount(3, doc.getId( ));
            String download = PathKit.getWebRootPath( ) + doc.getDocurl( );
            renderFile(new File(download));
            return;
        }
        //如果是自己上传的文档 可以直接下载
        Doc doc1 = usersDocService.getByIdUserId(getloginUsersId( ), doc.getId( ));
        if (doc1 != null) {
            //判断该用户是否生成过该文档订单 ,但没付款,更新订单号信息
            downloadService.getIfSave(getloginUsersId( ), doc.getId( ), doc.getDocname( ));
            usersDocService.updateCount(3, doc.getId( ));
            String download = PathKit.getWebRootPath( ) + doc.getDocurl( );
            renderFile(new File(download));
            return;
        }

        //生成二维码
        //创建idworker对象，生成支付订单号
        long out_trade_no = new IdWorker( ).nextId( );
        Ret ret = usersDocService.qrcode(out_trade_no, doc, getRequest( ));
        //提示失败
        if (ret.isFail( )) {
            renderJson(ret);
            return;
        }

        //判断该用户是否生成过该文档订单 ,但没付款,更新订单号信息
        Download download = downloadService.getNoPayByUserIdDocId(getloginUsersId( ), doc.getId( ));
        if (download == null) {
            Download d = new Download( );
            d.setAddtime(new Date( ));
            d.setDocid(doc.getId( ));
            d.setDocname(doc.getDocname( ));
            d.setUsersid(getloginUsersId( ));
            d.setOutTradeNo(out_trade_no + "");
            d.setPay(0);
            d.save( );
        } else {
            download.set("outTradeNo", out_trade_no).removeNullValueAttrs( ).update( );
        }

        //生成二维码
        if (StringUtils.isNotBlank(ret.getStr("code_url"))) {
            renderQrCode(ret.getStr("code_url"), 250, 250, 'H');
            return;
        }
    }


    /**
     * 微信支付 回调函数
     */
    public void notifyUrl( ) throws Exception {
        HttpServletRequest request = getRequest( );
        //读取参数
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream( )));
        String line;
        StringBuilder sb = new StringBuilder( );
        while ((line = br.readLine( )) != null) {
            sb.append(line);
        }
        if (StringUtils.isBlank(sb)) {
            return;
        }
        //支付结果通知的xml格式数据
        String notifyData = sb.toString( );
        MyWxPayConfig myWxPayConfig = new MyWxPayConfig( );
        WXPay wxpay = new WXPay(myWxPayConfig);
        Map< String, String > notifyMap = WXPayUtil.xmlToMap(notifyData);

        //验证签名是否正确
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            //支付成功
            if ("SUCCESS".equals(notifyMap.get("result_code"))) {
                //商户订单号
                String out_trade_no = notifyMap.get("out_trade_no");
                Download download = downloadService.getByOutTradeNo(out_trade_no);
                //不为空直接下载
                if (download != null) {
                    //更新成付款状态
                    download.set("pay", 1).removeNullValueAttrs( ).update( );
                    renderNull();
                    return;
                }
            } else {
                //log.info("微信支付回调函数：支付失败");
                renderJson(Ret.fail("msg", "二维码过期,请重新生成!"));
                return;
            }
        } else {
            //log.info("微信支付回调函数：微信签名错误");
            renderJson(Ret.fail("msg", "二维码过期,请重新生成!"));
            return;
        }
    }

    /**
     * js 是否执行递归定时器 判断是否付款
     */
    public void ifPay( ) {
        Download download = downloadService.getByUserIdDocIdPay(getloginUsersId( ), getInt("id"));
        //表示已付款
        if (download != null) {
            renderJson(Ret.ok( ));
        } else {
            //未付款
            renderJson(Ret.fail("msg","未付款"));
        }
    }

    /**
     * 文档收藏
     */
    @Before({FrontAuthInterceptor.class, UsersInfoIntreceptor.class})
    public void docColl( ) {
        Integer docId = getInt("id");

        Integer type = getInt("type", 1);
        Favorite f = favoriteService.getOneByUserIdDocId(getloginUsersId( ), docId, type);
        if (f != null) {
            if (f.delete( )) {
                editData(true, type, docId);
                renderJson(Ret.ok("msg", "取消收藏!"));
            } else {
                renderJson(Ret.fail("msg", "取消失败!"));
            }
        } else {
            boolean save = new Favorite( ).set("accountId", getloginUsersId( )).set("refType", type).set("refId", getInt("id", 0)).set("createAt", new Date( )).save( );
            if (save) {
                editData(false, type, docId);
                renderJson(Ret.ok("msg", "收藏成功!"));
            } else {
                renderJson(Ret.fail("msg", "收藏失败!"));
            }
        }
    }

    /**
     * 取消收藏
     */
    public void cancelColl( ) {
        Integer id = getInt("id");
        Integer type = getInt("type", 1);
        Favorite favorite = favoriteService.getOneById(id);
        if (type == 1) {
            Doc docById = usersDocService.getDocById(favorite.getRefId( ));
            docById.setLoveing(docById.getLoveing( ) - 1);
            docById.removeNullValueAttrs( ).update( );
        } else {
            Userct ctById = userCtService.getCtById(favorite.getRefId( ));
            ctById.setLoveing(ctById.getLoveing( ) - 1);
            ctById.removeNullValueAttrs( ).update( );
        }
        boolean b = new Favorite( ).dao( ).deleteById(id);
        if (b) {
            renderJson(Ret.ok("msg", "取消成功!"));
        } else {
            renderJson(Ret.fail("msg", "取消失败！"));
        }
    }

    /**
     * 添加收藏时 用到
     * 1文档，2百科 +1,-1操作
     */
    private void editData(boolean s, int type, int id) {
        if (type == 1) {
            Doc docById = usersDocService.getDocById(id);
            //更新数量
            if (s) {
                docById.setLoveing(docById.getLoveing( ) - 1);
            } else {
                docById.setLoveing(docById.getLoveing( ) + 1);
            }
            docById.removeNullValueAttrs( ).update( );
        } else {
            Userct ctById = userCtService.getCtById(id);
            if (s) {
                ctById.setLoveing(ctById.getLoveing( ) - 1);
            } else {
                ctById.setLoveing(ctById.getLoveing( ) + 1);
            }
            ctById.removeNullValueAttrs( ).update( );
        }
    }


    /**
     * 收藏按钮显示
     */
    public void showColl( ) {

        Doc doc = usersDocService.getDocById(getInt("id"));
        doc.setLooking(doc.getLooking() - 1);
        doc.removeNullValueAttrs().update();

        if (getloginUsersId( ) == 0) {
            renderJson(Ret.fail( ));
            return;
        }
        Integer type = getInt("type", 1);
        Favorite f = favoriteService.getOneByUserIdDocId(getloginUsersId( ), getInt("id"), type);
        //true收藏
        if (f != null) {
            renderJson(Ret.ok( ));
        } else {
            renderJson(Ret.fail( ));
        }

    }


}
