/*
 * 自然写互动课堂应用开发SDK软件 V1.0
 * WritechSDK - SDK初始化与鉴权入口
 *
 * 功能说明：
 * 1. SDK全局初始化（配置加载、模块注册）
 * 2. 应用鉴权（AppKey/AppSecret验证）
 * 3. 各子模块生命周期管理
 * 4. 全局配置管理（服务器地址、超时、日志级别）
 * 5. SDK版本信息与功能授权查询
 */

package com.writech.sdk.android;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 自然写SDK主入口类
 * 使用前必须先调用 init() 方法进行初始化和鉴权
 *
 * 典型使用流程：
 * 1. WritechSDK.init(context, config)
 * 2. WritechSDK.getInstance().getPenManager().startScan()
 * 3. WritechSDK.getInstance().getOCREngine().recognizeHandwriting(...)
 */
public class WritechSDK {

    private static final String TAG = "WritechSDK";

    /* SDK版本号 */
    public static final String SDK_VERSION = "1.0.0";

    /* SDK构建号 */
    public static final int SDK_BUILD = 100;

    /* 单例实例 */
    private static volatile WritechSDK sInstance;

    /* 是否已初始化 */
    private static final AtomicBoolean sInitialized = new AtomicBoolean(false);

    /* ========== 配置类 ========== */

    /** SDK初始化配置 */
    public static class Config {
        /** 云平台API地址 */
        public String cloudBaseUrl = "https://api.writech.com";

        /** SDK应用标识（从自然写开放平台获取） */
        public String appKey;

        /** SDK应用密钥 */
        public String appSecret;

        /** 离线OCR模型文件路径（可选） */
        public String offlineModelPath;

        /** 是否启用调试日志 */
        public boolean debugMode = false;

        /** 笔迹数据本地缓存目录 */
        public String cacheDir;

        /** BLE扫描超时时间（毫秒） */
        public int bleScanTimeout = 30000;

        /** 网关自动发现 */
        public boolean autoDiscoverGateway = true;

        /** 最大同时连接笔数 */
        public int maxPenConnections = 60;
    }

    /* ========== 成员变量 ========== */

    private Context mContext;
    private Config mConfig;

    /* 各子模块实例 */
    private PenManager mPenManager;
    private StrokeCanvas mDefaultCanvas;
    private OCREngine mOCREngine;
    private GatewaySDK mGatewaySDK;
    private CloudClient mCloudClient;

    /* 鉴权状态 */
    private boolean mIsAuthenticated = false;
    private String mLicenseType;          /* 授权类型: trial/standard/enterprise */
    private long mLicenseExpireTime;      /* 授权到期时间 */

    /* 本地存储 */
    private SharedPreferences mPrefs;

    /* ========== 初始化入口 ========== */

    /**
     * 初始化SDK（必须在使用任何功能前调用）
     *
     * @param context  Android上下文（Application级别）
     * @param config   SDK配置
     * @return 初始化结果：true成功，false失败
     */
    public static boolean init(Context context, Config config) {
        if (sInitialized.getAndSet(true)) {
            Log.w(TAG, "SDK已初始化，忽略重复调用");
            return true;
        }

        if (context == null || config == null) {
            Log.e(TAG, "初始化失败：context或config为null");
            sInitialized.set(false);
            return false;
        }

        if (config.appKey == null || config.appSecret == null) {
            Log.e(TAG, "初始化失败：appKey或appSecret未配置");
            sInitialized.set(false);
            return false;
        }

        sInstance = new WritechSDK();
        boolean success = sInstance.doInit(context, config);

        if (!success) {
            sInstance = null;
            sInitialized.set(false);
        }

        return success;
    }

    /** 获取SDK单例 */
    public static WritechSDK getInstance() {
        if (sInstance == null) {
            throw new IllegalStateException("WritechSDK未初始化，请先调用 WritechSDK.init()");
        }
        return sInstance;
    }

    /** 检查SDK是否已初始化 */
    public static boolean isInitialized() {
        return sInitialized.get();
    }

    /* ========== 内部初始化流程 ========== */

    /** 执行具体的初始化逻辑 */
    private boolean doInit(Context context, Config config) {
        mContext = context.getApplicationContext();
        mConfig = config;
        mPrefs = mContext.getSharedPreferences("writech_sdk", Context.MODE_PRIVATE);

        Log.i(TAG, "=== 自然写SDK V" + SDK_VERSION + " 初始化开始 ===");
        Log.i(TAG, "云平台地址: " + config.cloudBaseUrl);
        Log.i(TAG, "AppKey: " + config.appKey.substring(0, 8) + "****");
        Log.i(TAG, "调试模式: " + config.debugMode);

        /* 步骤1：应用鉴权（验证AppKey和AppSecret） */
        if (!authenticate(config.appKey, config.appSecret)) {
            Log.e(TAG, "SDK鉴权失败，请检查AppKey和AppSecret");
            return false;
        }

        /* 步骤2：初始化云平台客户端 */
        mCloudClient = new CloudClient(config.cloudBaseUrl, config.appKey, config.appSecret);

        /* 恢复本地缓存的令牌 */
        restoreTokens();

        /* 步骤3：初始化蓝牙笔管理器 */
        mPenManager = new PenManager(mContext);

        /* 步骤4：初始化OCR引擎 */
        mOCREngine = new OCREngine(mContext, config.cloudBaseUrl, null);
        if (config.offlineModelPath != null) {
            mOCREngine.loadOfflineModel(config.offlineModelPath);
        }

        /* 步骤5：初始化网关SDK */
        mGatewaySDK = new GatewaySDK(mContext);
        if (config.autoDiscoverGateway) {
            mGatewaySDK.startDiscovery();
        }

        Log.i(TAG, "=== 自然写SDK初始化完成 ===");
        return true;
    }

    /* ========== 应用鉴权 ========== */

    /**
     * 验证AppKey和AppSecret的有效性
     * 首次验证需要联网，之后缓存鉴权结果
     */
    private boolean authenticate(String appKey, String appSecret) {
        /* 检查本地缓存的鉴权结果 */
        String cachedLicense = mPrefs.getString("license_type", null);
        long cachedExpire = mPrefs.getLong("license_expire", 0);

        if (cachedLicense != null && cachedExpire > System.currentTimeMillis()) {
            mIsAuthenticated = true;
            mLicenseType = cachedLicense;
            mLicenseExpireTime = cachedExpire;
            Log.i(TAG, "使用缓存鉴权结果: " + mLicenseType
                  + "，到期: " + new java.util.Date(mLicenseExpireTime));
            return true;
        }

        /* 在线鉴权 */
        try {
            String authUrl = mConfig.cloudBaseUrl + "/api/v1/sdk/authenticate";
            String body = "{\"appKey\":\"" + appKey
                         + "\",\"appSecret\":\"" + appSecret
                         + "\",\"sdkVersion\":\"" + SDK_VERSION + "\"}";

            /* 使用CloudClient的静态方法发送无认证请求 */
            java.net.HttpURLConnection conn =
                (java.net.HttpURLConnection) new java.net.URL(authUrl).openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setDoOutput(true);
            conn.setConnectTimeout(10000);
            conn.getOutputStream().write(body.getBytes(java.nio.charset.StandardCharsets.UTF_8));

            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                java.io.InputStream is = conn.getInputStream();
                java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
                byte[] buf = new byte[1024];
                int len;
                while ((len = is.read(buf)) != -1) {
                    baos.write(buf, 0, len);
                }
                String response = baos.toString("UTF-8");
                is.close();
                conn.disconnect();

                /* 解析鉴权结果 */
                mLicenseType = extractJsonField(response, "licenseType");
                String expireStr = extractJsonField(response, "expireTime");
                if (mLicenseType != null) {
                    mLicenseExpireTime = expireStr != null ? Long.parseLong(expireStr)
                                        : System.currentTimeMillis() + 365L * 24 * 3600 * 1000;
                    mIsAuthenticated = true;

                    /* 缓存鉴权结果 */
                    mPrefs.edit()
                        .putString("license_type", mLicenseType)
                        .putLong("license_expire", mLicenseExpireTime)
                        .apply();

                    Log.i(TAG, "在线鉴权成功: " + mLicenseType);
                    return true;
                }
            }
            conn.disconnect();

        } catch (Exception e) {
            Log.w(TAG, "在线鉴权异常: " + e.getMessage());
            /* 联网失败时允许离线试用（7天） */
            mLicenseType = "trial";
            mLicenseExpireTime = System.currentTimeMillis() + 7L * 24 * 3600 * 1000;
            mIsAuthenticated = true;
            Log.i(TAG, "离线模式，试用授权7天");
            return true;
        }

        return false;
    }

    /** 恢复本地缓存的认证令牌 */
    private void restoreTokens() {
        String accessToken = mPrefs.getString("access_token", null);
        String refreshToken = mPrefs.getString("refresh_token", null);
        long expireTime = mPrefs.getLong("token_expire", 0);

        if (accessToken != null && refreshToken != null) {
            mCloudClient.setTokens(accessToken, refreshToken, expireTime);
            Log.d(TAG, "已恢复缓存的认证令牌");
        }
    }

    /* ========== 对外接口 ========== */

    /** 获取笔管理器 */
    public PenManager getPenManager() {
        return mPenManager;
    }

    /** 获取OCR引擎 */
    public OCREngine getOCREngine() {
        return mOCREngine;
    }

    /** 获取网关SDK */
    public GatewaySDK getGatewaySDK() {
        return mGatewaySDK;
    }

    /** 获取云平台客户端 */
    public CloudClient getCloudClient() {
        return mCloudClient;
    }

    /** 获取SDK版本 */
    public String getVersion() {
        return SDK_VERSION;
    }

    /** 获取授权类型 */
    public String getLicenseType() {
        return mLicenseType;
    }

    /** 检查是否已鉴权 */
    public boolean isAuthenticated() {
        return mIsAuthenticated;
    }

    /** 用户登录（通过云平台认证） */
    public boolean loginUser(String username, String password) {
        try {
            String response = mCloudClient.login(username, password);
            String accessToken = extractJsonField(response, "accessToken");
            String refreshToken = extractJsonField(response, "refreshToken");

            if (accessToken != null) {
                long expireTime = System.currentTimeMillis() + 30 * 60 * 1000;
                mCloudClient.setTokens(accessToken, refreshToken, expireTime);

                /* 缓存令牌 */
                mPrefs.edit()
                    .putString("access_token", accessToken)
                    .putString("refresh_token", refreshToken)
                    .putLong("token_expire", expireTime)
                    .apply();

                return true;
            }
        } catch (IOException e) {
            Log.e(TAG, "登录失败: " + e.getMessage());
        }
        return false;
    }

    /* ========== 资源释放 ========== */

    /** 释放SDK所有资源 */
    public static void destroy() {
        if (sInstance != null) {
            if (sInstance.mGatewaySDK != null) sInstance.mGatewaySDK.destroy();
            if (sInstance.mOCREngine != null) sInstance.mOCREngine.destroy();
            if (sInstance.mPenManager != null) sInstance.mPenManager.destroy();
            sInstance = null;
        }
        sInitialized.set(false);
        Log.i(TAG, "WritechSDK已释放所有资源");
    }

    /** 从JSON提取字段值 */
    private String extractJsonField(String json, String key) {
        if (json == null) return null;
        String search = "\"" + key + "\"";
        int idx = json.indexOf(search);
        if (idx < 0) return null;
        int start = json.indexOf("\"", idx + search.length() + 1) + 1;
        int end = json.indexOf("\"", start);
        return (start > 0 && end > start) ? json.substring(start, end) : null;
    }
}
