<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\UpdateSettingsRequest;
use App\Models\Setting;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Inertia\Inertia;
use Inertia\Response;

class SettingsController extends Controller
{
    /**
     * The setting keys for each group, with their defaults.
     *
     * @var array<string, array<string, string|null>>
     */
    private const SETTING_DEFAULTS = [
        'general' => [
            'company_name' => 'EZSCALE',
            'company_email' => null,
            'support_url' => null,
            'status_page_url' => null,
        ],
        'api' => [
            'virtfusion_api_url' => null,
            'virtfusion_api_token' => null,
            'pterodactyl_api_url' => null,
            'pterodactyl_api_token' => null,
            'synergycp_api_url' => null,
            'synergycp_api_token' => null,
            'enhance_api_url' => null,
            'enhance_api_token' => null,
            'enhance_organization_id' => null,
        ],
        'billing' => [
            'default_currency' => 'USD',
            'grace_period_days' => '7',
            'suspension_warning_days' => '3',
            'auto_terminate_days' => '14',
            'bandwidth_overage_rate' => '0.05',
            'bandwidth_alert_75' => '1',
            'bandwidth_alert_90' => '1',
            'bandwidth_alert_100' => '1',
            'bandwidth_alert_75_email' => '1',
            'bandwidth_alert_90_email' => '1',
            'bandwidth_alert_100_email' => '1',
            'bandwidth_grace_period_days' => '3',
            'bandwidth_auto_suspend' => '0',
        ],
        'notifications' => [
            'email_from_address' => null,
            'email_from_name' => null,
        ],
        'discord' => [
            'discord_payment_webhook_url' => null,
            'discord_payment_webhook_enabled' => '0',
            'discord_provisioning_webhook_url' => null,
            'discord_provisioning_webhook_enabled' => '0',
            'discord_support_webhook_url' => null,
            'discord_support_webhook_enabled' => '0',
            'discord_system_webhook_url' => null,
            'discord_system_webhook_enabled' => '0',
        ],
    ];

    /**
     * Keys that contain sensitive values and should be masked in the UI.
     *
     * @var array<int, string>
     */
    private const SENSITIVE_KEYS = [
        'virtfusion_api_token',
        'pterodactyl_api_token',
        'synergycp_api_token',
        'enhance_api_token',
        'enhance_organization_id',
        'discord_payment_webhook_url',
        'discord_provisioning_webhook_url',
        'discord_support_webhook_url',
        'discord_system_webhook_url',
    ];

    public function index(): Response
    {
        $settings = [];

        foreach (self::SETTING_DEFAULTS as $group => $keys) {
            $stored = Setting::getGroup($group);

            foreach ($keys as $key => $default) {
                $value = $stored[$key] ?? $default;
                $settings[$group][$key] = $value;
            }
        }

        // Add read-only env-based values for display (masked)
        $settings['api']['stripe_publishable_key'] = $this->maskValue(config('cashier.key'));
        $settings['api']['stripe_secret_key'] = $this->maskValue(config('cashier.secret'));
        $settings['api']['paypal_client_id'] = $this->maskValue(config('paypal.credentials.client_id'));
        $settings['api']['paypal_client_secret'] = $this->maskValue(config('paypal.credentials.client_secret'));

        // Mask sensitive stored values
        foreach (self::SENSITIVE_KEYS as $key) {
            foreach (self::SETTING_DEFAULTS as $group => $keys) {
                if (array_key_exists($key, $keys) && ! empty($settings[$group][$key])) {
                    $settings[$group]["{$key}_masked"] = $this->maskValue($settings[$group][$key]);
                    $settings[$group]["{$key}_set"] = true;
                } elseif (array_key_exists($key, $keys)) {
                    $settings[$group]["{$key}_masked"] = '';
                    $settings[$group]["{$key}_set"] = false;
                }
            }
        }

        return Inertia::render('Admin/Settings/Index', [
            'settings' => $settings,
        ]);
    }

    public function update(UpdateSettingsRequest $request): RedirectResponse
    {
        $group = $request->validated('group');
        $validated = $request->validated();

        unset($validated['group']);

        // For sensitive keys, skip if the value wasn't actually changed (empty means "keep current")
        foreach (self::SENSITIVE_KEYS as $sensitiveKey) {
            if (array_key_exists($sensitiveKey, $validated) && empty($validated[$sensitiveKey])) {
                unset($validated[$sensitiveKey]);
            }
        }

        Setting::setGroup($group, $validated);

        return redirect()
            ->route('admin.settings.index')
            ->with('success', ucfirst($group).' settings updated successfully.');
    }

    /**
     * Test an API provider connection by making a simple health-check request.
     */
    public function testApiConnection(Request $request): JsonResponse
    {
        $request->validate([
            'provider' => ['required', 'string', 'in:virtfusion,pterodactyl,synergycp,enhance'],
        ]);

        $provider = $request->input('provider');

        // Use provided values or fall back to stored settings
        $url = $request->input('url') ?: Setting::get("{$provider}_api_url");
        $token = $request->input('token') ?: Setting::get("{$provider}_api_token");

        if (empty($url) || empty($token)) {
            return response()->json([
                'success' => false,
                'message' => 'API URL and token are required.',
            ]);
        }

        try {
            $result = match ($provider) {
                'virtfusion' => $this->testVirtFusion($url, $token),
                'pterodactyl' => $this->testPterodactyl($url, $token),
                'synergycp' => $this->testSynergyCP($url, $token),
                'enhance' => $this->testEnhance($url, $token, $request->input('organization_id')),
            };

            return response()->json($result);
        } catch (\Exception $e) {
            Log::warning("API connection test failed for {$provider}", [
                'error' => $e->getMessage(),
            ]);

            return response()->json([
                'success' => false,
                'message' => "Connection failed: {$e->getMessage()}",
            ]);
        }
    }

    /**
     * Test a Discord webhook by sending a test message.
     */
    public function testDiscordWebhook(Request $request): JsonResponse
    {
        $request->validate([
            'webhook_url' => ['required', 'url', 'regex:/^https:\/\/discord\.com\/api\/webhooks\//'],
            'channel' => ['required', 'string', 'in:payment,provisioning,support,system'],
        ]);

        $webhookUrl = $request->input('webhook_url');
        $channel = $request->input('channel');

        try {
            $response = Http::timeout(10)->post($webhookUrl, [
                'content' => null,
                'embeds' => [
                    [
                        'title' => 'EZSCALE Webhook Test',
                        'description' => "This is a test message for the **{$channel}** notification channel.",
                        'color' => 7563248, // Purple (#7367F0)
                        'footer' => [
                            'text' => 'EZSCALE Billing System',
                        ],
                        'timestamp' => now()->toIso8601String(),
                    ],
                ],
            ]);

            if ($response->successful() || $response->status() === 204) {
                return response()->json([
                    'success' => true,
                    'message' => 'Test message sent successfully! Check your Discord channel.',
                ]);
            }

            return response()->json([
                'success' => false,
                'message' => "Discord returned status {$response->status()}: {$response->body()}",
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => "Failed to send test message: {$e->getMessage()}",
            ]);
        }
    }

    /**
     * Mask a sensitive value, showing only the last 4 characters.
     */
    private function maskValue(?string $value): string
    {
        if (empty($value)) {
            return '';
        }

        $length = strlen($value);

        if ($length <= 4) {
            return str_repeat('*', $length);
        }

        return str_repeat('*', $length - 4).substr($value, -4);
    }

    /**
     * @return array{success: bool, message: string}
     */
    private function testVirtFusion(string $url, string $token): array
    {
        $response = Http::withToken($token)
            ->baseUrl(rtrim($url, '/'))
            ->acceptJson()
            ->timeout(10)
            ->get('/connect');

        if ($response->successful()) {
            $data = $response->json();

            return [
                'success' => true,
                'message' => 'VirtFusion connection successful. '.
                    (isset($data['version']) ? "Version: {$data['version']}" : ''),
            ];
        }

        return ['success' => false, 'message' => "VirtFusion returned HTTP {$response->status()}: {$response->body()}"];
    }

    /**
     * @return array{success: bool, message: string}
     */
    private function testPterodactyl(string $url, string $token): array
    {
        $response = Http::withToken($token)
            ->baseUrl(rtrim($url, '/'))
            ->acceptJson()
            ->timeout(10)
            ->get('/api/application/servers?per_page=1');

        if ($response->successful()) {
            return ['success' => true, 'message' => 'Pterodactyl connection successful.'];
        }

        return ['success' => false, 'message' => "Pterodactyl returned HTTP {$response->status()}."];
    }

    /**
     * @return array{success: bool, message: string}
     */
    private function testSynergyCP(string $url, string $token): array
    {
        $response = Http::withToken($token)
            ->baseUrl(rtrim($url, '/'))
            ->acceptJson()
            ->timeout(10)
            ->get('/api/v1/servers?per_page=1');

        if ($response->successful()) {
            return ['success' => true, 'message' => 'SynergyCP connection successful.'];
        }

        return ['success' => false, 'message' => "SynergyCP returned HTTP {$response->status()}."];
    }

    /**
     * @return array{success: bool, message: string}
     */
    private function testEnhance(string $url, string $token, ?string $orgId = null): array
    {
        $client = Http::withToken($token)
            ->baseUrl(rtrim($url, '/'))
            ->acceptJson()
            ->timeout(10);

        if ($orgId) {
            $client = $client->withHeaders(['X-Organization-ID' => $orgId]);
        }

        $response = $client->get('/orgs');

        if ($response->successful()) {
            return ['success' => true, 'message' => 'Enhance connection successful.'];
        }

        return ['success' => false, 'message' => "Enhance returned HTTP {$response->status()}."];
    }
}
