/**
 * 自然写互动课堂PC端应用软件 V1.0
 *
 * cloud_api.ts - 云平台API通信层
 *
 * 功能说明：
 * - HTTP REST API封装（Axios）
 * - JWT Token管理与自动刷新
 * - 请求拦截器（签名/认证/日志）
 * - 响应拦截器（错误处理/重试）
 * - API类型定义
 * - 离线请求队列
 */

/* ======================== 类型定义 ======================== */

/** 统一响应格式 */
interface ApiResponse<T = any> {
    code: number;
    msg: string;
    data: T;
}

/** 分页参数 */
interface PageParams {
    page: number;
    size: number;
    sort?: string;
}

/** 分页响应 */
interface PageResult<T> {
    total: number;
    pages: number;
    current: number;
    records: T[];
}

/** 用户信息 */
interface UserInfo {
    userId: string;
    name: string;
    role: 'admin' | 'teacher' | 'student' | 'parent';
    phone: string;
    schoolId: string;
    schoolName: string;
    avatar: string;
}

/** 课堂信息 */
interface ClassroomInfo {
    classroomId: string;
    className: string;
    grade: string;
    teacherId: string;
    teacherName: string;
    studentCount: number;
    gatewayId: string;
}

/** 作业信息 */
interface AssignmentInfo {
    assignmentId: string;
    title: string;
    type: 'homework' | 'exam' | 'practice';
    classId: string;
    deadline: string;
    status: 'draft' | 'published' | 'closed';
    totalStudents: number;
    submittedCount: number;
}

/** 学情报告 */
interface LearningReport {
    studentId: string;
    studentName: string;
    subject: string;
    overallScore: number;
    writingScore: number;
    strokeOrderAccuracy: number;
    knowledgePoints: { name: string; mastery: number }[];
    trend: { date: string; score: number }[];
}

/** 认证令牌 */
interface AuthTokens {
    accessToken: string;
    refreshToken: string;
    expiresIn: number;    /* 有效期（秒） */
    tokenType: string;
}

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

/** API基础URL */
const API_BASE_URL = 'https://api.writech.cn';
/** 请求超时 */
const REQUEST_TIMEOUT = 30000;
/** Token刷新提前量（毫秒） */
const TOKEN_REFRESH_AHEAD = 5 * 60 * 1000;
/** 最大重试次数 */
const MAX_RETRIES = 3;

/* ======================== Token管理 ======================== */

/** 存储的Token信息 */
let currentTokens: AuthTokens | null = null;
/** Token过期时间戳 */
let tokenExpiresAt: number = 0;
/** 是否正在刷新Token */
let isRefreshing: boolean = false;
/** 等待Token刷新的请求队列 */
let refreshQueue: Array<(token: string) => void> = [];

/**
 * 保存认证令牌
 */
function saveTokens(tokens: AuthTokens): void {
    currentTokens = tokens;
    tokenExpiresAt = Date.now() + tokens.expiresIn * 1000;
    /* 持久化到electron-store */
    console.log(`[API] Token已保存, 有效期至 ${new Date(tokenExpiresAt).toLocaleString()}`);
}

/**
 * 获取当前Access Token
 * 如果即将过期则自动刷新
 */
async function getValidToken(): Promise<string> {
    if (!currentTokens) {
        throw new Error('未登录');
    }

    /* 检查是否需要刷新 */
    if (Date.now() + TOKEN_REFRESH_AHEAD > tokenExpiresAt) {
        if (!isRefreshing) {
            isRefreshing = true;
            try {
                const newTokens = await refreshToken(currentTokens.refreshToken);
                saveTokens(newTokens);
                /* 通知所有等待中的请求 */
                refreshQueue.forEach(resolve => resolve(newTokens.accessToken));
                refreshQueue = [];
            } finally {
                isRefreshing = false;
            }
        } else {
            /* 等待正在进行的刷新完成 */
            return new Promise<string>(resolve => {
                refreshQueue.push(resolve);
            });
        }
    }

    return currentTokens.accessToken;
}

/* ======================== HTTP请求封装 ======================== */

/**
 * 通用HTTP请求方法
 */
async function request<T>(
    method: 'GET' | 'POST' | 'PUT' | 'DELETE',
    path: string,
    data?: any,
    retryCount: number = 0
): Promise<ApiResponse<T>> {
    const url = `${API_BASE_URL}${path}`;
    const headers: Record<string, string> = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    };

    /* 添加认证头 */
    try {
        const token = await getValidToken();
        headers['Authorization'] = `Bearer ${token}`;
    } catch {
        /* 登录接口不需要Token */
    }

    /* 添加请求签名 */
    const timestamp = Date.now().toString();
    headers['X-Timestamp'] = timestamp;
    headers['X-Device-Id'] = getDeviceId();

    try {
        const response = await fetch(url, {
            method,
            headers,
            body: data ? JSON.stringify(data) : undefined,
            signal: AbortSignal.timeout(REQUEST_TIMEOUT)
        });

        const json: ApiResponse<T> = await response.json();

        /* 处理业务错误 */
        if (json.code === 401 && retryCount < 1) {
            /* Token过期，尝试刷新后重试 */
            console.log('[API] Token过期, 刷新后重试');
            if (currentTokens) {
                const newTokens = await refreshToken(currentTokens.refreshToken);
                saveTokens(newTokens);
                return request<T>(method, path, data, retryCount + 1);
            }
        }

        if (json.code !== 200 && json.code !== 0) {
            console.warn(`[API] 业务错误: ${method} ${path} code=${json.code} msg=${json.msg}`);
        }

        return json;
    } catch (error: any) {
        console.error(`[API] 请求失败: ${method} ${path}`, error.message);

        /* 网络错误重试 */
        if (retryCount < MAX_RETRIES && isNetworkError(error)) {
            const delay = Math.pow(2, retryCount) * 1000;
            console.log(`[API] ${delay}ms后重试 (${retryCount + 1}/${MAX_RETRIES})`);
            await sleep(delay);
            return request<T>(method, path, data, retryCount + 1);
        }

        return { code: -1, msg: error.message || '网络错误', data: null as any };
    }
}

function isNetworkError(error: any): boolean {
    return error.name === 'TypeError' || error.name === 'AbortError';
}

function sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function getDeviceId(): string {
    return 'PC-' + (typeof window !== 'undefined' ?
        navigator.userAgent.slice(-8) : 'unknown');
}

/* ======================== API方法 ======================== */

/** 用户登录 */
async function login(username: string, password: string): Promise<ApiResponse<AuthTokens>> {
    const result = await request<AuthTokens>('POST', '/api/v1/auth/login', {
        username, password, device_type: 'pc'
    });
    if (result.code === 200 && result.data) {
        saveTokens(result.data);
    }
    return result;
}

/** 刷新Token */
async function refreshToken(token: string): Promise<AuthTokens> {
    const resp = await fetch(`${API_BASE_URL}/api/v1/auth/refresh`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ refresh_token: token })
    });
    const json: ApiResponse<AuthTokens> = await resp.json();
    if (json.code !== 200 || !json.data) {
        throw new Error('Token刷新失败');
    }
    return json.data;
}

/** 获取当前用户信息 */
async function getUserInfo(): Promise<ApiResponse<UserInfo>> {
    return request<UserInfo>('GET', '/api/v1/user/me');
}

/** 获取班级列表 */
async function getClassrooms(): Promise<ApiResponse<ClassroomInfo[]>> {
    return request<ClassroomInfo[]>('GET', '/api/v1/classroom/list');
}

/** 获取作业列表 */
async function getAssignments(classId: string, params: PageParams): Promise<ApiResponse<PageResult<AssignmentInfo>>> {
    return request<PageResult<AssignmentInfo>>('GET',
        `/api/v1/assignment/list?class_id=${classId}&page=${params.page}&size=${params.size}`);
}

/** 发布作业 */
async function publishAssignment(assignment: Partial<AssignmentInfo>): Promise<ApiResponse<{ assignmentId: string }>> {
    return request<{ assignmentId: string }>('POST', '/api/v1/assignment/publish', assignment);
}

/** 上传笔迹数据 */
async function uploadStrokeData(assignmentId: string, studentId: string,
                                  strokeData: any[]): Promise<ApiResponse<void>> {
    return request<void>('POST', '/api/v1/stroke/upload', {
        assignment_id: assignmentId,
        student_id: studentId,
        strokes: strokeData
    });
}

/** 获取AI批改结果 */
async function getGradingResult(assignmentId: string): Promise<ApiResponse<any>> {
    return request<any>('GET', `/api/v1/result/${assignmentId}`);
}

/** 获取学情报告 */
async function getLearningReport(studentId: string): Promise<ApiResponse<LearningReport>> {
    return request<LearningReport>('GET', `/api/v1/report/student/${studentId}`);
}

/** 下载课件资源 */
async function getResourceDownloadUrl(resourceId: string): Promise<ApiResponse<{ url: string }>> {
    return request<{ url: string }>('GET', `/api/v1/resource/download/${resourceId}`);
}

/** 退出登录 */
async function logout(): Promise<void> {
    await request<void>('POST', '/api/v1/auth/logout');
    currentTokens = null;
    tokenExpiresAt = 0;
    console.log('[API] 已退出登录');
}

/* ======================== 导出 ======================== */

export {
    login, logout, getUserInfo, getClassrooms, getAssignments,
    publishAssignment, uploadStrokeData, getGradingResult,
    getLearningReport, getResourceDownloadUrl, saveTokens
};
export type {
    ApiResponse, UserInfo, ClassroomInfo, AssignmentInfo,
    LearningReport, AuthTokens, PageParams, PageResult
};
