<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\basic\think;

use support\think\Model;
use think\model\concern\SoftDelete;
use plugin\saiadmin\basic\contracts\ModelInterface;

/**
 * ThinkORM 模型基类
 *
 * 全局策略：所有删除一律为硬删除（物理删除）。
 *  - 保留 SoftDelete trait 仅是为了兼容历史字段（如 delete_time）与查询作用域，
 *    实际删除方法（delete/destroy）均通过 trait 别名重写为强制 force=true。
 *  - 项目中不使用 withTrashed/onlyTrashed/restore() 等软删除恢复接口。
 */
class BaseModel extends Model implements ModelInterface
{
    use SoftDelete {
        delete as protected softDeleteCascadeOriginal;
        destroy as protected softDeleteDestroyOriginal;
    }

    /**
     * 删除时间字段
     * @var string
     */
    protected $deleteTime = 'delete_time';

    /**
     * 创建时间字段
     * @var string
     */
    protected $createTime = 'create_time';

    /**
     * 更新时间字段
     * @var string
     */
    protected $updateTime = 'update_time';

    /**
     * 自动写入时间戳（创建时写 create_time，更新时写 update_time）
     * @var bool
     */
    protected $autoWriteTimestamp = true;

    /**
     * 隐藏字段
     * @var array
     */
    protected $hidden = ['delete_time'];

    /**
     * 只读字段
     * @var array
     */
    protected $readonly = ['created_by', 'create_time'];

    /**
     * 获取表名
     * @return string
     */
    public function getTableName(): string
    {
        return $this->getTable();
    }

    /**
     * 获取主键名
     * @return string
     */
    public function getPrimaryKeyName(): string
    {
        return $this->getPk();
    }

    /**
     * 添加时间范围搜索
     * @param $query
     * @param $value
     */
    public function searchCreateTimeAttr($query, $value)
    {
        if (is_array($value)) {
            $query->whereBetween('create_time', $value);
        } else {
            $query->where('create_time', '=', $value);
        }
    }

    /**
     * 更新时间范围搜索
     * @param mixed $query
     * @param mixed $value
     */
    public function searchUpdateTimeAttr($query, $value)
    {
        if (is_array($value)) {
            $query->whereBetween('update_time', $value);
        } else {
            $query->where('update_time', '=', $value);
        }
    }

    /**
     * 删除记录（静态入口）：一律强制硬删除（物理删除）。
     * @param mixed $data 主键、闭包或条件
     * @param bool  $force 兼容签名，内部一律按 true 处理
     */
    public static function destroy($data, bool $force = true): bool
    {
        return static::softDeleteDestroyOriginal($data, true);
    }

    /**
     * 删除记录（实例方法）：一律强制硬删除。
     */
    public function delete(): bool
    {
        $this->force(true);
        return $this->softDeleteCascadeOriginal();
    }

    /**
     * 新增前事件：自动写入 create_time，有后台登录信息时写入 created_by
     * @param Model $model
     * @return void
     */
    public static function onBeforeInsert($model): void
    {
        try {
            $createTime = $model->createTime ?? 'create_time';
            if ($createTime && !$model->getData($createTime)) {
                $model->set($createTime, date('Y-m-d H:i:s'));
            }
        } catch (\Throwable $e) {
        }
        try {
            if (function_exists('getCurrentInfo')) {
                $info = getCurrentInfo();
                if (!empty($info['id'])) {
                    $model->setAttr('created_by', $info['id']);
                }
            }
        } catch (\Throwable $e) {
        }
    }

    /**
     * 写入前事件：更新时自动写入 update_time，有后台登录信息时写入 updated_by
     * @param Model $model
     * @return void
     */
    public static function onBeforeWrite($model): void
    {
        try {
            if ($model->isExists()) {
                $updateTime = $model->updateTime ?? 'update_time';
                if ($updateTime) {
                    $model->set($updateTime, date('Y-m-d H:i:s'));
                }
            }
        } catch (\Throwable $e) {
        }
        try {
            if (function_exists('getCurrentInfo')) {
                $info = getCurrentInfo();
                if (!empty($info['id'])) {
                    $model->setAttr('updated_by', $info['id']);
                }
            }
        } catch (\Throwable $e) {
        }
    }
}
