package com.jfinal.club.my.doc;

import com.jfinal.aop.Inject;
import com.jfinal.club.common.kit.IpKit;
import com.jfinal.club.common.model.*;
import com.jfinal.club.download.DownloadService;
import com.jfinal.club.sdk.WXPayUtil;
import com.jfinal.club.util.Cons;
import com.jfinal.club.util.HttpClient;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;

import static com.jfinal.club.my.doc.DocKit.suFfix;

/**
 * @ClassName UsersDocService
 * @Description TODO
 * @Author caolong
 * @Date 2020/3/18 11:00
 */
public class UsersDocService {


    public static final String extName = ".jpg";

    private final String docCacheName = "doc";

    private Doc docDao = new Doc( ).dao( );

    private Doctype doctype = new Doctype( ).dao( );

    private Loveings loveings = new Loveings( ).dao( );

    @Inject
    DownloadService downloadService;

    // 用户上传图像最多只允许 1M大小
    public int getAvatarMaxSize( ) {
        return 1024 * 1024 * 100;
    }

    /**
     * 上传文件
     */
    public String getAvatarTempDir( ) {
        return "/avatar/";
    }


    public Ret uploadAvatar(int usersId, UploadFile uf) {
        if (uf == null) {
            return Ret.fail("msg", "上传文件UploadFile对象不能为null");
        }
        try {
            if (DocKit.notImageExtName(uf.getFileName( ))) {
                return Ret.fail("msg", "文件类型不正确，只支持图片类型：pdf、doc、docx、xlsx、xls、pptx、ppt、txt");
            }
            String avatarUrl = "/upload" + getAvatarTempDir( ) + usersId + "_" + System.currentTimeMillis( ) + "." + suFfix(uf.getFileName( ));
            String saveFile = PathKit.getWebRootPath( ) + avatarUrl;
            int i = typeSuffix(suFfix(uf.getFileName( )));
            File save = new File(saveFile);
            boolean saveResult = uf.getFile( ).renameTo(save);
            return Ret.ok("avatarUrl", avatarUrl).set("filetype", i);
        } catch (Exception e) {
            return Ret.fail("msg", e.getMessage( ));
        } finally {
            uf.getFile( ).delete( );
        }
    }


    /**
     * @return
     * @Author Cc
     * @Description //TODO type == 1管理员上传文档
     * @Date 2020/3/25
     * @Param
     **/
    public Ret saveDoc(Doc doc, String avatarUrl, int usersId, int type) {
        if (type == 0) {
            doc.setStatus(0);
            doc.setLooking(0);
            doc.setLoveing(0);
            doc.setUping(0);
            doc.setTops(0);
            doc.setSort(0);
        } else {
            if (doc.getStatus( ) == null) {
                doc.setStatus(0);
            }

        }
        doc.setDocurl(avatarUrl);
        doc.setUsersid(usersId);
        doc.setAddtime(new Date( ));
        boolean save = doc.save( );
        if (save) {
            return Ret.ok("msg", "上传成功,待审核");
        } else {
            return Ret.ok("msg", "上传失败");
        }
    }

    public Ret updateDoc(Doc doc, String fileUrl, int usersId) {
        if (!StrKit.isBlank(fileUrl)) {
            doc.setDocurl(fileUrl);
        }
        if (usersId != 0) {
            doc.setStatus(0);
            doc.setLooking(0);
            doc.setLoveing(0);
            doc.setUping(0);
            doc.setTops(0);
            doc.setSort(0);
        }
        doc.setAddtime(new Date( ));
        boolean update = doc.update( );
        if (update) {
            return Ret.ok("msg", "修改成功,待审核");
        } else {
            return Ret.ok("msg", "修改失败");
        }
    }

    /**
     * @return int
     * @Author Cc
     * @Description //TODO 判断文件类型并返回对应的值
     * @Date 2020/3/18
     * @Param []
     **/
    public int typeSuffix(String suffixName) {
        switch (suffixName) {
            case "pdf":
                return 1;
            case "doc":
                return 2;
            case "docx":
                return 2;
            case "xlsx":
                return 3;
            case "xls":
                return 3;
            case "pptx":
                return 4;
            case "ppt":
                return 4;
            case "txt":
                return 5;
            default:
                throw new IllegalStateException("Unexpected value: " + suffixName);
        }
    }


    public Page< Doc > getDocList(int usersId, int status, String text, int pageNum) {
        String parm = "";
        if (!StrKit.isBlank(text)) {
            parm = "%" + text + "%";
        } else {
            parm = "%%";
        }
        Page< Doc > docList = docDao.paginate(pageNum, Cons.FRONT_PAGE_SIZE, "select * ", "from doc where usersid = ? and status = ? and docname like ? order by tops desc, addtime desc", usersId, status, parm);
        return docList;
    }

    public Doc getDocById(int id) {
        return docDao.findById(id);
    }

    public Long countDocById(int usersId) {
        return Db.queryLong("select count(*) from doc where usersid = ? and status = 1", usersId);
    }

    public Long countDoc( ) {
        return Db.queryLong("select count(*) from doc where status = 1");
    }

    public Ret deleteById(int id) {
        boolean b = docDao.deleteById(id);
        if (b) {
            return Ret.ok("msg", "删除成功");
        } else {
            return Ret.fail("msg", "删除失败");
        }
    }

    /**
     * @return java.util.List<com.jfinal.plugin.activerecord.Record>
     * @Author Cc
     * @Description //TODO 查看所有分类及文档数量
     * @Date 2020/3/23
     * @Param []
     **/
    public List< Record > docTypeList( ) {
        return Db.find("SELECT d.*,COUNT(c.id) AS num FROM doctype AS d LEFT JOIN doc AS c ON d.id=c.doctype and c.status = 1 GROUP BY d.id ORDER BY d.id");
    }

    /**
     * @return java.util.List<com.jfinal.club.common.model.Doctype>
     * @Author Cc
     * @Description //TODO 查看所有分类
     * @Date 2020/3/23
     * @Param []
     **/
    public List< Doctype > doctypeList( ) {
        return doctype.find("select * from doctype");
    }

    public Doctype docTypeById(int id) {
        return doctype.findById(id);
    }

    public List< Doc > docListByLooking( ) {
        return docDao.find("select * from doc where status = 1 order by addtime desc limit 6");
    }

    public Page< Doc > getDocListAll(String text, int docType, int pageNum) {
        String parm = "";
        if (!StrKit.isBlank(text)) {
            parm = "%" + text + "%";
        } else {
            parm = "%%";
        }
        Page< Doc > docList = null;
        if (docType != 0) {
            docList = docDao.paginate(pageNum, 10, "select * ", "from doc where status = 1 and filetype = ? and docname like ? order by tops desc,addtime desc", docType, parm);
        } else {
            docList = docDao.paginate(pageNum, 10, "select * ", "from doc where status = 1 and docname like ? order by tops desc,addtime desc", parm);
        }
        return docList;
    }


    public Page< Doc > getDocListTop(int top, int docType, int pageNum) {
        Page< Doc > docList = null;
        if (docType != 0) {
            if (top != 3) {
                docList = docDao.paginate(pageNum, 10, "select d.*,u.nickname", "from doc d ,users u where u.id = d.usersid and d.status = 1 and d.doctype = ? and d.tops = ? order by d.tops desc,d.addtime desc", docType, top);
            } else {
                docList = docDao.paginate(pageNum, 10, "select d.*,u.nickname", "from doc d ,users u where u.id = d.usersid and d.status = 1 and d.doctype = ? order by d.tops desc,d.addtime desc", docType);
            }
        }
        return docList;
    }


    /**
     * @return com.jfinal.plugin.activerecord.Page<com.jfinal.club.common.model.Doc>
     * @Author Cc
     * @Description //TODO 文档 猜你喜欢
     * @Date 2020/3/19
     * @Param []
     **/
    public Page< Doc > getDocByUsersLike(int usersid, int pageNum) {
        return docDao.paginate(pageNum, 6, "select d.*", "from doc d  where d.status = 1 and covertStatus = 1 and d.tops = 1 order by d.tops desc,d.addtime desc");
    }


    public Page< Doc > getDocByUping(int pageNum, int top, int size) {
        return docDao.paginate(pageNum, size, "select *", "from doc where status = 1 and covertStatus = 1 and tops = ? order by uping desc,addtime desc", top);
    }

    /**
     * @return com.jfinal.plugin.activerecord.Page<com.jfinal.club.common.model.Doc>
     * @Author Cc
     * @Description //TODO 首页推荐文档
     * @Date 2020/3/24
     * @Param [pageNum, size]
     **/
    public Page< Doc > getDocBySort(int pageNum, int size) {
        return docDao.paginate(pageNum, size, "select *", "from doc where status = 1 and covertStatus =1 order by sort desc , addtime desc");
    }

    /**
     * 每个类别取10条记录
     *
     * @return
     */
    public List< Doc > docTypeListByType( ) {
        return docDao.find("select * from doc a WHERE (select count(id) from doc b WHERE b.doctype=a.doctype and b.id>a.id) <11 ORDER BY a.addtime");
    }

    /**
     * 根据doc id,获取用户
     *
     * @param id
     * @return
     */
    public Users getUserByDocId(Integer id) {
        return new Users( ).findFirst("SELECT u.* from users  u inner JOIN doc d ON u.id = d.usersid WHERE d.id = ?", id);
    }

    /**
     * @param type
     * @param id
     */
    public void updateCount(int type, Integer id) {
        String sql = "UPDATE doc SET %s =  %s+1 WHERE id = ?";
        if (type == 1) {
            sql = String.format(sql, "looking", "looking");
        } else if (type == 2) {
            sql = String.format(sql, "loveing", "loveing");
        } else if (type == 3) {
            sql = String.format(sql, "uping", "uping");
        } else {
            return;
        }
        Db.update(sql, id);
    }

    /**
     * 微信扫码支付
     * 生成二维码信息
     *
     * @param out_trade_no 订单号
     * @param doc          文档对象
     * @param req          请求
     * @return
     */
    public Ret qrcode(long out_trade_no, Doc doc, HttpServletRequest req) {
        try {

            //支付金额 单位：分
            int money = (int) (doc.getDocmoney( ) * 100);

            Map< String, String > maps = new HashMap<>( );
            //公众账号ID
            maps.put("appid", PropKit.get("appid"));
            //商户号
            maps.put("mch_id", PropKit.get("mchid"));
            //随机字符串
            maps.put("nonce_str", WXPayUtil.generateNonceStr( ));
            //商品描述
            String body = doc.getDocname( ) == null ? "铁嘴网文档下载" : doc.getDocname( );
            maps.put("body", body);
            maps.put("out_trade_no", out_trade_no + "");
            //设置支付金额
            maps.put("total_fee", money + "");
            maps.put("spbill_create_ip", IpKit.getRealIp(req));
            maps.put("notify_url", PropKit.get("notify"));
            maps.put("trade_type", "NATIVE");


            //使用微信支付工具类对象，生成一个具有签名 sign 的xml格式参数(String类型)
            String xmlparam = WXPayUtil.generateSignedXml(maps, PropKit.get("mchkey"));
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //设置请求方式
            httpClient.setHttps(true);
            httpClient.setXmlParam(xmlparam);
            httpClient.post( );
            //获取查询结果
            String xmlMap = httpClient.getContent( );
            //把返回结果xml转换成map对象
            Map< String, String > resultMap = WXPayUtil.xmlToMap(xmlMap);

            return Ret.ok("code_url", resultMap.get("code_url"));
        } catch (Exception e) {
            e.printStackTrace( );
        }
        return Ret.fail("msg", "二维码生成失败!");
    }

    /**
     * 判读是否是自己上传的文件 是的话可以直接下载
     *
     * @param userId 用户id
     * @param docId  文档id
     * @return
     */
    public Doc getByIdUserId(int userId, Integer docId) {

        try {
            return new Doc( ).dao( ).findFirst("select * from doc where id = ? and usersid = ? ", docId, userId);
        } catch (Exception e) {
            e.printStackTrace( );
        }
        return null;
    }


    /**
     * lc
     * searchList
     * 页面大查询
     *
     * @param pageNum
     * @param pageSize
     * @param types
     * @param searchName
     * @return
     */
    public Page searchAll(int pageNum, int pageSize, Integer types, String searchName, int rad) {
        String radStr;
        if (rad == 0) {
            radStr = "";
        } else {
            radStr = " and filetype = " + rad;
        }
        try {
            if (types != 0 && StringUtils.isNotBlank(searchName)) {
                searchName = "%" + searchName.trim( ) + "%";
                return Db.paginate(pageNum, pageSize, "select *", "from (\n" +
                        "(select wd.id id,wd.docname name,wd.docname des,wd.addtime,@a types from doc wd,(select @a:=1) a where wd.status = 1 and wd.covertStatus = 1 " + radStr + " order by wd.looking desc,wd.addtime desc)\n" +
                        "union all\n" +
                        "(select bk.id id,bk.ctname name,bk.cttext des,bk.addtime,@b types from userct bk,(select @b:=2) a where bk.status = 1 order by bk.tops desc,bk.loveing desc,bk.addtime desc)\n" +
                        "union all\n" +
                        "(select wd.id id,wd.quesname name,wd.questext des,wd.addtime,@c types from questions wd,(select @c:= 3) a where wd.status = 1 order by wd.tops desc,wd.sort desc,wd.addtime desc)\n" +
/*                        "union all\n" +
                        "(select ws.id id,ws.wsRequest name,ws.wsReason des,ws.createAt addtime,@d types from wsinfo ws,(select @d:= 4) a where ws.status = 1 order by ws.createAt desc)\n" +*/
                        ") temp where types = ? and name like ?  order by temp.addtime desc", types, searchName);
            } else if (types != 0) {
                return Db.paginate(pageNum, pageSize, "select *", "from (\n" +
                        "(select wd.id id,wd.docname name,wd.docname des,wd.addtime,@a types from doc wd,(select @a:=1) a where wd.status = 1 and wd.covertStatus = 1 " + radStr + " order by wd.looking desc,wd.addtime desc)\n" +
                        "union all\n" +
                        "(select bk.id id,bk.ctname name,bk.cttext des,bk.addtime,@b types from userct bk,(select @b:=2) a where bk.status = 1 order by bk.tops desc,bk.loveing desc,bk.addtime desc)\n" +
                        "union all\n" +
                        "(select wd.id id,wd.quesname name,wd.questext des,wd.addtime,@c types from questions wd,(select @c:= 3) a where wd.status = 1 order by wd.tops desc,wd.sort desc,wd.addtime desc)\n" +
                        /*"union all\n" +
                        "(select ws.id id,ws.wsRequest name,ws.wsReason des,ws.createAt addtime,@d types from wsinfo ws,(select @d:= 4) a where ws.status = 1 order by ws.createAt desc)\n" +*/
                        ") temp where types = ?  order by temp.addtime desc", types);

            } else if (StringUtils.isNotBlank(searchName)) {
                searchName = "%" + searchName.trim( ) + "%";
                return Db.paginate(pageNum, pageSize, "select *", "from (\n" +
                        "(select wd.id id,wd.docname name,wd.docname des,wd.addtime,@a types from doc wd,(select @a:=1) a where wd.status = 1 and wd.covertStatus = 1 " + radStr + " order by wd.looking desc,wd.addtime desc)\n" +
                        "union all\n" +
                        "(select bk.id id,bk.ctname name,bk.cttext des,bk.addtime,@b types from userct bk,(select @b:=2) a where bk.status = 1 order by bk.tops desc,bk.loveing desc,bk.addtime desc)\n" +
                        "union all\n" +
                        "(select wd.id id,wd.quesname name,wd.questext des,wd.addtime,@c types from questions wd,(select @c:= 3) a where wd.status = 1 order by wd.tops desc,wd.sort desc,wd.addtime desc)\n" +
                        /*"union all\n" +
                        "(select ws.id id,ws.wsRequest name,ws.wsReason des,ws.createAt addtime,@d types from wsinfo ws,(select @d:= 4) a where ws.status = 1 order by ws.createAt desc)\n" +*/
                        ") temp where name like ?  order by temp.addtime desc", searchName);

            } else {
                return Db.paginate(pageNum, pageSize, "select *", "from (\n" +
                        "(select wd.id id,wd.docname name,wd.docname des,wd.addtime,@a types from doc wd,(select @a:=1) a where wd.status = 1 and wd.covertStatus = 1 " + radStr + " order by wd.looking desc,wd.addtime desc)\n" +
                        "union all\n" +
                        "(select bk.id id,bk.ctname name,bk.cttext des,bk.addtime,@b types from userct bk,(select @b:=2) a where bk.status = 1 order by bk.tops desc,bk.loveing desc,bk.addtime desc)\n" +
                        "union all\n" +
                        "(select wd.id id,wd.quesname name,wd.questext des,wd.addtime,@c types from questions wd,(select @c:= 3) a where wd.status = 1 order by wd.tops desc,wd.sort desc,wd.addtime desc)\n" +
                        /*"union all\n" +
                        "(select ws.id id,ws.wsRequest name,ws.wsReason des,ws.createAt addtime,@d types from wsinfo ws,(select @d:= 4) a where ws.status = 1 order by ws.createAt desc)\n" +*/
                        ") temp  order by temp.addtime desc");
            }


        } catch (Exception e) {
            e.printStackTrace( );
        }
        return null;
    }

    /**
     * 查询普通文档
     *
     * @param pageNum
     * @param pageSize
     * @param docTypeId
     * @return
     */
    public Page< Doc > getAllCommonDoc(Integer pageNum, int pageSize, int docTypeId) {

        try {
            return docDao.paginate(pageNum, pageSize, " select ifnull(u.nickname,'admin') nickname,d.* ", "from doc d left join users u  on d.usersid = u.id  where d.doctype = ? and   d.covertStatus = 1 and d.status = 1", docTypeId);
        } catch (Exception e) {
            e.printStackTrace( );
        }
        return null;
    }

    /**
     * 查询精品文档
     *
     * @param pageNum
     * @param pageSize
     * @param docTypeId
     * @return
     */
    public Page< Doc > getAllJingPinDoc(Integer pageNum, int pageSize, int docTypeId) {

        try {
            return docDao.paginate(pageNum, pageSize, " select ifnull(u.nickname,'admin') nickname,d.* ", "from doc d left join users u  on d.usersid = u.id  where d.jptype = ? and   d.covertStatus = 1 and d.status = 1", docTypeId);
        } catch (Exception e) {
            e.printStackTrace( );
        }
        return null;
    }

    /**
     * 普通文档 类型数量
     *
     * @param
     * @return
     */
    public List< Record > getCountCommonDoc( ) {
        return Db.find("select a.id,a.typename,ifnull(b.tot,0) total from (select * from doctype a where type = 1) a left join (select doctype,count(*) tot from doc where  status = 1 and covertStatus = 1 group by doctype) b on a.id = b.doctype");
    }

    /**
     * 精品文档 类型数量
     *
     * @param
     * @return
     */
    public List< Record > getCountJingPinDoc( ) {
        return Db.find("select a.id,a.typename,ifnull(b.tot,0) total from (select * from doctype a where type = 2) a left join (select jptype,count(*) tot from doc where  status = 1 and covertStatus = 1 group by jptype) b on a.id = b.jptype");
    }
}
