<?php
declare(strict_types=1);

namespace App;

use App\Avatar\Lorelei;

final class ProfileSettings
{
    private bool $schemaEnsured = false;
    private array $columnCache = [];

    public function __construct(private \PDO $pdo)
    {
    }

    public function ensureSchema(): void
    {
        if ($this->schemaEnsured) {
            return;
        }

        if (!$this->hasColumn('user_profiles', 'location_tracking_preference')) {
            $this->pdo->exec(
                "ALTER TABLE user_profiles
                 ADD COLUMN location_tracking_preference ENUM('disabled','prompt','enabled')
                 NOT NULL DEFAULT 'prompt'
                 AFTER lng"
            );
            $this->columnCache['user_profiles.location_tracking_preference'] = true;
        }

        $avatarColumns = [
            'avatar_preset' => "ALTER TABLE user_profiles ADD COLUMN avatar_preset VARCHAR(64) NOT NULL DEFAULT 'papa-kind-treff' AFTER location_tracking_preference",
            'avatar_lorelei_eyes_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_eyes_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_preset",
            'avatar_lorelei_eyebrows_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_eyebrows_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_eyes_variant",
            'avatar_lorelei_mouth_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_mouth_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_eyebrows_variant",
            'avatar_lorelei_glasses_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_glasses_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_mouth_variant",
            'avatar_lorelei_hair_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_hair_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_glasses_variant",
            'avatar_lorelei_beard_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_beard_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_hair_variant",
            'avatar_lorelei_earrings_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_earrings_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_beard_variant",
        ];
        foreach ($avatarColumns as $column => $sql) {
            if (!$this->hasColumn('user_profiles', $column)) {
                $this->pdo->exec($sql);
                $this->columnCache['user_profiles.' . $column] = true;
            }
        }

        $this->schemaEnsured = true;
    }

    public function getLocationTrackingPreference(int $userId): string
    {
        if ($userId <= 0) {
            return 'prompt';
        }

        $this->ensureSchema();
        $stmt = $this->pdo->prepare('SELECT location_tracking_preference FROM user_profiles WHERE user_id = :id LIMIT 1');
        $stmt->execute(['id' => $userId]);
        $value = (string)($stmt->fetchColumn() ?: 'prompt');
        return in_array($value, ['disabled', 'prompt', 'enabled'], true) ? $value : 'prompt';
    }

    public function updateLocationTrackingPreference(int $userId, string $preference): void
    {
        if ($userId <= 0) {
            return;
        }

        $this->ensureSchema();
        $preference = in_array($preference, ['disabled', 'prompt', 'enabled'], true) ? $preference : 'prompt';
        $stmt = $this->pdo->prepare('UPDATE user_profiles SET location_tracking_preference = :pref, updated_at = NOW() WHERE user_id = :id');
        $stmt->execute([
            'pref' => $preference,
            'id' => $userId,
        ]);
    }

    public function updateAvatar(int $userId, array $avatarConfig): void
    {
        if ($userId <= 0) {
            return;
        }

        $this->ensureSchema();
        $avatar = Lorelei::normalize($avatarConfig);
        $stmt = $this->pdo->prepare(
            'UPDATE user_profiles
             SET avatar_preset = :preset,
                 avatar_lorelei_eyes_variant = :eyesVariant,
                 avatar_lorelei_eyebrows_variant = :eyebrowsVariant,
                 avatar_lorelei_mouth_variant = :mouthVariant,
                 avatar_lorelei_glasses_variant = :glassesVariant,
                 avatar_lorelei_hair_variant = :hairVariant,
                 avatar_lorelei_beard_variant = :beardVariant,
                 avatar_lorelei_earrings_variant = :earringsVariant,
                 updated_at = NOW()
             WHERE user_id = :id'
        );
        $stmt->execute([
            'preset' => $avatar['avatar_preset'],
            'eyesVariant' => $avatar['avatar_lorelei_eyes_variant'],
            'eyebrowsVariant' => $avatar['avatar_lorelei_eyebrows_variant'],
            'mouthVariant' => $avatar['avatar_lorelei_mouth_variant'],
            'glassesVariant' => $avatar['avatar_lorelei_glasses_variant'],
            'hairVariant' => $avatar['avatar_lorelei_hair_variant'],
            'beardVariant' => $avatar['avatar_lorelei_beard_variant'],
            'earringsVariant' => $avatar['avatar_lorelei_earrings_variant'],
            'id' => $userId,
        ]);
    }

    private function hasColumn(string $table, string $column): bool
    {
        $cacheKey = $table . '.' . $column;
        if (array_key_exists($cacheKey, $this->columnCache)) {
            return $this->columnCache[$cacheKey];
        }

        $stmt = $this->pdo->prepare("
            SELECT COUNT(*)
            FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_NAME = :tableName
              AND COLUMN_NAME = :columnName
        ");
        $stmt->execute([
            'tableName' => $table,
            'columnName' => $column,
        ]);

        return $this->columnCache[$cacheKey] = ((int)$stmt->fetchColumn() > 0);
    }
}
