<?php

namespace App\Http\Livewire;

use App\Models\Offerwall;
use App\Models\User;
use App\Models\Withdrawal;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Storage;
use App\Support\ProviderOfferImporter;
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\WithPagination;

class Offerwalls extends Component
{
    use WithPagination;
    use WithFileUploads;

    protected $paginationTheme = 'bootstrap';

    public $photo;
    public $name;
    public $iframe;
    public $type = 'offer';
    public $launchMode = 'iframe';
    public $backgroundColor = '#202637';
    public $badge;
    public $badgeColor = '#02d46f';
    public $showRate = true;
    public $rate = '5';
    public $unlockLevel = 1;
    public $isMobile = false;
    public $description;
    public $offerFeedEnabled = false;
    public $offerFeedProvider = 'generic';
    public $gemiwallPlacementId;
    public $gemiwallApiKey;
    public $offerFeedUrl;
    public $offerFeedMethod = 'GET';
    public $offerFeedRoot;
    public $offerFeedHeaders;
    public $offerFeedBodyType = 'json';
    public $offerFeedHideMissing = false;
    public $offerFeedQueryRows = [
        ['key' => '', 'value' => ''],
    ];
    public $offerFeedBodyRows = [
        ['key' => '', 'value' => ''],
    ];
    public $offerFieldOfferId = 'id';
    public $offerFieldName = 'name';
    public $offerFieldDescription = 'description';
    public $offerFieldRequirements = 'requirements';
    public $offerFieldReward = 'reward';
    public $offerFieldPayout = 'payout';
    public $offerFieldIcon = 'icon';
    public $offerFieldUrl = 'url';
    public $offerFieldCategory = 'category';
    public $offerFieldDevices = 'devices';
    public $offerFieldCountries = 'countries';
    public $offerFieldSteps = 'steps';
    public $offerFieldRewards = 'rewards';
    public $postbackSecret;
    public $postbackScheme = 'static_secret';
    public $sdkRows = [
        ['key' => 'appName', 'value' => ''],
        ['key' => 'appId', 'value' => ''],
    ];
    public $selectedOffer;
    public $selectedProviders = [];
    public $selectPage = false;
    public $bulkAction = '';
    public $offerFeedConnectionStatus;
    public $offerFeedConnectionMessage;
    public $offerFeedConnectionCount;

    public function render()
    {
        $offerwalls = $this->offerwallsQuery()->paginate(20);
        return view('livewire.offerwalls', compact('offerwalls'));
    }

    public function save()
    {
        $this->validate([
            'name' => 'required|string|max:255',
            'iframe' => 'required|string|max:2048',
            'photo' => 'nullable|image|max:12048',
            'type' => 'nullable|in:offer,survey',
            'launchMode' => 'nullable|in:iframe,external',
            'unlockLevel' => 'nullable|integer|min:1',
            'offerFeedUrl' => 'nullable|url|max:2048',
        ]);

        $photoPath = $this->photo ? $this->photo->store('offerwalls', 'public') : $this->defaultProviderImage();

        Offerwall::create([
            'name' => $this->name,
            'iframe_url' => $this->iframe,
            'photo_path' => $photoPath,
            'type' => $this->type ?: 'offer',
            'launch_mode' => $this->launchMode ?: 'iframe',
            'background_color' => $this->backgroundColor ?: '#202637',
            'badge' => $this->badge,
            'badge_color' => $this->badgeColor ?: '#02d46f',
            'show_rate' => $this->showRate,
            'rate' => $this->rate,
            'unlock_level' => $this->unlockLevel ?: 1,
            'is_mobile' => $this->isMobile,
            'description' => $this->description,
            'sdk_data' => $this->normalizedSdkData(),
        ]);

        $this->resetProviderForm();
        $this->toasts('Created successfully');
    }

    public function update()
    {
        $this->validate([
            'name' => 'required|string|max:255',
            'iframe' => 'required|string|max:2048',
            'photo' => 'nullable|image|max:12048',
            'type' => 'nullable|in:offer,survey',
            'launchMode' => 'nullable|in:iframe,external',
            'unlockLevel' => 'nullable|integer|min:1',
            'offerFeedUrl' => 'nullable|url|max:2048',
        ]);

        $this->selectedOffer->name = $this->name;
        $this->selectedOffer->iframe_url = $this->iframe;
        $this->selectedOffer->type = $this->type;
        $this->selectedOffer->launch_mode = $this->launchMode;
        $this->selectedOffer->background_color = $this->backgroundColor;
        $this->selectedOffer->badge = $this->badge;
        $this->selectedOffer->badge_color = $this->badgeColor;
        $this->selectedOffer->show_rate = $this->showRate;
        $this->selectedOffer->rate = $this->rate;
        $this->selectedOffer->unlock_level = $this->unlockLevel;
        $this->selectedOffer->is_mobile = $this->isMobile;
        $this->selectedOffer->description = $this->description;
        $this->selectedOffer->sdk_data = $this->normalizedSdkData();
        if ($this->photo)
            $this->selectedOffer->photo_path = $this->photo->store('offerwalls', 'public');
        $this->selectedOffer->save();
        $this->toasts('Updated successfully');
    }

    public function delete($id): void
    {
        Offerwall::find($id)->delete();
        $this->toasts('Deleted successfully', 'error');
    }

    public function updatedSelectPage($value): void
    {
        $this->selectedProviders = $value
            ? $this->currentPageProviderIds()
            : [];
    }

    public function updatedSelectedProviders(): void
    {
        $pageIds = collect($this->currentPageProviderIds());
        $selectedIds = collect($this->selectedProviders)->map(fn($id) => (string) $id);

        $this->selectPage = $pageIds->isNotEmpty() && $pageIds->diff($selectedIds)->isEmpty();
    }

    public function updatingPage(): void
    {
        $this->selectedProviders = [];
        $this->selectPage = false;
    }

    public function applyBulkAction(): void
    {
        $ids = collect($this->selectedProviders)->filter()->map(fn($id) => (int) $id)->unique()->values();

        if ($ids->isEmpty()) {
            $this->toasts('Select at least one provider first', 'warning');
            return;
        }

        switch ($this->bulkAction) {
            case 'activate':
                Offerwall::whereKey($ids)->update(['is_active' => true]);
                $message = 'Selected providers activated';
                break;
            case 'deactivate':
                Offerwall::whereKey($ids)->update(['is_active' => false]);
                $message = 'Selected providers deactivated';
                break;
            case 'offer':
                Offerwall::whereKey($ids)->update(['type' => 'offer']);
                $message = 'Selected providers moved to offers';
                break;
            case 'survey':
                Offerwall::whereKey($ids)->update(['type' => 'survey']);
                $message = 'Selected providers moved to surveys';
                break;
            case 'delete':
                Offerwall::whereKey($ids)->delete();
                $message = 'Selected providers deleted';
                break;
            default:
                $this->toasts('Choose a bulk action', 'warning');
                return;
        }

        $this->bulkAction = '';
        $this->selectedProviders = [];
        $this->selectPage = false;
        $this->toasts($message);
    }

    public function select($id): void
    {
        $this->selectedOffer = Offerwall::find($id);
        $this->name = $this->selectedOffer->name;
        $this->iframe = $this->selectedOffer->iframe_url;
        $this->type = $this->selectedOffer->type ?? 'offer';
        $this->launchMode = $this->selectedOffer->launch_mode ?? 'iframe';
        $this->backgroundColor = $this->selectedOffer->background_color ?? '#202637';
        $this->badge = $this->selectedOffer->badge;
        $this->badgeColor = $this->selectedOffer->badge_color ?? '#02d46f';
        $this->showRate = $this->selectedOffer->show_rate ?? true;
        $this->rate = $this->selectedOffer->rate ?? '5';
        $this->unlockLevel = $this->selectedOffer->unlock_level ?? 1;
        $this->isMobile = $this->selectedOffer->is_mobile ?? false;
        $this->description = $this->selectedOffer->description;
        $this->fillOfferFeedFields($this->selectedOffer->sdk_data ?? []);
        $this->sdkRows = [['key' => '', 'value' => '']];
    }

    public function changeStatus()
    {
        $this->selectedOffer->is_active = !$this->selectedOffer->is_active;
        $this->selectedOffer->save();
        return redirect()->route('admin.offerwalls');
    }

    protected function toasts($message, $type = 'success'): void
    {
        $this->dispatchBrowserEvent('toasts', ['message' => $message, 'type' => $type, 'title' => 'Offerwalls']);
    }

    private function offerwallsQuery()
    {
        return Offerwall::withCount('providerOffers')->orderBy('name')->orderBy('id');
    }

    private function currentPageProviderIds(): array
    {
        return $this->offerwallsQuery()
            ->paginate(20)
            ->pluck('id')
            ->map(fn($id) => (string) $id)
            ->all();
    }

    public function addSdkRow(): void
    {
        $this->sdkRows[] = ['key' => '', 'value' => ''];
    }

    public function removeSdkRow($index): void
    {
        unset($this->sdkRows[$index]);
        $this->sdkRows = array_values($this->sdkRows);
    }

    public function addOfferFeedQueryRow(): void
    {
        $this->offerFeedQueryRows[] = ['key' => '', 'value' => ''];
    }

    public function removeOfferFeedQueryRow($index): void
    {
        unset($this->offerFeedQueryRows[$index]);
        $this->offerFeedQueryRows = array_values($this->offerFeedQueryRows);
    }

    public function testOfferFeedConnection(ProviderOfferImporter $importer): void
    {
        $this->resetValidation('offerFeedUrl');
        $this->offerFeedConnectionStatus = null;
        $this->offerFeedConnectionMessage = null;
        $this->offerFeedConnectionCount = null;

        if (!filter_var($this->offerFeedUrl, FILTER_VALIDATE_URL)) {
            $this->addError('offerFeedUrl', 'Enter a valid API GET URL before testing.');
            return;
        }

        $result = $importer->testConnection($this->offerFeedData());
        $this->offerFeedConnectionStatus = $result['success'] ? 'success' : 'error';
        $this->offerFeedConnectionMessage = $result['message'];
        $this->offerFeedConnectionCount = $result['count'] ?? null;
    }

    public function addOfferFeedBodyRow(): void
    {
        $this->offerFeedBodyRows[] = ['key' => '', 'value' => ''];
    }

    public function removeOfferFeedBodyRow($index): void
    {
        unset($this->offerFeedBodyRows[$index]);
        $this->offerFeedBodyRows = array_values($this->offerFeedBodyRows);
    }

    private function normalizedSdkData(): array
    {
        $data = [];

        foreach ($this->offerFeedData() as $key => $value) {
            if ($value !== '' && $value !== null) {
                $data[$key] = $value;
            }
        }

        return $data;
    }

    private function offerFeedData(): array
    {
        return [
            'offer_feed_enabled' => $this->offerFeedEnabled ? '1' : '0',
            'offer_feed_provider' => 'generic',
            'offer_feed_url' => trim((string) $this->offerFeedUrl),
            'offer_feed_method' => 'GET',
            'offer_feed_root' => trim((string) $this->offerFeedRoot),
            'offer_feed_headers' => '',
            'offer_feed_body_type' => 'json',
            'offer_feed_query_params' => $this->normalizedRows($this->offerFeedQueryRows),
            'offer_feed_body_params' => [],
            'offer_feed_hide_missing' => '1',
            'offer_launch_mode' => $this->launchMode ?: 'iframe',
            'postback_scheme' => 'static_secret',
        ];
    }

    private function fillOfferFeedFields(array $data): void
    {
        $this->offerFeedEnabled = array_key_exists('offer_feed_enabled', $data)
            ? filter_var($data['offer_feed_enabled'], FILTER_VALIDATE_BOOLEAN)
            : (filled($data['offer_feed_url'] ?? null) || str_contains(strtolower((string) $this->name), 'upwall'));
        $this->offerFeedProvider = 'generic';
        $this->gemiwallPlacementId = null;
        $this->gemiwallApiKey = null;
        $this->offerFeedUrl = $data['offer_feed_url'] ?? null;
        $this->offerFeedMethod = 'GET';
        $this->offerFeedRoot = $data['offer_feed_root'] ?? null;
        $this->offerFeedHeaders = null;
        $this->offerFeedBodyType = 'json';
        $this->offerFeedQueryRows = $this->rowsFromAssoc($data['offer_feed_query_params'] ?? []);
        $this->offerFeedBodyRows = [['key' => '', 'value' => '']];
        $this->offerFeedHideMissing = false;
        $this->postbackSecret = null;
        $this->postbackScheme = 'static_secret';
    }

    private function normalizedRows(array $rows): array
    {
        return collect($rows)
            ->mapWithKeys(function ($row) {
                $key = trim((string) ($row['key'] ?? ''));

                return $key === '' ? [] : [$key => trim((string) ($row['value'] ?? ''))];
            })
            ->all();
    }

    private function rowsFromAssoc($data): array
    {
        if (is_string($data)) {
            $decoded = json_decode($data, true);
            $data = is_array($decoded) ? $decoded : [];
        }

        if (!is_array($data) || $data === []) {
            return [['key' => '', 'value' => '']];
        }

        return collect($data)
            ->map(function ($value, $key) {
                if (is_array($value) && array_key_exists('key', $value)) {
                    return [
                        'key' => (string) $value['key'],
                        'value' => (string) ($value['value'] ?? ''),
                    ];
                }

                return [
                    'key' => (string) $key,
                    'value' => is_scalar($value) ? (string) $value : json_encode($value),
                ];
            })
            ->values()
            ->all();
    }

    private function resetProviderForm(): void
    {
        $this->reset([
            'photo',
            'name',
            'iframe',
            'badge',
            'description',
        ]);

        $this->type = 'offer';
        $this->launchMode = 'iframe';
        $this->backgroundColor = '#202637';
        $this->badgeColor = '#02d46f';
        $this->showRate = true;
        $this->rate = '5';
        $this->unlockLevel = 1;
        $this->isMobile = false;
        $this->postbackSecret = null;
        $this->postbackScheme = 'static_secret';
        $this->offerFeedQueryRows = [['key' => '', 'value' => '']];
        $this->offerFeedBodyRows = [['key' => '', 'value' => '']];
        $this->fillOfferFeedFields([]);
        $this->sdkRows = [
            ['key' => 'appName', 'value' => ''],
            ['key' => 'appId', 'value' => ''],
        ];
        $this->offerFeedConnectionStatus = null;
        $this->offerFeedConnectionMessage = null;
        $this->offerFeedConnectionCount = null;
    }

    private function defaultProviderImage(): string
    {
        $path = 'offerwalls/provider-default.svg';

        if (!Storage::disk('public')->exists($path)) {
            Storage::disk('public')->put($path, '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96"><rect width="96" height="96" rx="12" fill="#101d19"/><path d="M27 31h42v34H27z" fill="none" stroke="#17df94" stroke-width="6"/><path d="M36 45h24M36 55h15" stroke="#17df94" stroke-width="6" stroke-linecap="round"/></svg>');
        }

        return $path;
    }
}
