package com.ttstd.controller.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;

import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKey;

import java.io.IOException;
import java.security.GeneralSecurityException;

/**
 * 主控端令牌安全存储。
 *
 * 登录得到的 accessToken 与 refreshToken 以密文落盘（EncryptedSharedPreferences）。
 * refreshToken 为一次性（ses_ 前缀），刷新后服务端可能轮换，需覆盖保存。
 */
public final class TokenStore {

    private static final String FILE_NAME = "ttstd_controller_tokens";
    private static final String KEY_ACCESS = "access_token";
    private static final String KEY_REFRESH = "refresh_token";
    private static final String KEY_USERNAME = "username";

    private static volatile TokenStore instance;

    private final SharedPreferences sp;

    public TokenStore(Context context) {
        this.sp = create(context);
    }

    /**
     * 在 {@code BaseApplication#onCreate} 中初始化一次，供拦截器与仓库层全局访问。
     */
    public static void init(Context context) {
        if (instance == null) {
            synchronized (TokenStore.class) {
                if (instance == null) {
                    instance = new TokenStore(context.getApplicationContext());
                }
            }
        }
    }

    public static TokenStore get() {
        if (instance == null) {
            throw new IllegalStateException("TokenStore 未初始化，请先在 Application 中调用 TokenStore.init()");
        }
        return instance;
    }

    private static SharedPreferences create(Context context) {
        try {
            MasterKey masterKey = new MasterKey.Builder(context)
                    .setKeyGenParameterSpec(
                            new KeyGenParameterSpec.Builder(
                                    MasterKey.DEFAULT_MASTER_KEY_ALIAS,
                                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                                    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                    .setKeySize(256)
                                    .build())
                    .build();
            return EncryptedSharedPreferences.create(
                    context,
                    FILE_NAME,
                    masterKey,
                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
        } catch (GeneralSecurityException | IOException e) {
            return context.getSharedPreferences(FILE_NAME + "_fallback", Context.MODE_PRIVATE);
        }
    }

    public void save(String accessToken, String refreshToken, String username) {
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(KEY_ACCESS, accessToken);
        if (refreshToken != null) editor.putString(KEY_REFRESH, refreshToken);
        if (username != null) editor.putString(KEY_USERNAME, username);
        editor.apply();
    }

    public void saveAccessToken(String accessToken) {
        sp.edit().putString(KEY_ACCESS, accessToken).apply();
    }

    public void saveRefreshToken(String refreshToken) {
        if (refreshToken != null) sp.edit().putString(KEY_REFRESH, refreshToken).apply();
    }

    public String getAccessToken() {
        return sp.getString(KEY_ACCESS, null);
    }

    public String getRefreshToken() {
        return sp.getString(KEY_REFRESH, null);
    }

    public String getUsername() {
        return sp.getString(KEY_USERNAME, null);
    }

    public boolean hasTokens() {
        return sp.getString(KEY_ACCESS, null) != null && sp.getString(KEY_REFRESH, null) != null;
    }

    public void clear() {
        sp.edit().clear().apply();
    }
}
