package com.tongyi.multimodal_dialog;

import android.Manifest.permission;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.aliyun.bailian.billingsignature.DeviceAuthClient;
import com.aliyun.bailian.billingsignature.bean.DeviceRegisterParams;
import com.aliyun.bailian.billingsignature.bean.GenGetTokenParams;
import com.aliyun.bailian.billingsignature.bean.InitParams;
import com.aliyun.bailian.billingsignature.bean.ResultError;
import com.aliyun.bailian.billingsignature.constants.PayMode;
import com.aliyun.bailian.billingsignature.interfaces.DeviceRegisterCallBack;
import com.aliyun.bailian.billingsignature.interfaces.GetTokenCallBack;
import com.aliyun.bailian.billingsignature.interfaces.InitCallBack;
import com.aliyun.bailian.billingsignature.utils.DeviceUUIDUtil;
import com.aliyun.bailian.billingsignature.utils.RandomUtil;
import com.tongyi.multimodal_conversation.R;
import com.tongyi.multimodal_dialog.data.MultimodalParams;
import com.tongyi.multimodal_dialog.data.request.MultiModalRequestParam;
import com.tongyi.multimodal_dialog.util.ConvLog;
import com.tongyi.multimodal_dialog.util.DeviceUtil;
import com.tongyi.multimodal_dialog.video.TYVideoConfig;

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

/**
 * @author songsong.shao
 * @date 2024/10/15
 * description:
 */
public class EntranceActivity extends AppCompatActivity {
    private static final String TAG = EntranceActivity.class.getSimpleName();
    private static final int PERMISSION_REQUEST_CODE = 100;
    //Demo支持 WebSocket 链路
    private static String url = "wss://dashscope.aliyuncs.com/api-ws/v1/inference";
    // 凭证默认值（占位符）。运行时由 BailianCredentials 三级回退加载：
    //   SharedPreferences（用户上次填的） > assets/credentials.properties（开发者本地） > 这里的占位符
    // 推荐做法：复制 assets/credentials.properties.template → assets/credentials.properties 填入真实值，免去每次手动输入
    private static String workspaceId = "YOUR_WORKSPACE_ID";
    private static String apiKey = "YOUR_API_KEY";
    private static String appId = "YOUR_APP_ID";
    private static String vqaImgLink = "https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/7043267371/p909896.png";


    private EditText apiKeyView;
    private EditText workspaceIdView;
    private EditText urlView;
    private Spinner convTypeSpinner;
    private EditText vqaLinkView;
    private EditText modelView;

    private EditText appidView;
    private boolean isAudio = true;


    private String[] permissions = new String[]{
            permission.RECORD_AUDIO,
            permission.CAMERA,
            permission.WRITE_EXTERNAL_STORAGE,
            permission.ACCESS_COARSE_LOCATION,
            permission.READ_EXTERNAL_STORAGE

    };


    //License计费模式
    private LinearLayout llAppSecret;
    private EditText getAppSecretView;

    private String mDeviceName;
    private String mPayMode = PayMode.PAYG.getPayMode(); //默认后付费


    @SuppressLint({"MissingInflatedId", "SetTextI18n"})
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DeviceUtil.setStatusBarColor(this);
        setContentView(R.layout.activity_entrance);

        apiKeyView = (EditText) findViewById(R.id.editView2);
        vqaLinkView = (EditText) findViewById(R.id.editView3);
        workspaceIdView = (EditText) findViewById(R.id.editView6);
        urlView = (EditText) findViewById(R.id.editView9);
        appidView = (EditText) findViewById(R.id.editView11);
        modelView = (EditText) findViewById(R.id.editViewModel);
        convTypeSpinner = (Spinner) findViewById(R.id.spinner);
        ConvLog.setLogLevel(ConvLog.DEBUG);

        // 初始化参数：三级回退加载凭证（SP → assets/credentials.properties → 占位符）
        // 占位符值不会回填到输入框，避免用户看到 "YOUR_API_KEY" 还要先删掉
        String loadedApiKey = BailianCredentials.load(this, BailianCredentials.KEY_API_KEY, apiKey);
        String loadedWorkspaceId = BailianCredentials.load(this, BailianCredentials.KEY_WORKSPACE_ID, workspaceId);
        String loadedAppId = BailianCredentials.load(this, BailianCredentials.KEY_APP_ID, appId);
        if (BailianCredentials.isUsable(loadedApiKey)) apiKeyView.setText(loadedApiKey);
        if (BailianCredentials.isUsable(loadedWorkspaceId)) workspaceIdView.setText(loadedWorkspaceId);
        if (BailianCredentials.isUsable(loadedAppId)) appidView.setText(loadedAppId);
        vqaLinkView.setText(vqaImgLink);
        urlView.setText(BailianCredentials.load(this, BailianCredentials.KEY_URL, url));
        modelView.setText("multimodal-dialog");



        // 进入页面后，尝试主动申请权限，简化流程
        checkPermission();


        findViewById(R.id.btn_chat).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                genLaunchParams();
                // 凭证校验：识别空值和 YOUR_xxx 占位符，给出明确的提示（哪个字段没填）
                String missing = BailianCredentials.findMissingField(
                        multimodalParams.getApiKey(),
                        multimodalParams.getWorkspaceId(),
                        multimodalParams.getAppid());
                if (missing != null) {
                    showToast("请填写 " + missing + "（可在 https://bailian.console.aliyun.com/cn-beijing?tab=app#/app/app-market/multi-modal-app/myApp 获取）");
                    return;
                }
                // 校验通过：持久化到 SharedPreferences，下次开 App 自动回填
                BailianCredentials.save(EntranceActivity.this,
                        multimodalParams.getApiKey(),
                        multimodalParams.getWorkspaceId(),
                        multimodalParams.getAppid());
                if (mPayMode.equals(PayMode.PAYG.getPayMode())) {
                    if (!hasPermissions(permissions)) {
                        ActivityCompat.requestPermissions(EntranceActivity.this, permissions, PERMISSION_REQUEST_CODE);
                    } else {
                        launchVideoChat();
                    }
                } else {
                    //License计费模式，需要依次完成tongyimetathings sdk的初始化、设备注册、获取token
                    String appSecret = getAppSecretView.getText().toString().trim();
                    if (TextUtils.isEmpty(appSecret)) {
                        showToast("请补充应用AppSecret");//前往控制台应用详情界面购买License后，应用详情界面--管理License--License秘钥
                        return;
                    }
                    DeviceAuthClient.getInstance().initialize(new InitParams(multimodalParams.getAppid(), appSecret, mDeviceName), new InitCallBack() {
                        @Override
                        public void success() {
                            //初始化完成，检测设备是否注册
                            if (DeviceAuthClient.getInstance().deviceIsRegistered()) {
                                getToken();
                            } else {
                                deviceRegister();
                            }
                        }

                        @Override
                        public void fail(ResultError resultError) {
                            Log.e(TAG, "tongyimetathings sdk initialize error:" + resultError.getMessage());
                            showToast("tongyimetathings sdk initialize error:" + resultError.getMessage());
                        }
                    });


                }

            }
        });
        mDeviceName = DeviceUUIDUtil.getAndroidId(this);
        llAppSecret = findViewById(R.id.ll_app_secret);
        getAppSecretView = findViewById(R.id.et_app_secret);
        ((RadioGroup) findViewById(R.id.rg_pay_mode)).setOnCheckedChangeListener((radioGroup, checkedId) -> {
            if (checkedId == R.id.rb_payg) {
                mPayMode = PayMode.PAYG.getPayMode();
                llAppSecret.setVisibility(View.GONE);
            } else {
                mPayMode = PayMode.LICENSE.getPayMode();
                llAppSecret.setVisibility(View.VISIBLE);
            }
        });
    }

    private MultimodalParams multimodalParams;

    /**
     * 拉起VideoChat页
     */
    private void launchVideoChat() {
        if (null == multimodalParams) {
            Log.e(TAG, "launch failed without authParams or requestConfig");
            return;
        }
        String modeNow = convTypeSpinner.getSelectedItem().toString();
        Log.i(TAG, "convTypeSpinner switch " + modeNow);

        if (modeNow.equals("tap2talk")) {
            multimodalParams.setDialogMode(Constant.DialogMode.TAP2TALK);
        } else if (modeNow.equals("duplex")) {
            multimodalParams.setDialogMode(Constant.DialogMode.DUPLEX);
        }else {
            multimodalParams.setDialogMode(Constant.DialogMode.PUSH2TALK);
        }


        MultimodalConversationActivity.launch(EntranceActivity.this, multimodalParams, mPayMode);
        Log.d(TAG, "startRTC called payload:" + multimodalParams);
    }

    private void checkPermission() {
        if (ContextCompat.checkSelfPermission(this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
            return;
        }
        if (ContextCompat.checkSelfPermission(this, permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{permission.RECORD_AUDIO}, PERMISSION_REQUEST_CODE);
            return;
        }

        //通过网络获取地址
        if (ContextCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE);
            return;
        }

        if (ContextCompat.checkSelfPermission(this, permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{permission.CAMERA}, PERMISSION_REQUEST_CODE);
            return;
        }
        if (ContextCompat.checkSelfPermission(this, permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//        if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//            launchVideoChat();
//        }

        if (requestCode == PERMISSION_REQUEST_CODE) {
            boolean allGranted = true;
            for (int grantResult : grantResults) {
                if (grantResult != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }
            if (allGranted) {
                launchVideoChat();
            } else {
                Toast.makeText(this, "权限申请失败", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * 生成请求参数
     */
    private void genLaunchParams() {
        try {
            multimodalParams = new MultimodalParams();
            //目前只支持语音模式

            TYVideoConfig videoConfig = new TYVideoConfig(1280,720,2);
            multimodalParams.setVideoConfig(videoConfig);
            //修改交互单双工模式 duplex/tap2talk


            //其他参数
            multimodalParams.setUrl(urlView.getText().toString());
            multimodalParams.setAppid(appidView.getText().toString());
            multimodalParams.setApiKey(apiKeyView.getText().toString());
            multimodalParams.setWorkspaceId(workspaceIdView.getText().toString());
            multimodalParams.setVqaImageLink(vqaLinkView.getText().toString());
            multimodalParams.setDialogMode(Constant.DialogMode.DUPLEX);
            multimodalParams.setModelId(modelView.getText().toString());

            //仅支持 WebSocket 链路
            multimodalParams.setChainMode(Constant.ChainMode.WEBSOCKET);
        } catch (Exception ex) {
            ex.printStackTrace();
            multimodalParams = null;
        }
    }

    private boolean hasPermissions(String[] permissions) {
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }


    //License计费模式相关示例方法

    /**
     * 设备注册
     */
    public void deviceRegister() {
        DeviceRegisterParams params = new DeviceRegisterParams();
        params.setNonce(RandomUtil.generateRandomHexString(26));
        params.setAppId(multimodalParams.getAppid());
        params.setWorkspaceId(multimodalParams.getWorkspaceId());
        params.setDeviceName(mDeviceName);
        params.setRequestTime(String.valueOf(System.currentTimeMillis()));
        params.setPayMode(PayMode.LICENSE.getPayMode());
        DeviceAuthClient.getInstance().deviceRegister(params, new DeviceRegisterCallBack() {

            @Override
            public void success() {
                Log.d(TAG, "deviceRegister success");
                getToken();
            }

            @Override
            public void fail(ResultError error) {
                Log.e(TAG, error.getMessage());
                showToast(error.getMessage());
            }
        });
    }

    /**
     * License模式请求token
     */
    private void getToken() {
        GenGetTokenParams params = new GenGetTokenParams();
        params.setNonce(RandomUtil.generateRandomHexString(26));
        params.setAppId(multimodalParams.getAppid());
        params.setApiKey(multimodalParams.getApiKey());
        params.setDeviceName(mDeviceName);
        params.setRequestTime(String.valueOf(System.currentTimeMillis()));
        params.setPayMode(PayMode.LICENSE.getPayMode());
        params.setTokenType("MMI");
        DeviceAuthClient.getInstance().getToken(params, new GetTokenCallBack() {
            @Override
            public void success(String tokenInfo) {
                Log.d(TAG, "getToken success: " + tokenInfo);
                try {
                    JSONObject jsonObject = new JSONObject(tokenInfo);
                    multimodalParams.setApiKey(jsonObject.getString("dashToken"));
                } catch (JSONException e) {
                    Log.e(TAG, "getToken error: " + e.getMessage());
                    return;
                }
                if (!hasPermissions(permissions)) {
                    checkPermission();
                } else {
                    launchVideoChat();
                }
            }

            @Override
            public void fail(ResultError error) {
                showToast("鉴权失败，请检查参数配置");
                Log.e(TAG, "getToken error:" + error.getMessage());
            }
        });
    }

    private void showToast(String message) {
        runOnUiThread(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show());
    }
}
