<?php

namespace Kylin\Core\Exceptions;

use Kylin\Core\Contracts\KylinErrorCodeInterface;
use RuntimeException;

/**
 * Kylin 异常基类
 *
 * 所有业务异常均继承此类，统一使用错误码枚举体系。
 * 通过 ApiExceptionHandler 自动转换为标准 JSON 响应格式。
 *
 * 特性：
 *  - 绑定 KylinErrorCodeInterface 枚举，自动携带错误码和 HTTP 状态码
 *  - 支持自定义消息覆盖枚举默认消息
 *  - 提供 from() 静态工厂方法快捷创建异常
 */
abstract class KylinException extends RuntimeException
{
    /** 关联的错误码枚举 */
    protected KylinErrorCodeInterface $errorCode;

    /**
     * @param  KylinErrorCodeInterface  $errorCode  错误码枚举
     * @param  string|null              $message    自定义消息（null 则使用枚举默认消息）
     * @param  int                      $code       PHP 异常码（通常为 0）
     * @param  \Throwable|null          $previous   前一个异常（用于异常链）
     */
    public function __construct(
        KylinErrorCodeInterface $errorCode,
        ?string $message = null,
        int $code = 0,
        ?\Throwable $previous = null,
    ) {
        $this->errorCode = $errorCode;
        parent::__construct(
            $message ?? $errorCode->message(),
            $code,
            $previous
        );
    }

    /**
     * 静态工厂方法，快捷创建异常
     *
     * @param  KylinErrorCodeInterface  $errorCode  错误码枚举
     * @param  string|null              $message    自定义消息
     * @return static
     */
    public static function from(KylinErrorCodeInterface $errorCode, ?string $message = null): static
    {
        return new static($errorCode, $message);
    }

    /**
     * 获取关联的错误码枚举
     */
    public function errorCode(): KylinErrorCodeInterface
    {
        return $this->errorCode;
    }

    /**
     * 获取 HTTP 状态码
     *
     * 用于 ApiExceptionHandler 设置响应 HTTP 状态码。
     */
    public function getHttpStatusCode(): int
    {
        return $this->errorCode->httpStatus();
    }
}
