package com.dgtis.dorm.manager.admin.web;

import cn.binarywang.wx.miniapp.config.WxMaConfig;
import com.google.gson.Gson;
import net.sf.json.JSONObject;
import com.dgtis.dorm.manager.admin.annotation.LoginAdmin;
import com.dgtis.dorm.manager.db.domain.AdministrativeItems;
import com.dgtis.dorm.manager.db.domain.Storage;
import com.dgtis.dorm.manager.db.param.ItemsQueryParam;
import com.dgtis.dorm.manager.db.service.AdministrativeItemsService;
import com.dgtis.dorm.manager.db.service.FileSystemStorageService;
import com.dgtis.dorm.manager.db.util.ResponseUtil;
import com.dgtis.dorm.manager.db.util.TreeNode;
import com.dgtis.dorm.manager.db.util.wx.QrCodeUtil;
import org.apache.catalina.Store;
import org.apache.commons.collections.CollectionUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 行政办理事项
 *
 * @author huanghaoqi
 * @version 1.0
 * @date 2018年12月03日 14:52:44
 * @since JDK1.8
 */
@RestController
@RequestMapping("/admin/items")
public class AdministrativeItemsController {
    @Resource
    private AdministrativeItemsService administrativeItemsService;
    @Resource
    private WxMaConfig wxMaConfig;
    @Resource
    private FileSystemStorageService fileSystemStorageService;
    /**
     * 方法描述  查询列表
     *
     * @param queryParam 查询参数
     * @return Object
     * @author huanghaoqi
     * @date 2018年12月03日 15:42:29
     */
    @PostMapping("/list")
    public Object list(@LoginAdmin Integer adminId,
                       @RequestBody ItemsQueryParam queryParam
    ) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        Map<String, Object> data = new HashMap<>();
        // 查询总数
        Long total = administrativeItemsService.count(queryParam);
        if (total == null || total == 0) {
            data.put("total", 0);
            data.put("items", new ArrayList<>(0));
            return ResponseUtil.ok(data);
        }
        // 查询列表
        List<AdministrativeItems> administrativeItemsList = administrativeItemsService.list(queryParam);
        data.put("total", total);
        data.put("items", administrativeItemsList);

        return ResponseUtil.ok(data);
    }

    /**
     * 方法描述  添加
     *
     * @param administrativeItems 添加对象
     * @return Object
     * @author huanghaoqi
     * @date 2018年12月03日 15:42:57
     */
    @PostMapping("/create")
    public Object create(@LoginAdmin Integer adminId, @RequestBody AdministrativeItems administrativeItems) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        administrativeItems.setCreateDate(new Date());
        administrativeItems.setCreateUser(adminId);
        administrativeItems.setDeflag(0);

        Integer id = administrativeItemsService.insert(administrativeItems);
        return ResponseUtil.ok(id);
    }

    /**
     * 方法描述  查询详情
     *
     * @param id id
     * @return Object
     * @author huanghaoqi
     * @date 2018年12月03日 15:43:20
     */
    @GetMapping("/detail")
    public Object detail(@LoginAdmin Integer adminId, Integer id) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        if (id == null) {
            return ResponseUtil.badArgument();
        }

        AdministrativeItems administrativeItems = administrativeItemsService.findById(id);
        return ResponseUtil.ok(administrativeItems);
    }

    /**
     * 方法描述  更新
     *
     * @param administrativeItems 更新对象
     * @return Object
     * @author huanghaoqi
     * @date 2018年12月03日 15:45:09
     */
    @PostMapping("/update")
    public Object update(@LoginAdmin Integer adminId, @RequestBody AdministrativeItems administrativeItems) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }

        administrativeItems.setUpdateDate(new Date());
        administrativeItems.setUpdateUser(adminId);
        Integer id = administrativeItemsService.update(administrativeItems);

        return ResponseUtil.ok(id);
    }

    /**
     * 方法描述  批量删除
     *
     * @param ids id集合
     * @return Object
     * @author huanghaoqi
     * @date 2018年12月03日 15:50:46
     */
    @PostMapping("/delete")
    public Object delete(@LoginAdmin Integer adminId, Integer[] ids) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }
        administrativeItemsService.batchDelete(Arrays.asList(ids));
        return ResponseUtil.ok(ids);
    }

    /**
     * 方法描述  获取所属事项父级结构
     *
     * @return Object
     * @author huanghaoqi
     * @date 2018年12月03日 15:45:09
     */
    @PostMapping("/parentTree")
    public Object parentTree(@LoginAdmin Integer adminId) {
        if (adminId == null) {
            return ResponseUtil.unlogin();
        }

        List<TreeNode> result = administrativeItemsService.getParentTree();

        return ResponseUtil.ok(result);
    }


    /**
     * @description 描述：生成事项二维码方法
     * @author      koucx
     * @return      Object
     * @date        2019/5/10
     * @param       id
     */
    @GetMapping("/createItemQrCode")
    public Object createItemQrCode(@RequestParam("id") Integer id) {

        if(id!=null){
            AdministrativeItems administrativeItems = administrativeItemsService.findById(id);
            Integer parentId = administrativeItems.getParentId();
            String parentName = administrativeItems.getParentName();
            String responseFileName = administrativeItems.getName() + ".jpg";
            InputStreamResource resource = null;
            try {
                if (parentId == null) {
                    // 生成一级事项二维码
                    String scene = "parentId" + id;
                    resource = createQrCode(scene);
                } else {
                    responseFileName = parentName + "_" + responseFileName;
                    // 生成二级事项二维码
                    String scene = "parentId" + parentId + "childrenId" + id;
                    resource = createQrCode(scene);
                }

                responseFileName = new String(responseFileName.getBytes(), StandardCharsets.UTF_8);

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            try {
                resource = QrCodeUtil.changeImage(resource.getInputStream(), administrativeItems.getName());
                //生成二维码相关信息存储到数据库
                Storage storage = fileSystemStorageService.storeQrCode(resource.getInputStream(), responseFileName);
                AdministrativeItems updateItem = new AdministrativeItems();
                updateItem.setId(id);
                updateItem.setQrcodeStorageId(storage.getKey());
                //更新新生成的二维码key到事项表
                administrativeItemsService.update(updateItem);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            ResponseUtil.fail();
        }

        return ResponseUtil.ok();
    }

   /* *
    * @descption:
    * @param: [absolutePath]
    * @return: org.springframework.http.ResponseEntity<java.lang.Object>
    * @auther: koucx
    * @date: 2019/5/13 0013 11:42
    */
    @GetMapping("/downloadItemQrCode")
    public ResponseEntity<Object> downloadItemQrCode(String qrcodeStorageId) {
        Storage storage = new Storage();
        storage.setKey(qrcodeStorageId);
        //根据key查询响应Storage
        Storage dbStorage = fileSystemStorageService.selectByKey(storage);
        String filePath = FileSystemStorageService.rootLocation.toString()+dbStorage.getFilePath();
        FileSystemResource file = new FileSystemResource(filePath);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");

        // 设置下载时的文件名，中文文件名需要进行转码，否则是乱码
        try {
            headers.add("Content-Disposition",
                    "attachment; filename=" +
                            new String(file.getFilename().getBytes("UTF-8"), "iso-8859-1"));
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");


        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok().headers(headers)
                .contentType(MediaType.IMAGE_JPEG)
                .body(file);
    }


    /**
     * 方法描述 二维码下载
     *
     * @param id 事项ID
     * @author huanghaoqi
     * @date 2017年09月01日 13:02:22
     */
    @GetMapping("/downloadQrCode")
    public ResponseEntity<Object> downloadQrCode(@RequestParam("id") Integer id) {
        AdministrativeItems administrativeItems = administrativeItemsService.findById(id);

        Integer parentId = administrativeItems.getParentId();
        String parentName = administrativeItems.getParentName();
        String responseFileName = administrativeItems.getName() + ".jpg";
        InputStreamResource resource = null;
        try {
            if (parentId == null) {
                // 生成一级事项二维码
                String scene = "parentId" + id;
                resource = createQrCode(scene);
            } else {
                responseFileName = parentName + "_" + responseFileName;
                // 生成二级事项二维码
                String scene = "parentId" + parentId + "childrenId" + id;
                resource = createQrCode(scene);
            }
            responseFileName = new String(responseFileName.getBytes(), StandardCharsets.ISO_8859_1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            resource = QrCodeUtil.changeImage(resource.getInputStream(), administrativeItems.getName());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + responseFileName +
                "\"").contentType(MediaType.IMAGE_JPEG)
                .body(resource);
    }

    /**
     * 方法描述 二维码打包下载
     *
     * @param ids 事项ID
     * @author huanghaoqi
     * @date 2017年09月01日 13:02:22
     */
    @GetMapping("/downloadZipQrCode")
    public ResponseEntity<Object> downloadZipQrCode(@RequestParam("ids") Integer[] ids) {

        List<AdministrativeItems> administrativeItemsList = administrativeItemsService.selectByIds(Arrays.asList(ids));
        if (CollectionUtils.isNotEmpty(administrativeItemsList)) {

            final InputStream[] bis = {null};

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ZipOutputStream zipfile = new ZipOutputStream(bos);
            administrativeItemsList.forEach(administrativeItems -> {
                Integer id = administrativeItems.getId();
                Integer parentId = administrativeItems.getParentId();
                String parentName = administrativeItems.getParentName();
                String responseFileName = administrativeItems.getName() + ".jpg";
                InputStreamResource resource;
                try {
                    if (parentId == null) {
                        // 生成一级事项二维码
                        String scene = "parentId" + id;
                        resource = createQrCode(scene);
                    } else {
                        responseFileName = parentName + "_" + responseFileName;
                        // 生成二级事项二维码
                        String scene = "parentId" + parentId + "childrenId" + id;
                        resource = createQrCode(scene);
                    }
                    if (resource != null) {
                        resource = QrCodeUtil.changeImage(resource.getInputStream(), administrativeItems.getName());
                        ZipEntry zipEntry = new ZipEntry(responseFileName);
                        if (resource != null) {
                            zipfile.putNextEntry(zipEntry);
                            bis[0] = resource.getInputStream();
                            int read;
                            while ((read = bis[0].read()) != -1) {
                                zipfile.write(read);
                            }
                        }
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            try {
                zipfile.close();
                bis[0].close();
                bos.close();
            } catch (IOException e) {
                throw new RuntimeException("Failed to store file ", e);
            }
            InputStream is = new ByteArrayInputStream(bos.toByteArray());
            String responseFileName = "二维码.zip";
            responseFileName = new String(responseFileName.getBytes(), StandardCharsets.ISO_8859_1);
            return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + responseFileName +
                    "\"").contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(new InputStreamResource(is));
        }

        return null;
    }


    /**
     * 方法描述  创建二维码
     *
     * @author huanghaoqi
     * @date 2018年12月06日 11:38:18
     */
    private InputStreamResource createQrCode(String scene) throws UnsupportedEncodingException {
        String page = "pages/handle/details/index";
        String token = getToken();   // 得到token

        Map<String, Object> params = new HashMap<>();
        params.put("scene", scene);  //参数
        params.put("page", page); //位置
        params.put("width", 400);

        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + token + "&scene=" + scene);  // 接口
        httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");

        String body = new Gson().toJson(params);           //必须是json模式的 post
        StringEntity entity = new StringEntity(body);
        entity.setContentType("image/png");
        httpPost.setEntity(entity);
        HttpResponse response;
        try {
            response = httpClient.execute(httpPost);
            InputStream inputStream = response.getEntity().getContent();
            return new InputStreamResource(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 方法描述  获取access_token
     *
     * @author huanghaoqi
     * @date 2018年12月06日 11:34:48
     */
    private String getToken() {
        // 小程序唯一标识 (在微信小程序管理后台获取)
        String wxspAppid = wxMaConfig.getAppid();
        // 小程序的 app secret (在微信小程序管理后台获取)
        String wxspSecret = wxMaConfig.getSecret();
        //这里直接写死就可以，不用改，用法可以去看api
        String grant_type = "client_credential";
        //封装请求数据
        String params = "grant_type=" + grant_type + "&secret=" + wxspSecret + "&appid=" + wxspAppid;
        //发送GET请求
        CloseableHttpClient httpCilent = HttpClients.createDefault();//Creates CloseableHttpClient instance with default configuration.
        HttpGet httpGet = new HttpGet("https://api.weixin.qq.com/cgi-bin/token?" + params);
        try {
            HttpResponse httpResponse = httpCilent.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                String srtResult = EntityUtils.toString(httpResponse.getEntity());//获得返回的结果
                //解析相应内容（转换成json对象）
                JSONObject json = JSONObject.fromObject(srtResult);
                //拿到accesstoken
                return (String) json.get("access_token");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpCilent.close();//释放资源
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
