<?php

declare(strict_types=1);

namespace App\Models;

use App\Core\Model;
use PDO;

/**
 * Setting Model
 *
 * Handles key-value application settings data retrieval and persistence.
 * Uses `setting_key` / `setting_value` columns (as defined in schema.sql).
 */
class Setting extends Model
{
    /**
     * The database table associated with the model.
     */
    protected string $table = 'settings';

    /**
     * Get a setting value by its key.
     *
     * @param string $key The setting key to look up
     * @return string|null The setting value, or null if not found
     */
    public function get(string $key): ?string
    {
        try {
            $sql = sprintf(
                'SELECT `setting_value` FROM `%s` WHERE `setting_key` = :key LIMIT 1',
                $this->table
            );
            $stmt = $this->db->prepare($sql);
            $stmt->execute([':key' => $key]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result !== false ? $result['setting_value'] : null;
        } catch (\Throwable $e) {
            error_log('Setting::get error for key "' . $key . '": ' . $e->getMessage());
            return null;
        }
    }

    /**
     * Set (update) a setting value by its key.
     *
     * Uses INSERT ... ON DUPLICATE KEY UPDATE for upsert.
     *
     * @param string $key The setting key to update
     * @param string $value The new value to set
     * @return bool True if the operation succeeded
     */
    public function set(string $key, string $value): bool
    {
        try {
            $sql = sprintf(
                'INSERT INTO `%s` (`setting_key`, `setting_value`) VALUES (:key, :value)
                 ON DUPLICATE KEY UPDATE `setting_value` = :value2',
                $this->table
            );
            $stmt = $this->db->prepare($sql);
            $stmt->execute([':key' => $key, ':value' => $value, ':value2' => $value]);
            return $stmt->rowCount() >= 0; // 0 on no change, 1 on insert, 2 on update
        } catch (\Throwable $e) {
            error_log('Setting::set error for key "' . $key . '": ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Get all settings as key-value pairs.
     *
     * @return array<string, string> Associative array of key => value
     */
    public function getAll(): array
    {
        try {
            // Try setting_key / setting_value first (new schema)
            $sql = sprintf(
                'SELECT `setting_key`, `setting_value` FROM `%s` WHERE `setting_key` IS NOT NULL AND `setting_key` != \'\'',
                $this->table
            );
            $stmt = $this->db->prepare($sql);
            $stmt->execute();
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
            $settings = [];
            foreach ($rows as $row) {
                $settings[$row['setting_key']] = $row['setting_value'];
            }

            // Also check key_name / value (old schema) for any keys not in new schema
            $sql2 = sprintf(
                'SELECT `key_name`, `value` FROM `%s` WHERE `key_name` IS NOT NULL AND `key_name` != \'\'',
                $this->table
            );
            $stmt2 = $this->db->prepare($sql2);
            $stmt2->execute();
            $rows2 = $stmt2->fetchAll(PDO::FETCH_ASSOC) ?: [];
            foreach ($rows2 as $row) {
                // Only use old schema value if new schema doesn't have it
                if (!isset($settings[$row['key_name']]) || $settings[$row['key_name']] === '') {
                    $settings[$row['key_name']] = $row['value'];
                }
            }

            return $settings;
        } catch (\Throwable $e) {
            error_log('Setting::getAll error: ' . $e->getMessage());
            return [];
        }
    }
}
