<?php

namespace App\Filament\Resources\Manage\DataChanges\Actions\DataChangeRequest;

use App\Enums\DataChangeDecision;
use App\Enums\DataChangeStatus;
use App\Enums\RoleEnum;
use App\Filament\Support\CheerfulNotification;
use App\Models\DataChangeRequest;
use App\Models\DataChangeReview;
use App\Notifications\BroadcastNotification;
use Filament\Actions\Action;
use Filament\Support\Contracts\HasLabel;
use Filament\Support\Icons\Heroicon;
use Illuminate\Support\Facades\Storage;

class AcceptAction extends Action
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->label('Setujui')
            ->icon(Heroicon::Check)
            ->color('success')
            ->requiresConfirmation()
            ->modalHeading('Setujui Perubahan Data')
            ->modalDescription('Apakah Anda yakin ingin menyetujui dan menerapkan perubahan data ini?')
            ->action(function (DataChangeRequest $record): void {
                $entity = $record->entity;
                $newData = $record->new_data;

                if (isset($newData['__delete_request__']) && $newData['__delete_request__'] === true) {
                    $entity->delete();

                    $record->update(['status' => DataChangeStatus::APPROVED]);

                    DataChangeReview::create([
                        'data_change_request_id' => $record->id,
                        'reviewer_id' => auth()->id(),
                        'decision' => DataChangeDecision::APPROVED,
                    ]);

                    CheerfulNotification::success(
                        'Penghapusan Disetujui! ✅',
                        'Data telah berhasil dihapus sesuai dengan permohonan.'
                    )->send();

                    // Notify User
                    $record->user?->notify(new BroadcastNotification([
                        'title' => 'Permohonan Penghapusan Disetujui ✨',
                        'body' => "Halo! Permohonan penghapusan data Anda untuk {$record->change_reason} telah disetujui oleh admin. 🚀",
                    ]));

                    return;
                }

                if (! $entity) {
                    CheerfulNotification::danger(
                        'Entitas Tidak Ditemukan ❌',
                        'Data asli untuk permohonan ini tidak dapat ditemukan.'
                    )->send();

                    return;
                }

                $fields = [];
                $docs = [];

                $reverseLabels = [];
                if (method_exists($record->entity_type, 'dataChangeEntryLabels')) {
                    $reverseLabels = array_flip(($record->entity_type)::dataChangeEntryLabels());
                }

                $casts = $entity->getCasts();
                foreach ($newData as $key => $value) {
                    $actualKey = $reverseLabels[$key] ?? $key;

                    if (str_ends_with($actualKey, '_docs')) {
                        $docs[$actualKey] = $value;
                    } else {
                        // Handle Enum labels reverse mapping
                        if (isset($casts[$actualKey])) {
                            $castType = $casts[$actualKey];
                            if (is_string($castType) && enum_exists($castType)) {
                                if (is_subclass_of($castType, HasLabel::class)) {
                                    foreach ($castType::cases() as $case) {
                                        if ($case->getLabel() === $value) {
                                            $value = $case->value;
                                            break;
                                        }
                                    }
                                }

                                // If it's an int-backed enum but we have a string (e.g. from older data or failed mapping)
                                if (is_string($value) && is_numeric($value)) {
                                    $reflection = new \ReflectionEnum($castType);
                                    if ($reflection->isBacked() && $reflection->getBackingType()?->getName() === 'int') {
                                        $value = (int) $value;
                                    }
                                }
                            }
                        }
                        $fields[$actualKey] = $value;
                    }
                }

                // Update model fields
                $entity->update($fields);

                // Update media/documents
                foreach ($docs as $field => $filePaths) {
                    if (empty($filePaths)) {
                        continue;
                    }

                    $docType = str($field)->replace('_docs', '')->slug('-');
                    $collection = match ($record->entity_type) {
                        'App\Models\PartnerMedia' => 'partnerMedia',
                        default => str($record->entity_type)->afterLast('\\')->plural()->lower()->toString(),
                    };

                    foreach ((array) $filePaths as $filePath) {
                        $fullPath = Storage::disk(config('filesystems.default'))->path($filePath);

                        if (! file_exists($fullPath)) {
                            continue;
                        }

                        $entity->addMediaFromDisk($filePath, config('filesystems.default'))
                            ->preservingOriginal()
                            ->withCustomProperties([
                                'feature' => $collection,
                                'date' => now()->toDateString(),
                                'doc_type' => $docType,
                            ])
                            ->toMediaCollection($collection);
                    }
                }

                $record->update(['status' => DataChangeStatus::APPROVED]);

                DataChangeReview::create([
                    'data_change_request_id' => $record->id,
                    'reviewer_id' => auth()->id(),
                    'decision' => DataChangeDecision::APPROVED,
                ]);

                CheerfulNotification::success(
                    'Perubahan Disetujui! ✅',
                    'Data telah berhasil diperbarui sesuai dengan permohonan.'
                )->send();

                // Notify User
                $record->user?->notify(new BroadcastNotification([
                    'title' => 'Permohonan Perubahan Disetujui ✨',
                    'body' => "Halo! Permohonan perubahan data Anda untuk {$record->change_reason} telah disetujui oleh admin. Cek sekarang ya! 🚀",
                ]));
            })
            ->visible(fn (DataChangeRequest $record): bool => $record->status === DataChangeStatus::PENDING && ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value));
    }
}
