package com.bofeng.excel;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.Sheet;
import com.google.common.base.Strings;
import com.yvan.PageDb;
import com.yvan.platform.Conv;
import com.yvan.platform.JsonWapper;
import com.yvan.springmvc.HttpParameterParser;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.codec.binary.Base64;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

@Slf4j
public class ExcelUtils {

    @SneakyThrows
    public static void exportTemplate(String path, JsonWapper data, HttpServletResponse resp) {
        TemplateExportParams params = new TemplateExportParams(path);

        Workbook workbook = ExcelExportUtil.exportExcel(params, (Map<String, Object>) data.getInnerMap());
        try (OutputStream fos = resp.getOutputStream()) {
            workbook.write(fos);
        }
    }

    public static <T> ExcelBuilder writeSheet(Class<T> clazz, List<T> data, String sheetName) {
        return new ExcelBuilder().writeSheet(clazz, data, sheetName);
    }

    public static <T> ExcelBuilder writeSheet(Class<T> clazz, List<T> data) {
        return new ExcelBuilder().writeSheet(clazz, data);
    }

    public static boolean isRequireTemplate(HttpServletRequest req) {
        return "template".equals(req.getParameter("action"));
    }

    @SneakyThrows
    public static <T> ExcelDataReader<T> getReader(Class<T> clazz, HttpServletRequest req, int limitRows) {
        ExcelDataReader<T> reader = new ExcelDataReader<>(clazz, limitRows);

        StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest) req;
        MultipartFile excel = request.getFile("file");
        reader.FILE_NAME = excel.getOriginalFilename();

        try (InputStream is = excel.getInputStream();
             BufferedInputStream bis = new BufferedInputStream(is)) {

            try {
                EasyExcelFactory.readBySax(bis, new Sheet(1, reader.getHead().getRowNum()), reader);
            } catch (Exception e) {
                log.error("导入无效文件", e);
                reader.error("无效文件");
            }
        }

        req.setAttribute(ExcelDataReader.ATTRIB_NAME, reader);
        return reader;
    }

    @SneakyThrows
    public static <T> void writeSuccess(ExcelDataReader<T> reader,
                                        HttpServletRequest req,
                                        HttpServletResponse resp) {
        JsonWapper jw = new JsonWapper();
        jw.set("success", true);
        jw.set("data", reader.getBizData());
        jw.set("msg", "成功导入" + reader.getSuccessRows() + "行.");

        writeToResponse(resp, "application/json;charset=utf-8", jw.toString());
        req.removeAttribute(ExcelDataReader.ATTRIB_NAME);
    }

    @SneakyThrows
    public static boolean writeError(HttpServletRequest request, HttpServletResponse resp) {
        ExcelDataReader reader = (ExcelDataReader<?>) request.getAttribute(ExcelDataReader.ATTRIB_NAME);
        if (reader != null) {

            val data = reader.buildErrorRows();
            if (data.size() > 0 || reader.getGlobalError().size() > 0) {
                JsonWapper jw = new JsonWapper();
                jw.set("success", false);
                jw.set("data", data);
                jw.set("error", reader.getGlobalError());
                if (reader.getGlobalError().size() > 0) {
                    //全局错误
                    StringBuilder sb = new StringBuilder();
                    for (val s : reader.getGlobalError()) {
                        sb.append(s.toString() + '.');
                    }
                    jw.set("msg", sb.toString() + "本次导入无效");

                } else if (data.size() > 0) {
                    jw.set("msg", "存在" + reader.getErrorCount() + "个错误，本次导入无效(数据不会发生变化)，请核对后重新导入");

                } else {
                    jw.set("msg", "本次导入无效(数据不会发生变化)，请核对后重新导入");
                }

                writeToResponse(resp, "application/json;charset=utf-8", jw.toString());
                return true;
            }
        }
        return false;
    }


    public static final String TOKEN_KEY = "TOKEN";
    public static final Charset UTF8 = Charset.forName("UTF-8");

    public static HttpServletRequest currentRequest() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                    .getRequest();
        } catch (Exception e) {
            return null;
        }
    }

    public static HttpServletResponse currentResponse() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                    .getResponse();
        } catch (Exception e) {
            return null;
        }
    }

    public static String currentRemoteIp() {
        HttpServletRequest request = currentRequest();
        if (request == null) {
            return "";
        }

        if (request.getHeader("x-forwarded-for") != null) {
            return request.getHeader("x-forwarded-for");
        }
        return request.getRemoteAddr();
    }

    public static String currentHost() {
        HttpServletRequest request = currentRequest();
        if (request == null) {
            return "";
        }

        String host = request.getHeader("X-Forwarded-Host");
        if (!Strings.isNullOrEmpty(host)) {
            return host;
        }
        return request.getHeader("Host");
    }

    public static String currentUrl() {
        HttpServletRequest request = currentRequest();
        if (request == null) {
            return "";
        }

        return request.getScheme() + "://" + currentHost() + request.getRequestURI();
    }

    public static boolean isEqualPath(String s1, String s2) {
        if (Strings.isNullOrEmpty(s1) || Strings.isNullOrEmpty(s2)) {
            return false;
        }

        int p1 = s1.indexOf("?");
        if (p1 >= 0) {
            s1 = s1.substring(0, p1);
        }
        int p2 = s2.indexOf("?");
        if (p2 >= 0) {
            s2 = s2.substring(0, p1);
        }
        return s1.toLowerCase().equals(s2.toLowerCase());
    }

    public static String currentToken() {
        HttpServletRequest request = currentRequest();
        if (request == null) {
            return "";
        }

        String token;
        // 从head取
        token = request.getHeader(TOKEN_KEY);
        if (!Strings.isNullOrEmpty(token)) {
            return token;
        }

        // 从attribute取
        token = request.getAttribute(TOKEN_KEY).toString();
        if (!Strings.isNullOrEmpty(token)) {
            return token;
        }

        // 从cookie取
        token = getCookieValue(TOKEN_KEY);
        if (!Strings.isNullOrEmpty(token)) {
            return token;
        }

        return null;
    }

    public static void writeToken(String token) {
        Cookie cookie = new Cookie(TOKEN_KEY, token);
        cookie.setPath("/");
        writeCookie(cookie);
    }

    /**
     * 请求是否需要被拦截
     */
    public static boolean isFilterPass(HttpServletRequest httpRequest) {
        String thisUrl = httpRequest.getRequestURI();
        return (thisUrl.startsWith("/static/") ||
                thisUrl.startsWith("/manage/") ||
                thisUrl.startsWith("/druid/") ||
                thisUrl.startsWith("/igh2/") ||
                thisUrl.endsWith(".css") || thisUrl.endsWith(".jpg") || thisUrl.endsWith(".jpeg") ||
                thisUrl.endsWith(".html") || thisUrl.endsWith(".js") || thisUrl.endsWith(".png") ||
                thisUrl.endsWith(".gif") || thisUrl.endsWith(".map"));
    }

    /**
     * 从当前请求中获取分页方法和内容
     */
    public static PageDb parsePagination() {
        HttpServletRequest request = currentRequest();
        HttpParameterParser parser = HttpParameterParser.newInstance(request);
        int page = parser.getIntValue("page", 1);
        int start = parser.getIntValue("start", 0);
        int limit = parser.getIntValue("limit", 10);

        return new PageDb(page, limit);
    }


    /**
     * 得到当前request请求的所有cookie
     */
    public static Cookie[] getCookies() {
        HttpServletRequest request = currentRequest();
        return request == null ? null : request.getCookies();
    }

    /**
     * 根据cookie名字取得cookie
     */
    public static Cookie getCookie(String name) {
        Cookie[] cookies = getCookies();
        if (cookies != null && cookies.length > 0) {
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                String cookName = cookie.getName();
                if (cookName != null && cookName.equals(name)) {
                    return cookie;
                }
            }
        }
        return null;
    }

    public static String getCookieValue(String name) {
        Cookie cookie = getCookie(name);
        if (cookie == null) {
            return null;
        }
        return cookie.getValue();
    }

    /**
     * 将cookie写入客户端
     */
    public static void writeCookie(Cookie cookie) {
        if (cookie == null) {
            return;
        }
        HttpServletResponse response = currentResponse();

        /*
         * if (request != null) { String host = request.getHeader("Host"); if (ConfigUtils.WEBSITE.equals(host))
         * cookie.setDomain("." + ConfigUtils.DOMAIN); }
         */
        if (response != null) {
            response.addCookie(cookie);
        }
    }

    public static void removeCookie(String cookieName, String path) {

        HttpServletResponse response = currentResponse();
        HttpServletRequest request = currentRequest();

        Cookie[] cookies = request.getCookies();
        if (cookies == null || cookies.length == 0) {
            return;
        }

        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if (cookie.getName().equals(cookieName)) {
                cookie.setMaxAge(0);
                cookie.setPath(path);
                response.addCookie(cookie);
                break;
            }
        }

    }

    public static String urlEncoding(String value) {
        try {
            byte[] bs = Base64.encodeBase64URLSafe(value.getBytes("UTF-8"));
            return new String(bs, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("encode error.", e);
        }
    }

    @SneakyThrows
    public static void writeToResponse(HttpServletResponse response, String contentType, String json) {
        response.setContentType(contentType);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Expires", "0");
        response.setHeader("Pragma", "No-cache");
        response.setContentLength(json.getBytes(UTF8).length);
        PrintWriter out = response.getWriter();
        if (out != null) {
            out.print(json);
            out.flush();
            out.close();
        }
    }
}
