<?php

namespace App\Filament\Pages\Company;

use App\Enums\VerificationStatus;
use App\Filament\Pages\Company\Concerns\HasCompanyActions;
use App\Filament\Pages\Company\Schemas\CompanyForm;
use App\Filament\Pages\Company\Services\CompanySaveService;
use App\Filament\Support\CheerfulNotification;
use App\Models\Company as CompanyModel;
use App\Models\VerificationRequest;
use BackedEnum;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Pages\Page;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Illuminate\Validation\ValidationException;
use UnitEnum;

class Index extends Page implements HasActions, HasForms
{
    use HasCompanyActions, HasPageShield, InteractsWithActions, InteractsWithForms;

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

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

    protected static ?string $navigationLabel = 'Perusahaan';

    protected static ?int $navigationSort = 2;

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

    protected static ?string $title = 'Perusahaan';

    public ?VerificationRequest $verificationRequest = null;

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

    public ?CompanyModel $company = null;

    public array $data = [];

    public array $originalDocuments = [];

    public bool $isVerificationStage = false;

    public static function canAccess(): bool
    {
        return auth()->user()->can('View: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
    {
        return CompanyForm::configure($schema);
    }

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

    public function needsCompanyReview(): bool
    {
        return $this->company?->verificationRequest?->status !== null;
    }

    public function handleCompanySave(array $data = []): void
    {
        try {
            $company = CompanySaveService::handle(
                existingCompany: $this->company,
                formState: $this->form->getState(),
                pageData: $this->data,
                originalDocuments: $this->originalDocuments,
                needsReview: $this->needsCompanyReview(),
                actionData: $data,
            );

            if ($this->needsCompanyReview()) {
                return;
            }

            $this->company = $company;

            CheerfulNotification::update()->send();
        } catch (ValidationException $e) {
            $this->unmountAction();

            throw $e;
        }
    }
}
