package com.cooleshow.base.utils.helper.upload;

import android.app.Activity;
import android.text.TextUtils;

import com.cooleshow.base.bean.UploadTokenInfoBean;
import com.cooleshow.base.constanst.UploadConstants;
import com.cooleshow.base.data.api.UploadApi;
import com.cooleshow.base.data.net.BaseResponse;
import com.cooleshow.base.data.net.RetrofitFactory;
import com.cooleshow.base.utils.FileUtils;
import com.cooleshow.base.utils.LogUtils;
import com.cooleshow.base.utils.RequestBodyUtil;
import com.cooleshow.base.utils.TimeUtils;
import com.cooleshow.base.utils.Utils;
import com.cooleshow.base.widgets.ProgressLoading;
import com.cooleshow.base.widgets.UploadProgressLoading;
import com.ksyun.ks3.auth.AuthUtils;
import com.ksyun.ks3.exception.Ks3Error;
import com.ksyun.ks3.model.PostObjectFormFields;
import com.ksyun.ks3.model.acl.Authorization;
import com.ksyun.ks3.model.acl.CannedAccessControlList;
import com.ksyun.ks3.services.AuthListener;
import com.ksyun.ks3.services.Ks3Client;
import com.ksyun.ks3.services.Ks3ClientConfiguration;
import com.ksyun.ks3.services.handler.CreateBucketResponceHandler;
import com.ksyun.ks3.services.handler.Ks3HttpResponceHandler;
import com.ksyun.ks3.services.handler.PutObjectResponseHandler;
import com.ksyun.ks3.services.request.PutObjectRequest;
import com.ksyun.ks3.services.request.object.PostObjectRequest;
import com.ksyun.ks3.util.Constants;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.RequestBody;

/**
 * Author by pq, Date on 2022/5/11.
 */
public class UploadHelper {
    public String SRC_BUCKETNAME = UploadConstants.BUCKET_NAME_DAYA;
    public static final String END_POINT = "ks3-cn-beijing.ksyuncs.com";
    public static final String PROTOCOL = "https://";
    public static final String SRC_OBJECTKEY = "";
    public static final String DST_BUCKETNAME = "";
    public static final String ak = "AKLTtTeIbadpRG-pil4S0Q4m-Q";
    public static final String sk = "OB1HmNOfDNW95wHoxMkP6IPFZXormk2ngA800TkvKAw7ozhiJGRqrMnnV8ZrAU3WRQ==";
    private Ks3Client mClient;

    private String uploadToken = "";
    private Activity mActivity;
    private UploadProgressLoading mProgressLoading;

    public UploadHelper(Activity activity, int type) {
        this(activity, UploadConstants.getBucketNameByType(type));
    }

    public UploadHelper(Activity activity, String bukName) {
        this.mActivity = activity;
        //获取桶名称
        SRC_BUCKETNAME = bukName;
        if (TextUtils.isEmpty(bukName)) {
            SRC_BUCKETNAME = UploadConstants.BUCKET_NAME_DAYA;
        }
        LogUtils.i("UploadHelper", "SRC_BUCKETNAME:" + SRC_BUCKETNAME);
        initUploadProgressDialog();
        initClient();
    }

    private void initUploadProgressDialog() {
        if (mActivity != null) {
            if (mActivity.isFinishing() || mActivity.isDestroyed()) {
                return;
            }
            mProgressLoading = UploadProgressLoading.Companion.create(mActivity);
        }
    }

    private void initClient() {
        Ks3ClientConfiguration configuration = Ks3ClientConfiguration.getDefaultConfiguration();
        configuration.setSSLSocketFactory(SSLSocketFactory.getSocketFactory());
        configuration.setDomainMode(true);
        configuration.setPathStyleAccess(true);
        configuration.setProtocol(Ks3ClientConfiguration.PROTOCOL.https);
        mClient = new Ks3Client(new AuthListener() {
            @Override
            public String onCalculateAuth(final String httpMethod,
                                          final String ContentType, final String Date,
                                          final String ContentMD5, final String Resource,
                                          final String Headers) {
                String token = "";
                try {
                    token = AuthUtils.calcAuthToken(httpMethod, ContentType, Date, ContentMD5, Resource, Headers, ak, sk);
                    LogUtils.i("pq", "token:" + token);
                } catch (SignatureException e) {
                    e.printStackTrace();
                }
                return token;
            }
        }, configuration, Utils.getApp());
        mClient.setEndpoint(END_POINT);
    }

    public void uploadFile(File file) {
        if (!file.exists()) {
            return;
        }
        String name = FileUtils.getFileName(file);
        long timeStr = TimeUtils.getNowMills();
        if (name.contains(".")) {
            String[] split = name.split("\\.");
            name = timeStr + "." + split[split.length - 1];
        } else {
            name = "" + timeStr;
        }
        String lastName = timeStr + "_" + name;
        String month = TimeUtils.date2String(TimeUtils.getNowDate(), TimeUtils.getSafeDateFormat("yyyy-MM"));
        String key = "android/" + month + "/" + lastName;
        getUploadToken(name, key, file);
    }

    private void doUpload(String key, File file) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(SRC_BUCKETNAME, key, file);
        putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
        mClient.putObject(putObjectRequest, new PutObjectResponseHandler() {
            @Override
            public void onTaskFailure(int i, Ks3Error ks3Error, Header[] headers, String s, Throwable throwable) {
                if (throwable != null) {
                    throwable.printStackTrace();
                }
                hideUploadLoading();
                if (upLoadCallBack != null) {
                    upLoadCallBack.onFailure();
                }
                LogUtils.i("pq", "onFailure postObject is " + ks3Error.getErrorMessage());
            }

            @Override
            public void onTaskSuccess(int i, Header[] headers) {
                hideUploadLoading();
                if (null != upLoadCallBack) {
                    upLoadCallBack.onSuccess(buildUploadUrl(key));
                }
                LogUtils.i("pq", "onSuccess postObject is " + i);
            }

            @Override
            public void onTaskStart() {
                showUploadLoading();
                if (upLoadCallBack != null) {
                    upLoadCallBack.onUploadStart();
                }
            }

            @Override
            public void onTaskFinish() {
                hideUploadLoading();
                if (upLoadCallBack != null) {
                    upLoadCallBack.onUploadFinish();
                }
            }

            @Override
            public void onTaskCancel() {
                hideUploadLoading();
                if (upLoadCallBack != null) {
                    upLoadCallBack.onUploadCancel();
                }
            }

            @Override
            public void onTaskProgress(double v) {
                if (mProgressLoading != null) {
                    mProgressLoading.setProgress(v);
                }
                if (upLoadCallBack != null) {
                    upLoadCallBack.onUploadProgress(v);
                }
            }
        });
    }

    private void getUploadToken(String fileName, String key, File file) {
        JSONObject jsonObject = new JSONObject();
        try {
            JSONObject postDataJson = new JSONObject();
            postDataJson.put("acl", CannedAccessControlList.PublicRead);
            postDataJson.put("key", key);
            jsonObject.putOpt("filename", fileName);
            jsonObject.putOpt("postData", postDataJson);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        RequestBody body = RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString());

        UploadApi uploadApi = RetrofitFactory.Companion.getInstance().create(UploadApi.class);
        uploadApi.getUploadTokenForTeacher(body).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<BaseResponse<UploadTokenInfoBean>>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull BaseResponse<UploadTokenInfoBean> response) {
                        if (response != null) {
                            uploadToken = "KSS " + response.getData().kssAccessKeyId + ":" + response.getData().signature;
                            doUpload(key, file);
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        uploadToken = "";
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }


    private String buildUploadUrl(String key) {
        StringBuilder sb = new StringBuilder();
        sb.append(PROTOCOL)
                .append(END_POINT)
                .append("/")
                .append(SRC_BUCKETNAME)
                .append("/")
                .append(key);
        LogUtils.i("UploadHelper", "upload success path:" + sb.toString());
        return sb.toString();
    }

    private UpLoadCallBack upLoadCallBack;

    public void setUpLoadCallBack(UpLoadCallBack upLoadCallBack) {
        this.upLoadCallBack = upLoadCallBack;
    }

    private void showUploadLoading() {
        if (mActivity == null || mActivity.isFinishing() || mActivity.isDestroyed()) {
            return;
        }
        if (mProgressLoading != null) {
            mProgressLoading.showLoading();
        }
    }

    private void hideUploadLoading() {
        if (mActivity == null || mActivity.isFinishing() || mActivity.isDestroyed()) {
            return;
        }
        if (mProgressLoading != null) {
            mProgressLoading.hideLoading();
        }
    }

    public abstract static class UpLoadCallBack {
        protected abstract void onSuccess(String url);

        protected abstract void onFailure();

        public void onUploadStart() {

        }

        public void onUploadCancel() {

        }


        public void onUploadProgress(double v) {

        }


        public void onUploadFinish() {

        }
    }
}
