<?php

namespace App\Filament\Pages;

use App\Enums\DataChangeStatus;
use App\Enums\VerificationStatus;
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
use App\Filament\Support\CheerfulNotification;
use App\Models\Company as CompanyModel;
use App\Models\DataChangeRequest;
use App\Models\User;
use App\Models\VerificationRequest;
use App\Notifications\BroadcastNotification;
use Asmit\FilamentUpload\Forms\Components\AdvancedFileUpload;
use BackedEnum;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
use Filament\Actions\Action;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Contracts\HasForms;
use Filament\Pages\Page;
use Filament\Schemas\Components\Group;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
use UnitEnum;

class Company extends Page implements HasForms
{
    use HasPageShield;

    public ?CompanyModel $company = null;

    public array $data = [];

    public array $originalDocuments = [];

    public bool $isVerificationStage = false;

    protected static string|UnitEnum|null $navigationGroup = 'Kelola';

    protected static string|BackedEnum|null $navigationIcon = Heroicon::BuildingOffice2;

    protected static ?string $navigationLabel = 'Perusahaan';

    protected static ?int $navigationSort = 2;

    protected static ?string $recordTitleAttribute = 'name';

    protected static ?string $slug = 'manage/company';

    protected static ?string $title = 'Perusahaan';

    public ?VerificationRequest $verificationRequest = null;

    protected string $view = 'filament.pages.company';

    public function mount(): void
    {
        $company = auth()->user()->company;

        if (! $company) {
            return;
        }

        $this->isVerificationStage = in_array($company->verificationRequest?->status, [
            VerificationStatus::PENDING,
            VerificationStatus::REJECTED,
        ]) || $company->verificationRequest()->pending()->exists();

        $this->verificationRequest = $company->verificationRequest()
            ->latest()
            ->first();

        $this->company = $company;

        $this->form->fill($company->toArray());

        $documents = [
            'director_nik',
            'deed_incorporation',
            'trade_license',
            'tax_id_number',
            'taxable_enterprise',
            'annual_tax_return',
            'domicile_certificate',
            'profile',
        ];

        $mediaItems = $company->getMedia('companies');

        foreach ($documents as $docType) {
            $media = $mediaItems
                ->where('custom_properties.doc_type', str($docType)->replace('_docs', '')->slug('-'))
                ->sortByDesc('created_at')
                ->first();

            if ($media) {
                $path = $media->getPathRelativeToRoot();
                $this->data["{$docType}_docs"] = [$path];
                $this->originalDocuments["{$docType}_docs"] = [$path];
            }
        }
    }

    public static function form(Schema $schema): Schema
    {
        $documents = [
            [
                'title' => 'Akta Pendirian',
                'text_name' => 'deed_incorporation',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'deed_incorporation_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/deed-incorporation/',
            ],
            [
                'title' => 'SIUP / NIB',
                'text_name' => 'trade_license',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'trade_license_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/trade-license/',
            ],
            [
                'title' => 'NPWP',
                'text_name' => 'tax_id_number',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'tax_id_number_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/tax-id-number/',
            ],
            [
                'title' => 'PKP',
                'text_name' => 'taxable_enterprise',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'taxable_enterprise_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/taxable-enterprise/',
            ],
            [
                'title' => 'SPT Tahunan',
                'text_name' => 'annual_tax_return',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'annual_tax_return_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/annual-tax-return/',
            ],
            [
                'title' => 'Suket Domisili',
                'text_name' => 'domicile_certificate',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'domicile_certificate_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/domicile-certificate/',
            ],
            [
                'title' => 'Profil Perusahaan',
                'text_name' => 'profile',
                'placeholder' => '*****',
                'max' => 150,
                'max_size' => 1024 * 10,
                'file_name' => 'profile_docs',
                'accept' => ['application/pdf'],
                'folder' => 'companies/profile/',
            ],
        ];

        return $schema
            ->components([
                Section::make('Informasi')
                    ->schema([
                        TextInput::make('name')
                            ->label('Nama')
                            ->placeholder('PT ABC Indonesia Abadi')
                            ->autocomplete(false)
                            ->autofocus()
                            ->required()
                            ->maxLength(100),

                        TextInput::make('email')
                            ->label('Alamat Surel')
                            ->placeholder('johndoe@example.com')
                            ->autocomplete(false)
                            ->required()
                            ->maxLength(254),

                        Textarea::make('address')
                            ->label('Alamat')
                            ->placeholder('Jl. Kebontoro, Jakarta Pusat')
                            ->autocomplete(false)
                            ->required()
                            ->columnSpanFull(),

                        TextInput::make('director_name')
                            ->label('Nama Direktur')
                            ->placeholder('John Doe')
                            ->autocomplete(false)
                            ->required()
                            ->maxLength(150)
                            ->columnSpanFull(),
                    ])
                    ->columns(2)
                    ->columnSpan(2),

                Group::make()
                    ->schema(
                        array_merge(
                            [
                                Section::make('NIK Direktur')
                                    ->schema([
                                        TextInput::make('director_nik')
                                            ->hiddenLabel()
                                            ->placeholder('32***')
                                            ->autocomplete(false)
                                            ->required()
                                            ->maxLength(16)
                                            ->rule('digits:16')
                                            ->inputMode('numeric')
                                            ->regex('/^[0-9]+$/'),

                                        AdvancedFileUpload::make('director_nik_docs')
                                            ->hiddenLabel()
                                            ->disk(config('filesystems.default'))
                                            ->acceptedFileTypes(['image/*'])
                                            ->maxSize(1024 * 3)
                                            ->directory('companies/director-nik/'.now()->toDateString())
                                            ->required(),
                                    ]),
                            ],

                            collect($documents)
                                ->map(function (array $doc): Section {
                                    return Section::make($doc['title'])
                                        ->schema([
                                            TextInput::make($doc['text_name'])
                                                ->hiddenLabel()
                                                ->placeholder($doc['placeholder'])
                                                ->autocomplete(false)
                                                ->required()
                                                ->maxLength($doc['max']),

                                            AdvancedFileUpload::make($doc['file_name'])
                                                ->hiddenLabel()
                                                ->disk(config('filesystems.default'))
                                                ->acceptedFileTypes($doc['accept'])
                                                ->maxSize($doc['max_size'])
                                                ->directory($doc['folder'].now()->toDateString())
                                                ->required(),
                                        ]);
                                })->toArray()
                        )
                    )
                    ->columns(2),
            ])
            ->statePath('data');
    }

    public function save(): void
    {
        $this->mountAction('save');
    }

    public function saveAction(): Action
    {
        $needsReview = $this->company?->verificationRequest?->status !== null;

        return Action::make('save')
            ->label('Simpan')
            ->modalHeading('Ajukan Perubahan')
            ->modal($needsReview)
            ->schema(
                $needsReview
                    ? [
                        Textarea::make('change_reason')
                            ->label('Alasan')
                            ->placeholder('Jelaskan alasan perubahan data ini...')
                            ->autocomplete(false)
                            ->autofocus()
                            ->required(),
                    ]
                    : []
            )
            ->action(function (array $data = []) use ($needsReview) {
                try {
                    $this->performSave($data, $needsReview);
                } catch (ValidationException $e) {
                    $this->unmountAction();

                    throw $e;
                }
            })
            ->modalWidth(Width::Large);
    }

    public function performSave(array $data, bool $needsReview = false): void
    {
        if ($needsReview) {
            $existingRequest = DataChangeRequest::where('entity_type', CompanyModel::class)
                ->where('entity_id', $this->company->id)
                ->where('status', DataChangeStatus::PENDING)
                ->exists();

            if ($existingRequest) {
                CheerfulNotification::warning(
                    'Pengajuan Sudah Ada ⏳',
                    'Masih ada pengajuan perubahan data yang sedang menunggu verifikasi. Silakan tunggu hingga selesai diproses.'
                )
                    ->send();

                return;
            }

            $state = $this->form->getState();

            $data = array_merge($state, $data);

            $fieldLabels = CompanyModel::dataChangeEntryLabels();

            $editableFields = [
                'name',
                'email',
                'address',
                'director_name',
                'director_nik',
                'deed_incorporation',
                'trade_license',
                'tax_id_number',
                'taxable_enterprise',
                'annual_tax_return',
                'domicile_certificate',
                'profile',
            ];

            $changedFields = [];
            $oldData = [];

            foreach ($editableFields as $field) {
                if ($this->company->{$field} !== ($data[$field] ?? null)) {
                    $label = $fieldLabels[$field] ?? $field;
                    $changedFields[$label] = $data[$field] ?? null;
                    $oldData[$label] = $this->company->{$field};
                }
            }

            $documents = [
                'director_nik_docs',
                'deed_incorporation_docs',
                'trade_license_docs',
                'tax_id_number_docs',
                'taxable_enterprise_docs',
                'annual_tax_return_docs',
                'domicile_certificate_docs',
                'profile_docs',
            ];

            foreach ($documents as $field) {
                $newValue = $this->data[$field] ?? [];
                $oldValue = $this->originalDocuments[$field] ?? [];

                // Compare as arrays since file uploads are often arrays
                if (json_encode($newValue) !== json_encode($oldValue)) {
                    $label = $fieldLabels[$field] ?? $field;
                    $changedFields[$label] = $newValue;
                    $oldData[$label] = $oldValue;
                }
            }

            if (empty($changedFields)) {
                CheerfulNotification::info(
                    'Belum ada yang berubah ✨',
                    'Ubah data terlebih dulu lalu simpan kembali 💪'
                )
                    ->send();

                return;
            }

            $dataChangeRequest = DataChangeRequest::create([
                'user_id' => auth()->id(),
                'entity_type' => CompanyModel::class,
                'entity_id' => $this->company->id,
                'old_data' => $oldData,
                'new_data' => $changedFields,
                'change_reason' => $data['change_reason'],
            ]);

            CheerfulNotification::success(
                'Permohonan Berhasil 🎉',
                'Data sudah dikirim dan sedang menunggu verifikasi admin ⏳'
            )
                ->send();

            User::superAdmin()
                ->get()
                ->each(function ($admin) use ($dataChangeRequest): void {
                    $admin->notify(new BroadcastNotification([
                        'title' => 'Ada Pengajuan Perubahan Data ✨',
                        'body' => 'Halooo Admin! 👋 '.auth()->user()->name.' baru saja mengajukan perubahan data. Yuk, cek detailnya dan lakukan verifikasi ya! 🚀',
                        'action' => [
                            Action::make('view')
                                ->label('Lihat')
                                ->url(DataChangesResource::getUrl('view', ['record' => $dataChangeRequest->id])),
                        ],
                    ]));
                });
        } else {
            $data = $this->form->getState();

            $company = CompanyModel::updateOrCreate([
                'id' => $this->company?->id,
            ], [
                'user_id' => auth()->id(),
                'name' => $data['name'],
                'email' => $data['email'],
                'address' => $data['address'],
                'director_name' => $data['director_name'],
                'director_nik' => $data['director_nik'],
                'deed_incorporation' => $data['deed_incorporation'],
                'trade_license' => $data['trade_license'],
                'tax_id_number' => $data['tax_id_number'],
                'taxable_enterprise' => $data['taxable_enterprise'],
                'annual_tax_return' => $data['annual_tax_return'],
                'domicile_certificate' => $data['domicile_certificate'],
                'profile' => $data['profile'],
            ]);

            $this->company = $company;

            $documents = [
                'director_nik_docs',
                'deed_incorporation_docs',
                'trade_license_docs',
                'tax_id_number_docs',
                'taxable_enterprise_docs',
                'annual_tax_return_docs',
                'domicile_certificate_docs',
                'profile_docs',
            ];

            foreach ($documents as $field) {
                if (empty($this->data[$field])) {
                    continue;
                }

                foreach ((array) $this->data[$field] as $filePath) {
                    $fullPath = Storage::disk(config('filesystems.default'))->path($filePath);

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

                    $company
                        ->addMediaFromDisk($filePath, config('filesystems.default'))
                        ->preservingOriginal()
                        ->withCustomProperties([
                            'feature' => 'companies',
                            'date' => now()->toDateString(),
                            'doc_type' => str($field)
                                ->replace('_docs', '')
                                ->slug('-'),
                        ])
                        ->toMediaCollection('companies');
                }
            }

            if ($this->company) {
                CheerfulNotification::update()->send();
            } else {
                CheerfulNotification::create()->send();
            }
        }
    }
}
