<?php

namespace xmvc;

use Exception;
use xmvc\DB;
use xmvc\Sqler;

/**
 * Model 基类
 */
abstract class BaseModel
{
    /** 默认数据库连接 xmvc\DB */
    protected DB|null $db = null;
    /** 默认查询对象 xmvc\Sqler */
    protected Sqler|null $query = null;

    /**
     * 构造
     *
     */
    public function __construct(array $attributes = [])
    {
        foreach ($attributes as $key => $value) {
            $this->$key = $value;
        }
    }


    public function validate()
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public function save()
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public function delete()
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public static function get($id)
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public function toArray()
    {
        return get_object_vars($this);
    }

    public static function fromArray($data)
    {
        return new static($data);
    }

    /**
     * 创建或获取数据库连接
     *
     * @param string $dbKey 数据库的配置键, 如果传 null 则不会创建数据库连接
     * @return DB
     */
    protected function getDb($dbKey = 'main'): DB
    {
        $this->db = new DB($dbKey);
        $this->query = $this->db->newSqler();
        return $this->db;
    }

    protected function newSqler(): Sqler
    {
        return $this->db->newSqler();
    }

    public static function all()
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public static function filter(array $conditions = [])
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public function trackChanges()
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public function softDelete()
    {
        throw new Exception("Subclasses should implement this method.");
    }

    public function cache()
    {
        throw new Exception("Subclasses should implement this method.");
    }
}
