<?php

namespace App\Http\Controllers\Admin\Settings;

use App\Http\Controllers\Controller;
use App\Traits\RefreshesSettingsCache;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;

abstract class BaseSettingsController extends Controller
{
    use RefreshesSettingsCache;

    protected function getAllSettings(): \Illuminate\Support\Collection
    {
        return Cache::remember('all_settings_flat', 60, function () {
            return DB::table('settings')->pluck('value', 'key');
        });
    }

    protected function getBoolSetting(\Illuminate\Support\Collection $allSettings, string $key, bool $default): bool
    {
        if ($allSettings->has($key)) {
            return $allSettings->get($key) === '1';
        }

        DB::table('settings')->insert([
            'key' => $key,
            'value' => $default ? '1' : '0',
            'created_at' => now(),
            'updated_at' => now(),
        ]);
        Cache::forget('all_settings_flat');

        return $default;
    }

    protected function setting(string $key, mixed $default = null): mixed
    {
        $settings = $this->getAllSettings();
        return $settings->get($key) ?? $default;
    }

    protected function setSetting(string $key, mixed $value): void
    {
        DB::table('settings')->updateOrInsert(
            ['key' => $key],
            ['value' => $value, 'created_at' => now(), 'updated_at' => now()]
        );
    }

    protected function setBoolSetting(string $key, bool $value): void
    {
        $this->setSetting($key, $value ? '1' : '0');
    }

    /**
     * Update environment file
     */
    protected function updateEnv(array $data): void
    {
        $envPath = base_path('.env');
        $envContent = file_get_contents($envPath);

        foreach ($data as $key => $value) {
            $escapedValue = str_contains($value, ' ') ? "\"{$value}\"" : $value;

            if (preg_match("/^{$key}=.*/m", $envContent)) {
                $envContent = preg_replace("/^{$key}=.*/m", "{$key}={$escapedValue}", $envContent);
            } else {
                $envContent .= "\n{$key}={$escapedValue}";
            }
        }

        file_put_contents($envPath, $envContent);
    }

    /**
     * Convert image to WebP format
     */
    protected function convertToWebP(string $sourcePath, string $destinationDir, string $baseFilename, int $quality = 80): ?string
    {
        if (! extension_loaded('gd')) {
            return null;
        }

        $imageInfo = @getimagesize($sourcePath);
        if (! $imageInfo) {
            return null;
        }

        $mimeType = $imageInfo['mime'];

        $image = null;
        switch ($mimeType) {
            case 'image/jpeg':
            case 'image/jpg':
                $image = @imagecreatefromjpeg($sourcePath);
                break;
            case 'image/png':
                $image = @imagecreatefrompng($sourcePath);
                if ($image) {
                    imagepalettetotruecolor($image);
                    imagealphablending($image, true);
                    imagesavealpha($image, true);
                }
                break;
            case 'image/webp':
                $image = @imagecreatefromwebp($sourcePath);
                break;
            case 'image/gif':
                $image = @imagecreatefromgif($sourcePath);
                break;
        }

        if (! $image) {
            return null;
        }

        $webpPath = $destinationDir.'/'.$baseFilename.'.webp';
        $success = imagewebp($image, $webpPath, $quality);
        imagedestroy($image);

        return $success ? $webpPath : null;
    }

    /**
     * Handle background file upload
     */
    protected function handleBackgroundUpload(Request $request, string $fileKey, string $settingKey): void
    {
        if (! $request->hasFile($fileKey)) {
            return;
        }

        $file = $request->file($fileKey);
        $originalExtension = strtolower($file->getClientOriginalExtension());
        $baseFilename = time().'_'.$settingKey;
        $tempFilename = $baseFilename.'.'.$originalExtension;

        $dir = 'img/backgrounds/'.$settingKey;

        if (! file_exists(public_path($dir))) {
            mkdir(public_path($dir), 0755, true);
        }

        $file->move(public_path($dir), $tempFilename);
        $tempPath = public_path($dir.'/'.$tempFilename);

        if ($originalExtension !== 'svg' && $originalExtension !== 'mp4') {
            $webpPath = $this->convertToWebP($tempPath, public_path($dir), $baseFilename, 80);
            if ($webpPath) {
                $path = $dir.'/'.$baseFilename.'.webp';
                @unlink($tempPath);
            } else {
                $path = $dir.'/'.$tempFilename;
            }
        } else {
            $path = $dir.'/'.$tempFilename;
        }

        $oldBackground = DB::table('settings')->where('key', $settingKey.'_background')->value('value');
        if ($oldBackground && file_exists(public_path($oldBackground))) {
            @unlink(public_path($oldBackground));
        }

        DB::table('settings')->updateOrInsert(
            ['key' => $settingKey.'_background'],
            ['value' => $path, 'created_at' => now(), 'updated_at' => now()]
        );
    }

    /**
     * Handle logo upload
     */
    protected function handleLogoUpload(Request $request): void
    {
        if (! $request->hasFile('logo')) {
            return;
        }

        $file = $request->file('logo');
        $originalExtension = strtolower($file->getClientOriginalExtension());
        $baseFilename = time().'_logo';
        $tempFilename = $baseFilename.'.'.$originalExtension;

        if (! file_exists(public_path('img/logo'))) {
            mkdir(public_path('img/logo'), 0755, true);
        }

        $file->move(public_path('img/logo'), $tempFilename);
        $tempPath = public_path('img/logo/'.$tempFilename);

        if ($originalExtension !== 'svg') {
            $webpPath = $this->convertToWebP($tempPath, public_path('img/logo'), $baseFilename, 80);
            if ($webpPath) {
                $path = 'img/logo/'.$baseFilename.'.webp';
            } else {
                $path = 'img/logo/'.$tempFilename;
            }
        } else {
            $path = 'img/logo/'.$tempFilename;
        }

        $oldLogo = DB::table('settings')->where('key', 'app_logo')->value('value');
        if ($oldLogo && file_exists(public_path($oldLogo))) {
            @unlink(public_path($oldLogo));
        }

        DB::table('settings')->updateOrInsert(
            ['key' => 'app_logo'],
            ['value' => $path, 'created_at' => now(), 'updated_at' => now()]
        );
    }

    /**
     * Get available fonts from resources/fonts directory
     */
    protected function getAvailableFonts(): array
    {
        $fontsDir = resource_path('fonts');
        $availableFonts = [];
        if (File::exists($fontsDir)) {
            $files = File::files($fontsDir);
            foreach ($files as $file) {
                $ext = strtolower($file->getExtension());
                if (in_array($ext, ['ttf', 'otf', 'woff2'])) {
                    $availableFonts[] = $file->getFilename();
                }
            }
            sort($availableFonts);
        }
        return $availableFonts;
    }
}
