<?php

namespace App\Services;

use CodeIgniter\HTTP\IncomingRequest;
use App\Libraries\LogCollector;

abstract class CommonService
{
    private $_serviceDatas = [];
    private $_model = null;
    private $_classNames = [];
    protected ?IncomingRequest $request = null;
    protected function __construct(?IncomingRequest $_request = null)
    {
        $this->request = $_request;
    }
    abstract public function getModelClass(): mixed;
    abstract public function getEntityClass(): mixed;
    abstract public function getFormFields(): array;
    abstract public function getFilterFields(): array;
    abstract public function getBatchJobFields(): array;
    public function getIndexFields(): array
    {
        return $this->getFormFields();
    }
    public function getViewFields(): array
    {
        return $this->getModel()->getFields();
    }
    final public function __get($name)
    {
        if (!array_key_exists($name, $this->_serviceDatas)) {
            return null;
        }
        return $this->_serviceDatas[$name];
    }
    final public function __set($name, $value): void
    {
        $this->_serviceDatas[$name] = $value;
    }
    final public function getRequest(): IncomingRequest|null
    {
        return $this->request;
    }
    final protected function addClassName(string $className): void
    {
        $this->_classNames[] = $className;
    }
    final public function getClassName($delimeter = DIRECTORY_SEPARATOR): string
    {
        return implode($delimeter, $this->_classNames);
    }
    final public function getModel(): mixed
    {
        if (!$this->_model) {
            $this->_model = $this->getModelClass();
        }
        return $this->_model;
    }
    final public function getEntity(mixed $where, ?string $message = null): mixed
    {
        return is_array($where) ? $this->getModel()->where($where)->first() : $this->getModel()->find($where);
    }
    final public function getEntities(mixed $where = null, array $columns = ['*']): array
    {
        if ($where) {
            $this->getModel()->where($where);
        }
        $entitys = [];
        foreach ($this->getModel()->select(implode(',', $columns))->findAll() as $entity) {
            $entitys[$entity->getPK()] = $entity;
        }
        if (env('app.debug.index')) {
            echo $this->getModel()->getLastQuery() . "<BR>";
            // exit;
        }
        return $entitys;
    } // 
    //FieldForm관련용
    public function getFormFieldRule(string $action, string $field): string
    {
        if (is_array($field)) {
            throw new \Exception(__FUNCTION__ . "=> field가 array 입니다.\n" . var_export($field, true));
        }
        switch ($field) {
            default:
                $rule = $this->getModel()->getFormFieldRule($action, $field);
                break;
        }
        return $rule;
    }
    public function create(array $formDatas, mixed $entity = null): mixed
    {
        $entity = $this->getModel()->create($formDatas, $entity ?? $this->getEntityClass());
        LogCollector::info("[{$entity->getTitle()}]" . MESSAGES["CREATED"] . ":");
        return $entity;
    }
    public function modify(mixed $entity, array $formDatas): mixed
    {
        $entity = $this->getModel()->modify($entity, $formDatas);
        LogCollector::info("[{$entity->getTitle()}]" . MESSAGES["UPDATED"] . ":");
        return $entity;
    }
    final public function delete(mixed $entity): bool
    {
        $result = $this->getModel()->delete($entity->getPK());
        if (!$result) {
            $message = sprintf(
                "\n------%s SQL오류-----\n%s\n------------------------------\n",
                __FUNCTION__,
                $this->getModel()->getLastQuery()
            );
            LogCollector::error($message);
            return false;
        }
        LogCollector::info("[{$entity->getTitle()}]" . MESSAGES["DELETED"] . ":");
        return true;
    }
}
