package com.ttstd.controller.network;

import com.ttstd.controller.network.model.BindingItem;
import com.ttstd.controller.network.model.BindingsResponse;
import com.ttstd.controller.network.model.OnlineDevicesResponse;
import com.ttstd.controller.network.model.LoginRequest;
import com.ttstd.controller.network.model.RedeemRequest;
import com.ttstd.controller.network.model.RefreshRequest;
import com.ttstd.controller.network.model.TokenResponse;
import com.ttstd.controller.network.model.VerifyResponse;
import com.ttstd.controller.utils.TokenStore;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.schedulers.Schedulers;

/**
 * 用户端认证 / 会话仓库。
 *
 * <p>对外统一返回 {@code Single} 冷流并已切到 IO 线程，由 ViewModel 的
 * CompositeDisposable 订阅，随生命周期自动取消。
 */
public class AuthRepository {

    private final AuthApi authApi;
    private final ClientApi clientApi;

    public AuthRepository() {
        this.authApi = RetrofitClient.authApi();
        this.clientApi = RetrofitClient.clientApi();
    }

    /**
     * 用户名密码登录，成功后自动持久化令牌。
     */
    public Single<TokenResponse> login(String username, String password) {
        return authApi.login(new LoginRequest(username, password))
                .doOnSuccess(token -> TokenStore.get().save(
                        token.getAccessToken(),
                        token.getRefreshToken(),
                        username))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 使用本地 refreshToken 续期，成功后覆盖保存（服务端会轮换 refreshToken）。
     */
    public Single<TokenResponse> refresh() {
        String refreshToken = TokenStore.get().getRefreshToken();
        if (refreshToken == null || refreshToken.isEmpty()) {
            return Single.error(new IllegalStateException("本地无刷新令牌"));
        }
        return authApi.refresh(new RefreshRequest(refreshToken))
                .doOnSuccess(token -> {
                    TokenStore.get().saveAccessToken(token.getAccessToken());
                    TokenStore.get().saveRefreshToken(token.getRefreshToken());
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 启动页登录态检查：先校验 access 令牌，失效则用 refresh 续期后再校验一次。
     *
     * @return true 表示已登录可直接进入主页
     */
    public Single<Boolean> checkLoginState() {
        if (!TokenStore.get().hasTokens()) {
            return Single.just(false);
        }
        return clientApi.verify()
                .map(VerifyResponse::isValid)
                .onErrorResumeNext(error -> refresh()
                        .flatMap(token -> clientApi.verify())
                        .map(VerifyResponse::isValid)
                        .onErrorReturnItem(false))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /** 校验当前令牌并返回本机账号信息（用户 id / 用户名）。 */
    public Single<VerifyResponse> verify() {
        return clientApi.verify().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /** 查询当前用户已绑定的被控端设备列表。 */
    public Single<BindingsResponse> bindings() {
        return clientApi.bindings().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /** 查询当前用户已绑定且在线（信令网络活跃）的被控端设备列表。 */
    public Single<OnlineDevicesResponse> onlineDevices() {
        return clientApi.onlineDevices().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /** 兑换配对码，建立与被控端的绑定关系。 */
    public Single<BindingItem> redeemPairingCode(String code) {
        return clientApi.redeemPairingCode(new RedeemRequest(code)).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /** 退出登录：清空本地令牌。 */
    public void logout() {
        TokenStore.get().clear();
    }
}
