<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;

class CommentMeta extends Model
{
    protected $table = 'tb_comment_meta';
    protected $primaryKey = 'comment_id';

    public $keyType = 'int';
    public $incrementing = false;
    public $timestamps = false;

    public string $metaKey = 'key';
    public string $metaValue = 'value';
    public string $cachePrefix = 'comment-meta-';
    public int $cacheTime = CACHE_EXPIRE_TIME;

    public function __set($name, $value)
    {
        $this->{$name} = $value;
    }

    public function __get($name)
    {
        return ($this->{$name} ?? null);
    }

    /*
     * 댓글 설정 정보 조회
     */
    public function data($commentID = 0): CommentMeta|null
    {
        $res = $this->where($this->primaryKey, $commentID)->get();
        if ($res->count() > 0) {
            foreach ($res as $val) {
                $this->{$val[$this->metaKey]} = $val[$this->metaValue];
            }
            return $this;
        }
        return null;
    }

    /*
     * 댓글 설정 값 조회
     */
    public function getAllMeta($commentID = 0): ?CommentMeta
    {
        $cacheName = ($this->cachePrefix . $commentID);
        if (!$ret = Cache::get($cacheName)) {
            $ret = $this->data($commentID);
            Cache::put($cacheName, (object)$ret, $this->cacheTime);
        }
        return $ret;
    }

    /*
     * 저장
     */
    public function save($commentID = 0, $saveData = []): void
    {
        if ($saveData && is_array($saveData)) {
            foreach ($saveData as $column => $value) {
                $this->_metaUpdate($commentID, $column, $value);
            }
        }
        Cache::forget($this->cachePrefix . $commentID);
        $this->getAllMeta($commentID);
    }

    /*
     * 삭제
     */
    public function deleteMeta($commentID = 0): void
    {
        $this->where($this->primaryKey, $commentID)->delete();
        Cache::forget($this->cachePrefix . $commentID);
    }

    /*
     * 조회
     */
    public function item($column = '', $default = null): mixed
    {
        if (empty($column)) {
            return false;
        }

        $return = $default;
        if (property_exists($this, $column)) {
            $return = $this->{$column};
        }

        return $return;
    }

    /*
     * 등록/수정 처리
     */
    private function _metaUpdate($commentID = 0, $column = '', $value = null): mixed
    {
        if(!$commentID) {
            return false;
        }

        $column = trim($column);
        if (empty($column)) {
            return false;
        }

        $items = $this->data($commentID);
        if($items) {
            $oldValue = property_exists($items, $column) ? $items->{$column} : false;
        }else{
            $oldValue = false;
        }

        if (empty($value) && $value != 0) {
            $value = '';
        }

        if ($value === $oldValue) {
            return false;
        }

        if (false === $oldValue) {
            return $this->_addMeta($commentID, $column, $value); // 새로 추가
        }

        return $this->_updateMeta($commentID, $column, $value); // 수정
    }

    /*
     * 등록
     */
    private function _addMeta($commentID = 0, $column = '', $value = ''): mixed
    {
        if(!$commentID) {
            return false;
        }

        $column = trim($column);
        if (empty($column)) {
            return false;
        }

        $insertData = [
            $this->primaryKey => $commentID,
            $this->metaKey => $column,
            $this->metaValue => $value
        ];

        return $this->insert($insertData);
    }

    /*
     * 수정
     */
    private function _updateMeta($commentID = 0, $column = '', $value = ''): mixed
    {
        if(!$commentID) {
            return false;
        }

        $column = trim($column);
        if (empty($column)) {
            return false;
        }

        $updateData = [
            $this->metaValue => $value
        ];

        return $this->where($this->primaryKey, $commentID)->where($this->metaKey, $column)->update($updateData);
    }
}
