<?php

namespace App\Http\Controllers\Backoffice;

use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\Site;
use App\Models\SitePaymentPopup;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class PaymentPopupController extends Controller
{
    public function index()
    {
        $sites = Site::query()
            ->with('paymentPopup')
            ->orderBy('name')
            ->get();

        return view('backoffice.payment-popups.index', [
            'sites' => $sites,
            'desktopRecommended' => '1200 x 720',
            'mobileRecommended' => '1080 x 1920',
        ]);
    }

    public function update(Request $request, Site $site)
    {
        $request->validate([
            'desktop_image' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:4096',
            'mobile_image' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:4096',
            'desktop_enabled' => 'nullable|boolean',
            'mobile_enabled' => 'nullable|boolean',
            'desktop_delete' => 'nullable|boolean',
            'mobile_delete' => 'nullable|boolean',
            'popup_click_url' => 'nullable|url|max:2048',
            'popup_footer_text' => 'nullable|string|max:255',
            'popup_footer_url' => 'nullable|url|max:2048',
        ], [
            'desktop_image.image' => 'Desktop image file must be an image.',
            'desktop_image.mimes' => 'Desktop image must be jpg, jpeg, png or webp.',
            'desktop_image.max' => 'Desktop image max size is 4 MB.',
            'desktop_image.uploaded' => 'Desktop image failed to upload. Please try a smaller file and upload again.',
            'mobile_image.image' => 'Mobile image file must be an image.',
            'mobile_image.mimes' => 'Mobile image must be jpg, jpeg, png or webp.',
            'mobile_image.max' => 'Mobile image max size is 4 MB.',
            'mobile_image.uploaded' => 'Mobile image failed to upload. Please try a smaller file and upload again.',
            'desktop_enabled.boolean' => 'Desktop visibility is invalid.',
            'mobile_enabled.boolean' => 'Mobile visibility is invalid.',
            'desktop_delete.boolean' => 'Desktop delete flag is invalid.',
            'mobile_delete.boolean' => 'Mobile delete flag is invalid.',
            'popup_click_url.url' => 'Popup image link must be a valid URL.',
            'popup_click_url.max' => 'Popup image link is too long.',
            'popup_footer_text.max' => 'Popup footer text is too long.',
            'popup_footer_url.url' => 'Popup footer link must be a valid URL.',
            'popup_footer_url.max' => 'Popup footer link is too long.',
        ]);

        DB::beginTransaction();
        try {
            $popup = SitePaymentPopup::firstOrNew([
                'site_id' => $site->id,
            ]);

            $oldDesktopPath = (string) $popup->desktop_image_path;
            $oldMobilePath = (string) $popup->mobile_image_path;
            $oldData = $popup->exists ? $popup->toArray() : null;
            $deleteDesktop = (bool) $request->boolean('desktop_delete');
            $deleteMobile = (bool) $request->boolean('mobile_delete');

            $hasUpload = false;
            if ($request->hasFile('desktop_image')) {
                $popup->desktop_image_path = $this->storeImageInPublic($request->file('desktop_image'), 'desktop');
                $hasUpload = true;
            }

            if ($request->hasFile('mobile_image')) {
                $popup->mobile_image_path = $this->storeImageInPublic($request->file('mobile_image'), 'mobile');
                $hasUpload = true;
            }

            if ($deleteDesktop && !$request->hasFile('desktop_image')) {
                $popup->desktop_image_path = null;
                $popup->desktop_enabled = false;
            }

            if ($deleteMobile && !$request->hasFile('mobile_image')) {
                $popup->mobile_image_path = null;
                $popup->mobile_enabled = false;
            }

            if ($request->has('desktop_enabled')) {
                $popup->desktop_enabled = (bool) $request->boolean('desktop_enabled');
            }

            if ($request->has('mobile_enabled')) {
                $popup->mobile_enabled = (bool) $request->boolean('mobile_enabled');
            }

            $popup->popup_click_url = $this->normalizeOptionalUrl($request->input('popup_click_url'));
            $popup->popup_footer_text = $this->normalizeOptionalString($request->input('popup_footer_text'));
            $popup->popup_footer_url = $this->normalizeOptionalUrl($request->input('popup_footer_url'));

            // If an image does not exist, force the visibility off for that device.
            if (trim((string) $popup->desktop_image_path) === '') {
                $popup->desktop_enabled = false;
            }

            if (trim((string) $popup->mobile_image_path) === '') {
                $popup->mobile_enabled = false;
            }

            if (!$popup->exists) {
                $popup->created_by = auth()->id();
            }
            $popup->updated_by = auth()->id();

            if ($hasUpload || $popup->isDirty()) {
                $popup->save();
            }

            if ($request->hasFile('desktop_image') && $oldDesktopPath !== '' && $oldDesktopPath !== $popup->desktop_image_path) {
                $this->deleteImageFromPublic($oldDesktopPath);
            }
            if ($deleteDesktop && !$request->hasFile('desktop_image') && $oldDesktopPath !== '') {
                $this->deleteImageFromPublic($oldDesktopPath);
            }

            if ($request->hasFile('mobile_image') && $oldMobilePath !== '' && $oldMobilePath !== $popup->mobile_image_path) {
                $this->deleteImageFromPublic($oldMobilePath);
            }
            if ($deleteMobile && !$request->hasFile('mobile_image') && $oldMobilePath !== '') {
                $this->deleteImageFromPublic($oldMobilePath);
            }

            ActivityLog::log(
                'update_payment_popup',
                'site_payment_popups',
                'Payment popup images updated for site: ' . $site->name,
                $oldData,
                $popup->toArray()
            );

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Popup images updated successfully.',
                'popup' => [
                    'site_id' => (int) $site->id,
                    'desktop_image_url' => $popup->desktop_image_url,
                    'mobile_image_url' => $popup->mobile_image_url,
                    'desktop_enabled' => (bool) $popup->desktop_enabled,
                    'mobile_enabled' => (bool) $popup->mobile_enabled,
                    'popup_click_url' => (string) ($popup->popup_click_url ?? ''),
                    'popup_footer_text' => (string) ($popup->popup_footer_text ?? ''),
                    'popup_footer_url' => (string) ($popup->popup_footer_url ?? ''),
                ],
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => 'Popup images could not be updated: ' . $e->getMessage(),
            ], 500);
        }
    }

    private function storeImageInPublic($file, string $device): string
    {
        $device = strtolower($device) === 'mobile' ? 'mobile' : 'desktop';
        $relativeDirectory = 'payment-popups/' . $device;
        $absoluteDirectory = public_path($relativeDirectory);

        if (!File::exists($absoluteDirectory)) {
            File::makeDirectory($absoluteDirectory, 0755, true);
        }

        $extension = strtolower((string) ($file->getClientOriginalExtension() ?: $file->extension() ?: 'jpg'));
        if ($extension === 'jpeg') {
            $extension = 'jpg';
        }

        $filename = now()->format('YmdHis') . '-' . Str::lower(Str::random(32)) . '.' . $extension;
        $file->move($absoluteDirectory, $filename);

        return $relativeDirectory . '/' . $filename;
    }

    private function deleteImageFromPublic(?string $path): void
    {
        $path = trim((string) $path);
        if ($path === '' || preg_match('/^https?:\/\//i', $path)) {
            return;
        }

        // Keep only relative path and avoid removing anything outside app paths.
        $relativePath = ltrim((string) preg_replace('#^/?storage/#i', '', $path), '/');
        if ($relativePath === '' || str_contains($relativePath, '..')) {
            return;
        }

        $publicFile = public_path($relativePath);
        if (File::isFile($publicFile)) {
            File::delete($publicFile);
        }

        // Backward compatibility: also remove old files that were saved under storage/app/public.
        $storageFile = storage_path('app/public/' . $relativePath);
        if (File::isFile($storageFile)) {
            File::delete($storageFile);
        }
    }

    private function normalizeOptionalString($value): ?string
    {
        $value = trim((string) $value);

        return $value === '' ? null : $value;
    }

    private function normalizeOptionalUrl($value): ?string
    {
        return $this->normalizeOptionalString($value);
    }
}
