<?php

namespace App\Models;

use CodeIgniter\Model;

class BaseModel extends Model
{
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $updatedField = 'updated_at';
    protected $deletedField = 'deleted_at';

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

    protected function initialize()
    {
        if (empty($this->returnType)) {
            $this->returnType = 'array';
        }
    }

    public function findAll(?int $limit = null, int $offset = 0)
    {
        $rows = parent::findAll($limit, $offset);
        return $this->snakeToCamelRecursive($rows);
    }

    public function find($id = null)
    {
        $row = parent::find($id);
        if ($row) {
            return $this->snakeToCamel($row);
        }
        return null;
    }

    public function first()
    {
        $row = parent::first();
        if ($row) {
            return $this->snakeToCamel($row);
        }
        return null;
    }

    protected function snakeToCamel(array $row): array
    {
        $converted = [];
        foreach ($row as $key => $value) {
            $camelKey = $this->snakeToCamelKey($key);
            $converted[$camelKey] = $value;
        }
        return $converted;
    }

    protected function snakeToCamelRecursive($data)
    {
        if (is_array($data)) {
            if (isset($data[0]) || empty($data)) {
                return array_map([$this, 'snakeToCamelRecursive'], $data);
            }
            return $this->snakeToCamel($data);
        }
        return $data;
    }

    protected function snakeToCamelKey(string $key): string
    {
        $parts = explode('_', $key);
        $camel = array_map(function ($part, $index) {
            if ($index === 0) {
                return $part;
            }
            return ucfirst($part);
        }, $parts, array_keys($parts));
        return implode('', $camel);
    }

    public function insert($data = null, bool $returnID = true)
    {
        $snakeData = $this->camelToSnakeArray($data);
        return parent::insert($snakeData, $returnID);
    }

    public function update($id = null, $row = null): bool
    {
        $snakeData = $this->camelToSnakeArray($row);
        return parent::update($id, $snakeData);
    }

    protected function camelToSnakeArray(array $data): array
    {
        $converted = [];
        foreach ($data as $key => $value) {
            $snakeKey = $this->camelToSnakeKey($key);
            $converted[$snakeKey] = $value;
        }
        return $converted;
    }

    protected function camelToSnakeKey(string $key): string
    {
        $pattern = '/([a-z])([A-Z])/';
        $snake = preg_replace($pattern, '$1_$2', $key);
        return strtolower($snake);
    }
}
