<?php

namespace App\Models;

use CodeIgniter\Model;

abstract class CommonModel extends Model
{
    protected $table = '';
    protected $primaryKey = '';
    protected $useAutoIncrement = true;

    protected $useSoftDeletes = false;
    protected $protectFields = true;
    protected $allowedFields = [];

    protected bool $allowEmptyInserts = false;
    protected bool $updateOnlyChanged = true;

    protected $useEmptyStringIfNull = false; // NULL도 DB로 보내기

    protected array $casts = [];
    protected array $castHandlers = [];

    // Dates
    protected $useTimestamps = false;
    protected $dateFormat = 'datetime';
    protected $createdField = 'created_at';
    protected $updatedField = 'updated_at';
    protected $deletedField = 'deleted_at';

    // Validation
    protected $validationRules = [];
    protected $validationMessages = [];
    protected $skipValidation = false;
    protected $cleanValidationRules = true;

    // Callbacks
    protected $allowCallbacks = true;

    /**
     * ✅ 변경:
     * - beforeInsert: emptyStringToNull + applyDbDefaultsOnInsert
     * - beforeUpdate: emptyStringToNull만 유지 (UPDATE에서는 DB default를 쓰려고 컬럼을 빼면 위험/의도와 다름)
     */
    protected $beforeInsert = ['emptyStringToNull', 'applyDbDefaultsOnInsert'];
    protected $afterInsert = [];
    protected $beforeUpdate = ['emptyStringToNull'];
    protected $afterUpdate = [];

    protected $beforeFind = [];
    protected $afterFind = [];
    protected $beforeDelete = [];
    protected $afterDelete = [];

    /**
     * 빈 문자열을 NULL로 바꾸고 싶은 필드들 (모델별 override)
     * - 예: FK, 숫자필드 등
     */
    protected array $nullableFields = [];

    /**
     * ✅ 추가: DB DEFAULT를 “사용하고 싶은” 필드들 (모델별 override)
     * - INSERT 시 값이 null/''/공백이면 payload에서 제거(unset)해서 DB default가 동작하게 함
     * - UPDATE에서는 적용하지 않음 (비우기 가능)
     */
    protected array $allowedDbDefaultFields = [];

    /**
     * 공백문자열도 빈값으로 취급할지 정책
     */
    protected bool $dbDefaultTreatWhitespaceAsEmpty = true;

    protected function __construct()
    {
        parent::__construct();
    }

    final public function getTable(): string
    {
        return constant("static::TABLE");
    }

    final public function getPKField(): string
    {
        return constant("static::PK");
    }

    final public function getTitleField(): string
    {
        return constant("static::TITLE");
    }

    final public function useAutoIncrement(): bool
    {
        return $this->useAutoIncrement;
    }

    final public function getAllowedFields(): array
    {
        return $this->allowedFields;
    }

    /**
     * 기존 로직 유지:
     * - nullableFields에 지정된 필드만 '' => null 로 변환
     */
    protected function emptyStringToNull(array $data): array
    {
        if (!isset($data['data']) || !is_array($data['data'])) {
            return $data;
        }

        if (empty($this->nullableFields)) {
            return $data;
        }

        foreach ($this->nullableFields as $field) {
            if (!array_key_exists($field, $data['data'])) {
                continue;
            }

            $v = $data['data'][$field];

            if (is_string($v)) {
                $v = trim($v);
                $data['data'][$field] = ($v === '') ? null : $v;
            } else {
                if ($v === '') {
                    $data['data'][$field] = null;
                }
            }
        }

        return $data;
    }

    /**
     * ✅ 추가 로직:
     * INSERT 때만 DB DEFAULT를 쓰고 싶은 필드를 payload에서 제거(unset)
     *
     * - allowedDbDefaultFields에 있는 필드만 처리
     * - 값이 null / '' / (옵션)공백문자열 이면 unset
     * - 이렇게 하면 INSERT 쿼리에서 컬럼 자체가 빠져서 DB default가 적용됨
     */
    protected function applyDbDefaultsOnInsert(array $data): array
    {
        if (!isset($data['data']) || !is_array($data['data'])) {
            return $data;
        }

        if (empty($this->allowedDbDefaultFields)) {
            return $data;
        }

        foreach ($this->allowedDbDefaultFields as $field) {
            if (!array_key_exists($field, $data['data'])) {
                continue;
            }

            $v = $data['data'][$field];

            // null이면 제거
            if ($v === null) {
                unset($data['data'][$field]);
                continue;
            }

            // 문자열이면 '' 또는 (옵션)trim 후 '' 이면 제거
            if (is_string($v)) {
                if ($v === '') {
                    unset($data['data'][$field]);
                    continue;
                }
                if ($this->dbDefaultTreatWhitespaceAsEmpty && trim($v) === '') {
                    unset($data['data'][$field]);
                    continue;
                }
            }
        }

        return $data;
    }
}
