package xn.hxp.ui.login;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.viewbinding.ViewBinding;

import com.blankj.utilcode.util.ClickUtils;
import com.blankj.utilcode.util.LogUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.rc.core.ui.activity.BaseActivity;
import com.rc.httpcore.HttpClient;
import com.rc.httpcore.HttpConfig;
import com.rc.httpcore.bean.UserValidationBean;
import com.rc.httpcore.client.ApiRepository;
import com.rc.httpcore.exception.NetException;
import com.rc.httpcore.vo.request.FaceCompareReq;

import java.io.File;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import io.fotoapparat.Fotoapparat;
import io.fotoapparat.facedetector.processor.FaceDetectorProcessor;
import io.fotoapparat.log.LoggersKt;
import io.fotoapparat.selector.LensPositionSelectorsKt;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import retrofit2.HttpException;
import xn.hxp.R;
import xn.hxp.app.ChemicalApp;
import xn.hxp.comm.Constants;
import xn.hxp.databinding.ActivityFacialLoginBinding;
import xn.hxp.utils.AudioPlayer;
import xn.hxp.utils.UiManager;
import xn.hxp.weidith.AuthenticationDialog;
import xn.hxp.weidith.CustomDialog;

public class FaceLoginActivity extends BaseActivity {

    private Fotoapparat mFotoapparat;
    private String faceList;
    private final Handler mainHandler = new Handler(Looper.getMainLooper());
    private int timeLeftInSeconds = 2;
    private TextView mTvView;
    private AuthenticationDialog mDialogsAut;
    private ActivityFacialLoginBinding viewBinding;
    private final AtomicBoolean isTakingPicture = new AtomicBoolean(false);
    private final AtomicBoolean isActivityRunning = new AtomicBoolean(false);

    @NonNull
    @Override
    protected ViewBinding setViewBinding() {
        viewBinding = ActivityFacialLoginBinding.inflate(getLayoutInflater());
        return viewBinding;
    }

    @Override
    protected void onInit() {
        isActivityRunning.set(true);
        AudioPlayer.getInstance().play(R.raw.face_detect_hint);
        viewBinding.deptName.setText(ChemicalApp.confs.getDeptName() + "-" + ChemicalApp.confs.getRoomNum());

        // 加载圆形logo
        loadCircularLogo();

        // 获取intent数据
        handleIntentData();

        // 初始化相机
        initCamera();

        // 开始倒计时和拍照循环
        startCountdownAndPictureLoop();
    }

    private void loadCircularLogo() {
        Glide.with(this)
                .load(HttpConfig.Companion.getAPI_BASE_IMG_URL() + ChemicalApp.confs.getCircularLogo())
                .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.AUTOMATIC))
                .into(viewBinding.image);
    }

    private void handleIntentData() {
        try {
            faceList = getIntent().getStringExtra("faceList");
            String mtypes = getIntent().getStringExtra("mtypes");

            if (mtypes != null) {
                switch (mtypes) {
                    case "1":
                        viewBinding.linType.setVisibility(View.GONE);
                        break;
                    case "4":
                        viewBinding.tvScan.setVisibility(View.GONE);
                        break;
                    case "5":
                        viewBinding.tvSwipe.setVisibility(View.GONE);
                        break;
                }
            }

            Map<String, String> map = new HashMap<>();
            if (mtypes != null) {
                map.put("mtypes", mtypes);
            }
            if (faceList != null && faceList.length() > 0) {
                faceList = faceList.replaceAll("^\\$$|\\$$$", "");
                map.put("faceList", faceList);
            }

            setupButtonListeners(map);
        } catch (Exception e) {
            LogUtils.e("Error handling intent data", e);
        }
    }

    private void setupButtonListeners(Map<String, String> map) {
        viewBinding.tvSwipe.setOnClickListener(new ClickUtils.OnDebouncingClickListener() {
            @Override
            public void onDebouncingClick(View v) {
                UiManager.INSTANCE.switcher(FaceLoginActivity.this, map, SwipeActivity.class);
                finish();
            }
        });

        viewBinding.tvScan.setOnClickListener(new ClickUtils.OnDebouncingClickListener() {
            @Override
            public void onDebouncingClick(View v) {
                UiManager.INSTANCE.switcher(FaceLoginActivity.this, map, ScanLoginActivity.class);
                finish();
            }
        });

        viewBinding.tvReturn.setText("返回" + ChemicalApp.confs.getBackTime() + "s");
        viewBinding.tvReturn.setOnClickListener(new ClickUtils.OnDebouncingClickListener() {
            @Override
            public void onDebouncingClick(View v) {
                finish();
            }
        });
    }

    private void initCamera() {
        mFotoapparat = Fotoapparat.with(this)
                .into(viewBinding.cameraView)
                .lensPosition(Constants.INSTANCE.getFACE_TAG() == 0 ? LensPositionSelectorsKt.front() : LensPositionSelectorsKt.back())
                .frameProcessor(FaceDetectorProcessor.with(this)
                        .listener(faces -> viewBinding.rectanglesView.setRectangles(faces))
                        .build())
                .logger(LoggersKt.loggers(LoggersKt.logcat(), LoggersKt.fileLogger(this)))
                .build();
        mFotoapparat.start();
    }

    private void startCountdownAndPictureLoop() {
        mainHandler.postDelayed(countdownRunnableTwo, 4000);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    @Override
    protected void cdTime(int cd) {
        viewBinding.tvReturn.setText("返回" + cd + "s");
    }

    @Override
    protected void onPause() {
        super.onPause();
        isActivityRunning.set(false);
        stopCameraAndRemoveCallbacks();
    }

    @Override
    protected void onResume() {
        super.onResume();
        isActivityRunning.set(true);
        if (mFotoapparat != null) {
            mFotoapparat.start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isActivityRunning.set(false);
        cleanupResources();
    }

    private void stopCameraAndRemoveCallbacks() {
        mainHandler.removeCallbacksAndMessages(null);
        if (mFotoapparat != null) {
            mFotoapparat.stop();
        }
    }

    private void cleanupResources() {
        if (mDialogsAut != null && mDialogsAut.isShowing()) {
            mDialogsAut.dismiss();
        }

        try {
            if (mFotoapparat != null) {
                mFotoapparat.stop();
            }
            mainHandler.removeCallbacksAndMessages(null);
            dismissLoading();
        } catch (Exception e) {
            LogUtils.e("Error during cleanup", e);
        }
    }

    @Override
    protected void cdFinish() {
        finish();
    }

    private void takePicture() {
        if (!isActivityRunning.get() || isTakingPicture.get()) {
            return;
        }

        isTakingPicture.set(true);
        LogUtils.i("=======人脸登录任务进行中");

        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.getDefault());
        String fileName = format.format(Calendar.getInstance().getTime()) + ".jpg";
        File photoFile = new File(getExternalFilesDir("photos"), fileName);

        try {
            mFotoapparat.takePicture()
                    .saveToFile(photoFile)
                    .whenAvailable(new Function1<Unit, Unit>() {
                        @Override
                        public Unit invoke(Unit unit) {
                            if (isActivityRunning.get()) {
                                callFaceMatchingApi(photoFile);
                            }
                            isTakingPicture.set(false);
                            return null;
                        }
                    });
        } catch (Exception e) {
            LogUtils.e("Error taking picture", e);
            isTakingPicture.set(false);
        }
    }

    private void callFaceMatchingApi(File featureData) {
        if (!isActivityRunning.get()) {
            return;
        }

        showLoading("比对中....");
        FaceCompareReq param = new FaceCompareReq();
        param.data = null;
        param.userIds = faceList;

        addDisposable(ApiRepository.INSTANCE.faceCompare(featureData, param)
                .subscribe(success -> {
                    if (!isActivityRunning.get()) {
                        return;
                    }
                    dismissLoading();
                    ChemicalApp.userData = success;
                    LogUtils.d(success.userId, ChemicalApp.subjectId);
                    authenticationInfo(success.userId, ChemicalApp.subjectId);
                }, throwable -> {
                    if (!isActivityRunning.get()) {
                        return;
                    }
                    dismissLoading();
                    throwableView(throwable);
                }));
    }

    private void authenticationInfo(String userId, String subId) {
        LogUtils.d(userId, subId);
        showLoading("验证中...");

        addDisposable(ApiRepository.INSTANCE.userCardValidation(userId, subId)
                .subscribe(data -> {
                    if (!isActivityRunning.get()) {
                        return;
                    }
                    dismissLoading();
                    handleAuthenticationResult(data);
                }, throwable -> {
                    if (!isActivityRunning.get()) {
                        return;
                    }
                    dismissLoading();
                    throwableView(throwable);
                }));
    }

    private void handleAuthenticationResult(UserValidationBean data) {
        boolean allFalse = Boolean.TRUE.equals(data.getCabinetAdmin()) ||
                Boolean.TRUE.equals(data.getBelongUser()) ||
                Boolean.TRUE.equals(data.getToipcUser()) ||
                Boolean.TRUE.equals(data.getSafeUser()) ||
                Boolean.TRUE.equals(data.getCollegeAdmin()) ||
                Boolean.TRUE.equals(data.getSchoolLevelAdmin()) ||
                Boolean.TRUE.equals(data.getAdminUser()) ||
                Boolean.TRUE.equals(data.getApply()) ||
                Boolean.TRUE.equals(data.getWhite());

        if (!allFalse) {
            handleFailedAuthentication();
        } else {
            handleSuccessfulAuthentication(data);
        }
    }

    private void handleFailedAuthentication() {
        HttpClient.INSTANCE.setToken(null);
        ChemicalApp.userData = null;
        customDialogView(2, "身份认证不通过");
    }

    private void handleSuccessfulAuthentication(UserValidationBean data) {
        if (Boolean.TRUE.equals(data.getSchoolLevelAdmin()) || Boolean.TRUE.equals(data.getCollegeAdmin())) {
            showAuthenticationDialog(data.getFaceImg(), data.getUserName());
        } else if (Boolean.TRUE.equals(data.getAdminUser()) || Boolean.TRUE.equals(data.getSafeUser()) || Boolean.TRUE.equals(data.getCabinetAdmin())) {
            showAuthenticationDialog(data.getFaceImg(), data.getUserName());
        } else if (Boolean.TRUE.equals(data.getBelongUser()) || Boolean.TRUE.equals(data.getToipcUser())) {
            showAuthenticationDialog(data.getFaceImg(), data.getUserName());
        } else if (Boolean.TRUE.equals(data.getWhite()) || Boolean.TRUE.equals(data.getApply())) {
            showAuthenticationDialog(data.getFaceImg(), data.getUserName());
        } else {
            handleFailedAuthentication();
        }
    }

    private void showAuthenticationDialog(String faceImg, String userName) {
        if (!isActivityRunning.get()) {
            return;
        }

        mFotoapparat.stop();
        mainHandler.removeCallbacks(countdownRunnableTwo);
        AudioPlayer.getInstance().play(R.raw.verify_success);

        mDialogsAut = new AuthenticationDialog(
                this,
                faceImg,
                ChemicalApp.confs.getSubName(),
                ChemicalApp.confs.getDeptName(),
                ChemicalApp.confs.getBuildName() + ChemicalApp.confs.getFloorName(),
                userName,
                new AuthenticationDialog.IClickLit() {
                    @Override
                    public void onUpView(TextView tvView) {
                        mTvView = tvView;
                    }
                });
        mDialogsAut.show();

        timeLeftInSeconds = 2;
        mainHandler.post(countdownRunnable);

        setupDialogTouchListener();
    }

    private void setupDialogTouchListener() {
        mDialogsAut.getWindow().getDecorView().setOnTouchListener((v, event) -> {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                float x = event.getX();
                float y = event.getY();
                View dialogView = mDialogsAut.getWindow().getDecorView();
                if (dialogView != null && (x < 0 || x > dialogView.getWidth() || y < 0 || y > dialogView.getHeight())) {
                    mDialogsAut.dismiss();
                    finish();
                    return true;
                }
            }
            return false;
        });
    }

    private final Runnable countdownRunnable = new Runnable() {
        @Override
        public void run() {
            if (!isActivityRunning.get()) {
                return;
            }

            if (timeLeftInSeconds > 0) {
                if (mTvView != null) {
                    mTvView.setText(timeLeftInSeconds + "秒后自动返回首页");
                }
                timeLeftInSeconds--;
                mainHandler.postDelayed(this, 1000);
            } else {
                if (mDialogsAut != null && mDialogsAut.isShowing()) {
                    mDialogsAut.dismiss();
                }
                finish();
            }
        }
    };

    private final Runnable countdownRunnableTwo = new Runnable() {
        @Override
        public void run() {
            if (!isActivityRunning.get()) {
                return;
            }

            takePicture();
            mainHandler.postDelayed(this, 4000);
        }
    };

    private void customDialogView(int types, String msg) {
        if (!isActivityRunning.get() || isFinishing() || isDestroyed()) {
            return;
        }

        CustomDialog customDialog = new CustomDialog(this, types, msg);
        customDialog.show();
    }

    private void throwableView(Throwable throwable) {
        LogUtils.e(Log.getStackTraceString(throwable));
        String message = getErrorMessage(throwable);
        customDialogView(2, message);
    }

    private String getErrorMessage(Throwable throwable) {
        if (throwable instanceof NetException) {
            if (((NetException) throwable).getMessage() == null || ((NetException) throwable).getMessage().isEmpty()) {
                return "接口请求失败(" + ((NetException) throwable).getCode() + ")";
            } else {
                return ((NetException) throwable).getMessage();
            }
        } else if (throwable instanceof SocketTimeoutException) {
            return "请求超时，请稍后重试";
        } else if (throwable instanceof ConnectException) {
            return "无法连接服务器，请检查网络";
        } else if (throwable instanceof HttpException) {
            return "服务器繁忙，请稍后重试";
        } else {
            return "服务器异常";
        }
    }
}