<?php
/**
 * DisciplineSettingsService.php
 * 
 * Serwis walidacji, transformacji i biznesowej logiki dla ustawień dyscyplin
 * Rozdziela logikę biznesową od modelu i kontrolera
 */

class DisciplineSettingsService
{
    private $model;

    public function __construct(DisciplineSettingsModel $model)
    {
        $this->model = $model;
    }

    /**
     * Pobiera ustawienia w formacie API
     * Separuje reguły gry od personalizacji
     * 
     * @param string $discipline Nazwa dyscypliny
     * @return array Ustawienia z metadanymi
     */
    public function getSettingsForAPI($discipline)
    {
        // Waliduj nazwę dyscypliny
        $this->validateDisciplineName($discipline);

        $settings = $this->model->getSettings($discipline);

        if (!$settings) {
            // Jeśli nie istnieją, zwróć defaults
            return [
                'discipline' => $discipline,
                'settingsVersion' => 1,
                'rules' => [
                    'pointsToWin' => DisciplineSettingsModel::getDefaults($discipline)['pointsToWin'],
                    'setsToWin' => DisciplineSettingsModel::getDefaults($discipline)['setsToWin'],
                    'serveRotation' => DisciplineSettingsModel::getDefaults($discipline)['serveRotation'],
                    'specialRules' => DisciplineSettingsModel::getDefaults($discipline)['specialRules'] ?? null
                ],
                'customization' => DisciplineSettingsModel::getDefaults($discipline)['customization'] ?? [],
                'status' => 'default'
            ];
        }

        return [
            'discipline' => $settings['discipline'],
            'settingsVersion' => (int)$settings['settingsVersion'],
            'rules' => [
                'pointsToWin' => (int)$settings['pointsToWin'],
                'setsToWin' => (int)$settings['setsToWin'],
                'serveRotation' => (int)$settings['serveRotation'],
                'specialRules' => $settings['specialRules']
            ],
            'customization' => $settings['customization'] ?? [],
            'metadata' => [
                'created_at' => $settings['created_at'],
                'updated_at' => $settings['updated_at'],
                'updated_by' => $settings['updated_by']
            ],
            'status' => 'custom'
        ];
    }

    /**
     * Waliduje i aktualizuje ustawienia
     * 
     * @param string $discipline Nazwa dyscypliny
     * @param array $input Dane wejściowe z API
     * @param int $userId ID administratora
     * @return array Zaktualizowane ustawienia
     * @throws InvalidArgumentException
     */
    public function validateAndUpdate($discipline, array $input, $userId)
    {
        // Waliduj nazwę dyscypliny
        $this->validateDisciplineName($discipline);

        // Wydziel reguły gry i personalizację
        $rules = $input['rules'] ?? [];
        $customization = $input['customization'] ?? null;

        // Waliduj strukturę
        if (empty($rules)) {
            throw new InvalidArgumentException('rules field is required');
        }

        // Przygotuj dane do modelu
        $settings = [
            'pointsToWin' => $rules['pointsToWin'] ?? 10,
            'setsToWin' => $rules['setsToWin'] ?? 2,
            'serveRotation' => $rules['serveRotation'] ?? 2,
            'specialRules' => $rules['specialRules'] ?? null,
            'customization' => $customization
        ];

        // Model zawsze waliduje dane
        $updated = $this->model->updateSettings($discipline, $settings, $userId);

        return $this->formatSettingsResponse($updated);
    }

    /**
     * Pobiera snapshot do startu meczu
     * 
     * @param string $discipline Nazwa dyscypliny
     * @param int|null $version Opcjonalnie: konkretna wersja
     * @return array Snapshot
     */
    public function getMatchSnapshot($discipline, $version = null)
    {
        $this->validateDisciplineName($discipline);

        try {
            $snapshot = $this->model->getSnapshot($discipline, $version);
            return [
                'success' => true,
                'snapshot' => $snapshot
            ];
        } catch (RuntimeException $e) {
            throw new RuntimeException('Cannot create snapshot: ' . $e->getMessage());
        }
    }

    /**
     * Resetuje ustawienia do defaults
     * (przydatne dla testów lub przywrócenia domyślnych)
     * 
     * @param string $discipline Nazwa dyscypliny
     * @param int $userId ID administratora
     * @return array Ustawienia po resecie
     */
    public function resetToDefaults($discipline, $userId)
    {
        $this->validateDisciplineName($discipline);

        $defaults = DisciplineSettingsModel::getDefaults($discipline);
        $updated = $this->model->updateSettings($discipline, $defaults, $userId);

        return $this->formatSettingsResponse($updated);
    }

    /**
     * Waliduje czy dyscyplina jest obsługiwana
     * 
     * @param string $discipline Nazwa dyscypliny
     * @throws InvalidArgumentException
     */
    private function validateDisciplineName($discipline)
    {
        $allowed = ['ping-pong', 'rock-paper-scissors', 'table-football'];

        if (!in_array($discipline, $allowed, true)) {
            throw new InvalidArgumentException(
                "Invalid discipline: $discipline. Allowed: " . implode(', ', $allowed)
            );
        }
    }

    /**
     * Formatuje odpowiedź z ustawień
     * 
     * @param array $settings Surowe ustawienia z modelu
     * @return array Sformatowana odpowiedź
     */
    private function formatSettingsResponse($settings)
    {
        return [
            'discipline' => $settings['discipline'],
            'settingsVersion' => (int)$settings['settingsVersion'],
            'rules' => [
                'pointsToWin' => (int)$settings['pointsToWin'],
                'setsToWin' => (int)$settings['setsToWin'],
                'serveRotation' => (int)$settings['serveRotation'],
                'specialRules' => $settings['specialRules']
            ],
            'customization' => $settings['customization'] ?? [],
            'metadata' => [
                'created_at' => $settings['created_at'],
                'updated_at' => $settings['updated_at'],
                'updated_by' => $settings['updated_by']
            ]
        ];
    }

    /**
     * Porównuje wersje ustawień (do debugowania zmian)
     * 
     * @param array $oldSettings Stare ustawienia
     * @param array $newSettings Nowe ustawienia
     * @return array Różnice
     */
    public function compareVersions($oldSettings, $newSettings)
    {
        $changes = [];

        foreach (['pointsToWin', 'setsToWin', 'serveRotation', 'specialRules'] as $field) {
            if (($oldSettings[$field] ?? null) !== ($newSettings[$field] ?? null)) {
                $changes[$field] = [
                    'old' => $oldSettings[$field] ?? null,
                    'new' => $newSettings[$field] ?? null
                ];
            }
        }

        if (json_encode($oldSettings['customization'] ?? []) !== json_encode($newSettings['customization'] ?? [])) {
            $changes['customization'] = [
                'old' => $oldSettings['customization'] ?? [],
                'new' => $newSettings['customization'] ?? []
            ];
        }

        return $changes;
    }
}
?>
