package com.ruoyi.course.common;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 统一响应结果
 *
 * @param <T> 响应数据类型
 */
@Data
@NoArgsConstructor
@Schema(description = "统一响应结果")
public class R<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @Schema(description = "状态码", example = "200")
    private Integer code;

    @Schema(description = "返回消息", example = "操作成功")
    private String msg;

    @Schema(description = "返回数据")
    private T data;

    @Schema(description = "时间戳", example = "1702512000000")
    private Long timestamp;

    /**
     * 成功状态码
     */
    public static final Integer SUCCESS_CODE = 200;
    
    /**
     * 失败状态码
     */
    public static final Integer ERROR_CODE = 500;
    
    /**
     * 未授权状态码
     */
    public static final Integer UNAUTHORIZED_CODE = 401;
    
    /**
     * 禁止访问状态码
     */
    public static final Integer FORBIDDEN_CODE = 403;
    
    /**
     * 资源不存在状态码
     */
    public static final Integer NOT_FOUND_CODE = 404;
    
    /**
     * 参数错误状态码
     */
    public static final Integer PARAM_ERROR_CODE = 400;
    
    /**
     * 业务异常状态码
     */
    public static final Integer BUSINESS_ERROR_CODE = 600;

    /**
     * 构造函数
     *
     * @param code 状态码
     * @param msg  消息
     * @param data 数据
     */
    public R(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        this.timestamp = System.currentTimeMillis();
    }

    /**
     * 成功响应（无数据）
     *
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> ok() {
        return ok(null, "操作成功");
    }

    /**
     * 成功响应（带数据）
     *
     * @param data 数据
     * @param <T>  数据类型
     * @return R
     */
    public static <T> R<T> ok(T data) {
        return ok(data, "操作成功");
    }

    /**
     * 成功响应（带数据和消息）
     *
     * @param data 数据
     * @param msg  消息
     * @param <T>  数据类型
     * @return R
     */
    public static <T> R<T> ok(T data, String msg) {
        return new R<>(SUCCESS_CODE, msg, data);
    }

    /**
     * 失败响应（默认消息）
     *
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> error() {
        return error("操作失败");
    }

    /**
     * 失败响应（自定义消息）
     *
     * @param msg 错误消息
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> error(String msg) {
        return error(ERROR_CODE, msg);
    }

    /**
     * 失败响应（自定义状态码和消息）
     *
     * @param code 状态码
     * @param msg  错误消息
     * @param <T>  数据类型
     * @return R
     */
    public static <T> R<T> error(Integer code, String msg) {
        return error(code, msg, null);
    }

    /**
     * 失败响应（完整参数）
     *
     * @param code 状态码
     * @param msg  错误消息
     * @param data 数据
     * @param <T>  数据类型
     * @return R
     */
    public static <T> R<T> error(Integer code, String msg, T data) {
        return new R<>(code, msg, data);
    }

    /**
     * 参数错误响应
     *
     * @param msg 错误消息
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> paramError(String msg) {
        return error(PARAM_ERROR_CODE, msg);
    }

    /**
     * 未授权响应
     *
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> unauthorized() {
        return unauthorized("未授权，请先登录");
    }

    /**
     * 未授权响应（自定义消息）
     *
     * @param msg 错误消息
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> unauthorized(String msg) {
        return error(UNAUTHORIZED_CODE, msg);
    }

    /**
     * 禁止访问响应
     *
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> forbidden() {
        return forbidden("禁止访问");
    }

    /**
     * 禁止访问响应（自定义消息）
     *
     * @param msg 错误消息
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> forbidden(String msg) {
        return error(FORBIDDEN_CODE, msg);
    }

    /**
     * 资源不存在响应
     *
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> notFound() {
        return notFound("资源不存在");
    }

    /**
     * 资源不存在响应（自定义消息）
     *
     * @param msg 错误消息
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> notFound(String msg) {
        return error(NOT_FOUND_CODE, msg);
    }

    /**
     * 业务异常响应
     *
     * @param msg 错误消息
     * @param <T> 数据类型
     * @return R
     */
    public static <T> R<T> businessError(String msg) {
        return error(BUSINESS_ERROR_CODE, msg);
    }

    /**
     * 判断是否成功
     *
     * @return 是否成功
     */
    public boolean isSuccess() {
        return SUCCESS_CODE.equals(this.code);
    }

    /**
     * 判断是否失败
     *
     * @return 是否失败
     */
    public boolean isError() {
        return !isSuccess();
    }

    /**
     * 获取数据（带安全检查）
     *
     * @return 数据
     * @throws IllegalStateException 如果响应失败
     */
    public T getDataOrThrow() {
        if (isError()) {
            throw new IllegalStateException(msg);
        }
        return data;
    }

    /**
     * 链式设置数据
     *
     * @param data 数据
     * @return R
     */
    public R<T> setData(T data) {
        this.data = data;
        return this;
    }

    /**
     * 链式设置消息
     *
     * @param msg 消息
     * @return R
     */
    public R<T> setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    /**
     * 链式设置状态码
     *
     * @param code 状态码
     * @return R
     */
    public R<T> setCode(Integer code) {
        this.code = code;
        return this;
    }
}