<?php

namespace App\Services;

use App\Models\Setting;
use App\Models\Hotel;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Log;

class SettingsService
{
    /**
     * System-wide green brand palette. Theme CSS always uses these; per-hotel appearance color fields do not override.
     */
    public const THEME_PRIMARY_GREEN = '#1a936f';

    public const THEME_SECONDARY_GREEN = '#88d498';

    public const THEME_LIGHT_GREEN = '#c6dabf';

    public const THEME_DARK_GREEN = '#114b5f';

    public const THEME_ACCENT = '#f3e9d2';

    /**
     * Canonical green variables injected into :root / theme (same for every hotel).
     */
    public static function canonicalGreenThemeCssVariables(): array
    {
        return [
            '--primary-green' => self::THEME_PRIMARY_GREEN,
            '--secondary-green' => self::THEME_SECONDARY_GREEN,
            '--light-green' => self::THEME_LIGHT_GREEN,
            '--dark-green' => self::THEME_DARK_GREEN,
            '--accent' => self::THEME_ACCENT,
        ];
    }

    protected $settings = [];
    protected $hotel = null;
    
    public function __construct()
    {
        $this->loadSettings();
    }
    
    protected function getHotelId()
    {
        if (auth()->check() && auth()->user()->isSuperAdmin()) {
            // Outside the main app Settings module, super admin uses global-only settings (no random hotel branding).
            // Inside Settings (hotel selected), merge that property's rows so appearance saves actually show up.
            $sessionHotelId = session('current_hotel_id');
            if ($sessionHotelId && request()->routeIs('settings.*')) {
                return (int) $sessionHotelId;
            }

            return null;
        }

        $sessionHotelId = session('current_hotel_id');
        if ($sessionHotelId) {
            return $sessionHotelId;
        }

        if (auth()->check()) {
            $user = auth()->user();

            if (!empty($user->hotel_id)) {
                return $user->hotel_id;
            }

            if (!empty($user->hotel?->id)) {
                return $user->hotel->id;
            }
        }

        return request()->get('hotel_id');
    }

    protected function getCacheKey($hotelId): string
    {
        // Use Setting model helper to keep cache key consistent across the app
        return \App\Models\Setting::cacheKey($hotelId);
    }

    protected function loadSettings()
    {
        if (! Schema::hasTable('settings')) {
            $this->settings = [];
            return;
        }

        $hotelId = $this->getHotelId();
        $cacheKey = $this->getCacheKey($hotelId);

        try {
            $this->settings = Cache::remember($cacheKey, 3600, function () use ($hotelId) {
                $query = Setting::query();

                if ($hotelId) {
                    $query->where(function ($q) use ($hotelId) {
                        $q->whereNull('hotel_id')
                          ->orWhere('hotel_id', $hotelId);
                    });
                } else {
                    $query->whereNull('hotel_id');
                }

                // Ensure hotel-specific settings override globals
                $settings = $query->orderByRaw('hotel_id DESC')
                    ->get()
                    ->pluck('value', 'key')
                    ->toArray();

                return $settings;
            });
        } catch (\Exception $e) {
            Log::warning('Could not load settings: ' . $e->getMessage());
            $this->settings = [];
        }
    }
    
    public function get($key, $default = null)
    {
        if ($key === 'currency_symbol' && ! array_key_exists('currency_symbol', $this->settings)) {
            return $this->settings['base_currency'] ?? $default;
        }

        return $this->settings[$key] ?? $default;
    }
    
    public function getAll()
    {
        return $this->settings;
    }
    
    public function all()
    {
        return $this->getAll();
    }
    
    public function set($key, $value, $hotelId = null)
    {
        if (! Schema::hasTable('settings')) {
            return;
        }

        $hotelId = $hotelId ?? $this->getHotelId();

        Setting::setValue($key, $value, $hotelId);

        // Invalidate cache so updated values propagate immediately
        Cache::forget($this->getCacheKey($hotelId));
        Cache::forget('theme_variables');

        $this->loadSettings();
    }
    
    public function getHotel()
    {
        if ($this->hotel) {
            return $this->hotel;
        }

        $hotelId = $this->getHotelId();
        if ($hotelId) {
            $this->hotel = Hotel::find($hotelId);
        }

        return $this->hotel;
    }

    public function getHotelName()
    {
        $hotel = $this->getHotel();
        // Prefer the `hotels` record name (source of truth per property) over a stale generic setting
        if ($hotel && ! empty(trim((string) $hotel->name))) {
            return trim($hotel->name);
        }
        $fromSettings = $this->get('hotel_name');
        if (is_string($fromSettings) && trim($fromSettings) !== '') {
            return trim($fromSettings);
        }

        if (auth()->check() && auth()->user()->isSuperAdmin()) {
            return config('app.name', 'Administration');
        }

        return 'Hotel Management System';
    }
    
    public function getHotelAddress()
    {
        $hotel = $this->getHotel();
        return $this->get('hotel_address', $hotel ? $hotel->address : '');
    }
    
    public function getHotelPhone()
    {
        $hotel = $this->getHotel();
        return $this->get('hotel_phone', $hotel ? $hotel->phone : '');
    }
    
    public function getHotelEmail()
    {
        $hotel = $this->getHotel();
        return $this->get('hotel_email', $hotel ? $hotel->email : '');
    }
    
    public function getVatRate()
    {
        return (float) $this->get('tax_rate', 18);
    }
    
    public function getCurrencySymbol()
    {
        return $this->get('base_currency', $this->get('currency_symbol', 'UGX'));
    }
    
    public function getCurrencyPosition()
    {
        return $this->get('currency_position', 'left');
    }
    
    public function getThemeCssVariables(bool $fresh = false): array
    {
        $primary = self::THEME_PRIMARY_GREEN;
        $secondary = self::THEME_SECONDARY_GREEN;
        $light = self::THEME_LIGHT_GREEN;
        $dark = self::THEME_DARK_GREEN;

        // Enforce a single global green palette across all hotels/modules.
        return array_merge([
            '--primary-green' => $primary,
            '--secondary-green' => $secondary,
            '--light-green' => $light,
            '--dark-green' => $dark,
            '--accent' => self::THEME_ACCENT,
            '--bs-primary' => $primary,
            '--bs-secondary' => $secondary,
            '--bs-success' => $primary,
        ], [
            '--font-family' => $this->get('font_family', "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif"),
            '--border-radius' => $this->get('border_radius', '12px'),
            '--box-shadow' => $this->get('box_shadow', '0 4px 12px rgba(0,0,0,0.08)'),
            '--header-font-size' => $this->get('header_font_size', '2.5rem'),
            '--gray-100' => $this->get('gray_100', '#f8f9fa'),
            '--gray-200' => $this->get('gray_200', '#e9ecef'),
            '--gray-600' => $this->get('gray_600', '#6c757d'),
            '--gray-800' => $this->get('gray_800', '#343a40'),
        ]);
    }
    
    public function getThemeMode(bool $fresh = false): string
    {
        // Read directly from settings storage for current hotel context.
        $mode = Setting::getValue('theme_mode', $this->getHotelId(), $this->get('theme_mode', null));
        if (in_array($mode, ['light', 'dark', 'auto'], true)) {
            return $mode;
        }

        return session('theme_mode', 'light');
    }
    
    public function getThemeStyles()
    {
        $cssVars = $this->getThemeCssVariables();
        $mode = $this->getThemeMode();
        
        $css = ":root {\n";
        foreach ($cssVars as $key => $value) {
            $css .= "    {$key}: {$value};\n";
        }
        $css .= "}\n\n";
        
        // Add dark mode styles if needed
        if ($mode === 'dark') {
            $css .= "body.theme-dark {\n";
            $css .= "    --gray-100: #1a1a1a;\n";
            $css .= "    --gray-200: #2d2d2d;\n";
            $css .= "    --gray-600: #b0b0b0;\n";
            $css .= "    --gray-800: #e0e0e0;\n";
            $css .= "    background-color: #1a1a1a;\n";
            $css .= "    color: #f0f0f0;\n";
            $css .= "}\n";
        }
        
        return $css;
    }
    
    public function getHotelSettingsJson()
    {
        return [
            'name' => $this->getHotelName(),
            'address' => $this->getHotelAddress(),
            'phone' => $this->getHotelPhone(),
            'email' => $this->getHotelEmail(),
            'vat_rate' => $this->getVatRate(),
            'currency' => $this->getCurrencySymbol(),
            'currency_position' => $this->getCurrencyPosition(),
            'theme' => [
                'variables' => $this->getThemeCssVariables(),
                'mode' => $this->getThemeMode()
            ]
        ];
    }
    
    public function isConfigured()
    {
        return Schema::hasTable('settings') && Setting::count() > 0;
    }
}