package shop.alien.util.webdav;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.MultiStatusResponse;
import org.apache.jackrabbit.webdav.client.methods.HttpMkcol;
import org.apache.jackrabbit.webdav.client.methods.HttpPropfind;
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.apache.jackrabbit.webdav.version.DeltaVConstants;

import java.io.*;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;


/**
 * WebDav工具类
 *
 * @author ssk
 * @version 1.0
 * @date 2023/5/30 23:35
 */
@Slf4j
public class WebDavJackRabbitUtil {

    /**
     * 用户名
     */
    public static String username;

    /**
     * 密码
     */
    public static String password;

    /**
     * 链接转URI
     */
    public static URI uri;

    public static HttpClient client;

    public static HttpClientContext context;

    public static void main(String[] args) throws IOException {
        String url = "http://xiaokuihua.fun:5005/Cache/";
        String userName = "ssk";
        String password = "!@#ZyL021405";
//        WebDavJackRabbitUtil util = new WebDavJackRabbitUtil(url, userName, password);
        WebDavJackRabbitUtil util = new WebDavJackRabbitUtil();
        util.init(url, userName, password);
        util.mkdir("http://xiaokuihua.fun:5005/Cache/douyin/user/三十个元元2/");
        //System.out.println(util.upload("http://xiaokuihua.fun:5005/Cache/学长心很愁", "D:\\douyin\\每天跟我涨知识dou是知识点奇妙知识在抖音脑洞大开关注我每天坚持分享知识20230531145652862.mp4"));
//        System.out.println(util.download(url + "/ddns.txt", "ddns.txt", "D:\\"));
//        System.out.println(util.mkdir("http://xiaokuihua.fun:5005/Cache/学长心很愁"));
//        System.out.println(util.delete("http://xiaokuihua.fun:5005/Cache/20230531"));
//        MultiStatusResponse[] propfind = util.propfind(url);
//        for (int i = 1; i < propfind.length - 1; i++) {
//            String href = propfind[i].getHref();
//            String path = URLDecoder.decode(href, "UTF-8");
//            util.download("http://158.221.136.226:8080/" + href, path);
//        }
    }

    /**
     * 初始化
     *
     * @param baseUri  链接
     * @param userName 用户名
     * @param passWord 密码
     */
    public static void init(String baseUri, String userName, String passWord) {
        uri = URI.create(baseUri);
        username = userName;
        password = passWord;
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort());
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, password);
        credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), upc);
        AuthCache authCache = new BasicAuthCache();
        // Generate BASIC scheme object and add it to the local auth cache
        BasicScheme basicAuth = new BasicScheme();
        authCache.put(targetHost, basicAuth);
        // Add AuthCache to the execution context
        context = HttpClientContext.create();
        context.setCredentialsProvider(credsProvider);
        context.setAuthCache(authCache);
        client = HttpClients.custom().setConnectionManager(cm).build();
    }

//    public WebDavJackRabbitUtil(String baseUri, String userName, String passWord) {
//        this.uri = URI.create(baseUri);
//        this.username = userName;
//        this.password = passWord;
//        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
//        HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort());
//        CredentialsProvider credsProvider = new BasicCredentialsProvider();
//        UsernamePasswordCredentials upc = new UsernamePasswordCredentials(this.username, this.password);
//        credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), upc);
//        AuthCache authCache = new BasicAuthCache();
//        // Generate BASIC scheme object and add it to the local auth cache
//        BasicScheme basicAuth = new BasicScheme();
//        authCache.put(targetHost, basicAuth);
//        // Add AuthCache to the execution context
//        this.context = HttpClientContext.create();
//        this.context.setCredentialsProvider(credsProvider);
//        this.context.setAuthCache(authCache);
//        this.client = HttpClients.custom().setConnectionManager(cm).build();
//    }

    /**
     * 上传
     *
     * @param uri      路径+文件名
     * @param filePath 文件路径
     * @return boolean
     */
    public boolean upload(String uri, String filePath) {
        try {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            HttpPut put = new HttpPut(uri);
            InputStreamEntity requestEntity = new InputStreamEntity(fis);
            put.setEntity(requestEntity);
            //HTTP状态201指示作为HTTP POST请求的结果，已在服务器上成功创建了一个或多个新资源。
            int status = client.execute(put, context).getStatusLine().getStatusCode();
            return status == 201;
        } catch (Exception e) {
            log.error("upload ERROR: " + e.getMessage());
            return false;
        }
    }

    /**
     * 下载
     *
     * @param uri          路径
     * @param fileName     文件名
     * @param downloadPath 下载路径
     * @return boolean
     */
    public boolean download(String uri, String fileName, String downloadPath) {
        try {
            HttpGet get = new HttpGet(uri);
            HttpResponse execRel = client.execute(get, context);
            StatusLine status = execRel.getStatusLine();
            HttpEntity resp = execRel.getEntity();
            return transStream2File(resp.getContent(), downloadPath + fileName);
        } catch (Exception e) {
            log.error("WEBDAV download ERROR: " + e.getMessage());
            return false;
        }
    }

    /**
     * 删除
     *
     * @param uri 路径
     * @return boolean
     */
    public boolean delete(String uri) {
        try {
            HttpDelete delete = new HttpDelete(uri);
            int status = client.execute(delete, context).getStatusLine().getStatusCode();
            return status == 201;
        } catch (Exception e) {
            log.error("delete ERROR: " + e.getMessage());
            return false;
        }
    }

    /**
     * 新建文件夹
     *
     * @param uri 路径+新文件夹名
     * @return boolean
     */
    public static boolean mkdir(String uri) {
        try {
            HttpMkcol mkcol = new HttpMkcol(uri);
            int status = client.execute(mkcol, context).getStatusLine().getStatusCode();
            return status == 201;
        } catch (Exception e) {
//            log.error("WebDavJackRabbitUtil: mkdir ERROR: MSG={}&Stack={}", e.getMessage(), e.getStackTrace());
            throw new RuntimeException(e);
//            return false;
        }
    }

    public MultiStatusResponse[] propfind(String testuri) throws IOException {
        MultiStatusResponse[] responses = null;
        try {
            DavPropertyNameSet names = new DavPropertyNameSet();
            names.add(DeltaVConstants.COMMENT);
            // DavConstants.DEPTH_1
            HttpPropfind propfind = new HttpPropfind(testuri, DavConstants.PROPFIND_ALL_PROP_INCLUDE, names, DavConstants.DEPTH_1);
            HttpResponse resp = client.execute(propfind, context);
            int status = resp.getStatusLine().getStatusCode();
            log.info("List file " + uri + " status is :" + status);
            // assertEquals(207, status);
            MultiStatus multistatus;
            multistatus = propfind.getResponseBodyAsMultiStatus(resp);
            responses = multistatus.getResponses();
        } catch (DavException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return responses;
    }

    /**
     * 输入流转文件
     *
     * @param is       输入流
     * @param fileName 文件名
     */
    public boolean transStream2File(InputStream is, String fileName) {
        try {
            BufferedInputStream in = new BufferedInputStream(is);
            BufferedOutputStream out = new BufferedOutputStream(Files.newOutputStream(Paths.get(fileName)));
            int len;
            byte[] b = new byte[1024];
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            in.close();
            out.close();
            return true;
        } catch (Exception e) {
            log.error("transStream2File ERROR: " + e.getMessage());
            return false;
        }
    }

}
