<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\FilesMainController;
use App\Http\Controllers\Helpers\ResponseHelper;
use App\Models\SystemSetting;
use App\Enums\UserTypes;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Exception;

class SystemSettingsController
{
    /**
     * Get all system settings grouped by group.
     */
    public function index(Request $request)
    {
        if (!Auth::user()->isUltimate()) {
            return ResponseHelper::returnUnauthorized();
        }

        $keys = $request->input('keys', []);
        
        if (!empty($keys)) {
            $settings = SystemSetting::whereIn('key', (array)$keys)->get();
            return response()->json([
                'success' => true,
                'data' => $settings
            ]);
        }

        $settings = SystemSetting::all()->groupBy('group');

        return response()->json([
            'success' => true,
            'data' => $settings
        ]);
    }

    /**
     * Update multiple settings.
     */
    public function update(Request $request)
    {
        if (!Auth::user()->isUltimate()) {
            return ResponseHelper::returnUnauthorized();
        }

        $validated = $request->validate([
            'settings' => 'required|array',
        ]);

        try {
            foreach ($validated['settings'] as $key => $value) {
                SystemSetting::setValue($key, $value);
            }

            SystemSetting::clearCache();

            return response()->json([
                'success' => true,
                'message' => 'System settings updated successfully'
            ]);
        } catch (Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to update settings: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Upload application logo.
     */
    public function uploadLogo(Request $request)
    {
        if (!Auth::user()->isUltimate()) {
            return ResponseHelper::returnUnauthorized();
        }

        if (!$request->hasFile('logo')) {
            return response()->json(['success' => false, 'message' => 'No logo file provided'], 400);
        }

        try {
            $file = $request->file('logo');
            $filename = 'app_logo_' . time() . '.' . $file->getExtension();

            // Extract palette from the uploaded file before it is moved by storage.
            $palette = \App\Support\PaletteExtractor::extract($file->getRealPath());

            // Reusing existing file storage system
            $result = FilesMainController::uploadFileList(
                $file,
                'System Logo',
                $filename,
                'Application branding logo',
                [],
                'system',
                [],
                0,
                'app_logo',
            );

            if ($result && isset($result->hashkey)) {
                SystemSetting::setValue('app_logo', $result->hashkey);

                if ($palette) {
                    SystemSetting::setValue('primary_color', $palette['primary']);
                    SystemSetting::setValue('accent_color', $palette['accent']);
                    SystemSetting::setValue('background_tint', $palette['tint']);
                }

                SystemSetting::clearCache();

                return response()->json([
                    'success' => true,
                    'hashkey' => $result->hashkey,
                    'url' => FilesMainController::generateURLforFileListHash($result->hashkey),
                    'palette' => $palette,
                    'message' => 'Logo uploaded successfully'
                ]);
            }

            throw new Exception('File upload failed');
        } catch (Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Logo upload failed: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get public settings data.
     */
    public static function getPublicSettingsData()
    {
        $publicKeys = ['app_name', 'app_logo', 'app_description', 'app_tagline', 'primary_color', 'accent_color', 'background_tint', 'footer_text', 'disabled_pages', 'top_up_enabled', 'app_mode', 'main_organization', 'accounting_theme', 'default_org_type', 'group_types', 'bible_verse_text', 'bible_verse_reference'];

        $settings = [];
        foreach ($publicKeys as $key) {
            $settings[$key] = SystemSetting::getValue($key);
        }

        // Add module states
        $settings['module_states'] = \App\Support\ModuleHelper::getModuleStates();

        // Generate URL for logo if it exists
        if (!empty($settings['app_logo'])) {
            $settings['app_logo_url'] = FilesMainController::generateURLforFileListHash($settings['app_logo']);
        } else {
            $settings['app_logo_url'] = cdn_asset('vendor/assets/icons/192x192.png'); // Fallback to PWA icon on the CDN
        }

        // Resolve main organization hashkey to a usable data object
        $settings['main_organization_data'] = null;
        if (!empty($settings['main_organization'])) {
            $org = \App\Models\Market\Organization::where('hashkey', $settings['main_organization'])->first();
            if ($org) {
                $settings['main_organization_data'] = [
                    'hashkey' => $org->hashkey,
                    'name' => $org->name,
                    'type' => $org->type,
                ];
            }
        }

        return $settings;
    }

    /**
     * List organizations available for selection as the main cooperative/organization.
     */
    public function listOrganizations()
    {
        if (!Auth::user()->isUltimate()) {
            return ResponseHelper::returnUnauthorized();
        }

        $orgs = \App\Models\Market\Organization::where('is_active', true)
            ->orderBy('type')
            ->orderBy('name')
            ->get(['hashkey', 'name', 'type']);

        return response()->json([
            'success' => true,
            'data' => $orgs,
        ]);
    }

    /**
     * Get all modules with their effective state, env/config default, and
     * any DB-stored override. Used by the Ultimate Console module manager.
     */
    public function getModules()
    {
        if (!Auth::user()->isUltimate()) {
            return ResponseHelper::returnUnauthorized();
        }

        return response()->json([
            'success' => true,
            'data' => [
                'system_enabled' => \App\Support\ModuleHelper::isSystemEnabled(),
                'modules' => \App\Support\ModuleHelper::getAllModules(),
            ],
        ]);
    }

    /**
     * Update the module override map. Accepts an associative array of
     * { module_key: bool|null }. A null value clears that key's override
     * so the env/config default takes effect again.
     */
    public function updateModules(Request $request)
    {
        if (!Auth::user()->isUltimate()) {
            return ResponseHelper::returnUnauthorized();
        }

        $validated = $request->validate([
            'overrides' => 'required|array',
        ]);

        $configModules = (array) \Hypervel\Support\Facades\Config::get('modules', []);
        $current = SystemSetting::getValue(\App\Support\ModuleHelper::OVERRIDE_KEY);
        if (is_string($current) && $current !== '') {
            $decoded = json_decode($current, true);
            $current = is_array($decoded) ? $decoded : [];
        } elseif (!is_array($current)) {
            $current = [];
        }

        foreach ($validated['overrides'] as $key => $value) {
            // Only allow keys that are actually defined as modules.
            if (!isset($configModules[$key]) || !is_array($configModules[$key])) {
                continue;
            }

            if ($value === null || $value === 'null') {
                unset($current[$key]);
            } else {
                $current[$key] = filter_var($value, FILTER_VALIDATE_BOOLEAN);
            }
        }

        try {
            SystemSetting::setValue(
                \App\Support\ModuleHelper::OVERRIDE_KEY,
                json_encode((object) $current),
                'modules',
                'json'
            );
            SystemSetting::clearCache();

            return response()->json([
                'success' => true,
                'message' => 'Module states updated',
                'data' => [
                    'modules' => \App\Support\ModuleHelper::getAllModules(),
                ],
            ]);
        } catch (Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to update modules: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get public settings for frontend.
     */
    public function getPublicSettings()
    {
        return response()->json([
            'success' => true,
            'data' => self::getPublicSettingsData()
        ]);
    }
}
