package com.datarecovery.master.utils;


import android.app.Application;
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import com.atmob.app.lib.base.BaseResponse;
import com.atmob.common.runtime.ContextUtil;
import com.atmob.common.runtime.ProcessUtil;
import com.datarecovery.master.data.consts.Constants;
import com.datarecovery.master.data.repositories.AccountRepository;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

import atmob.reactivex.rxjava3.core.SingleTransformer;
import dagger.hilt.EntryPoint;
import dagger.hilt.InstallIn;
import dagger.hilt.android.EntryPointAccessors;
import dagger.hilt.components.SingletonComponent;

/**
 * 处理RxJava封装的http响应结果, 后续可以根据某些通用code或者exception在此处聚合处理
 */
public class RxHttpHandler {

    private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());

    public static <T> SingleTransformer<BaseResponse<T>, T> handle(boolean allowEmptyData) {
        return upstream -> upstream
                .compose(handleInternal(allowEmptyData));
    }

    private static <T> SingleTransformer<BaseResponse<T>, T> handleInternal(boolean allowEmptyData) {
        return upstream -> upstream.map(
                        response -> {
                            if (response == null) {
                                throw new Exception("response is null");
                            }
                            int code = response.getCode();
                            T data = response.getData();
                            if (code == 0) {
                                if (data != null || allowEmptyData) {
                                    return data == null ? createT(response) : data;
                                } else {
                                    throw new Exception("data is null");
                                }
                            } else {
                                throw new ServerErrorException(code, response.getMsg());
                            }
                        })
                .doOnSuccess(RxHttpHandler::doOnSuccess)
                .doOnError(RxHttpHandler::doOnResponseError);
    }

    private static <T> T createT(@NonNull BaseResponse<T> response) {
        try {
            Field data = response.getClass().getDeclaredField("data");
            Class<?> type = data.getType();
            Constructor<?> constructor = type.getConstructor();
            Object o = constructor.newInstance();
            return (T) o;
        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
                 InvocationTargetException | NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> void doOnSuccess(T t) {
        // TODO: 2022/5/25 请求成功的通用处理, 比如含有UserBean的Response, 发送刷新各界面用户信息的Event
    }

    public static void doOnResponseError(Throwable throwable) {
        if (!ProcessUtil.isMainThread()) {
            MAIN_HANDLER.post(() -> doOnResponseError(throwable));
            return;
        }
        ServerErrorException serverErrorException = throwable instanceof ServerErrorException ? ((ServerErrorException) throwable) : null;
        if (serverErrorException != null) {
            if (serverErrorException.getCode() == Constants.ERROR_CODE_NO_LOGIN_ERROR) {
                Application application = ContextUtil.getApplication();
                EntryPointAccessors.fromApplication(application, RxHttpHandlerEntryPoint.class)
                        .accountRepository()
                        .logout();
            }
        }
    }

    public static class ServerErrorException extends Exception {
        private final int code;
        private final String msg;

        public ServerErrorException(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public int getCode() {
            return code;
        }

        public String getMsg() {
            return msg;
        }
    }

    @InstallIn(SingletonComponent.class)
    @EntryPoint
    interface RxHttpHandlerEntryPoint {
        AccountRepository accountRepository();
    }
}