<?php

namespace App\Filament\Pages\Company\Services;

use App\Enums\DataChangeStatus;
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\Notifications\BroadcastNotification;
use Filament\Actions\Action;
use Illuminate\Support\Facades\Storage;

class CompanySaveService
{
    public static function handle(
        ?CompanyModel $existingCompany,
        array $formState,
        array $pageData,
        array $originalDocuments,
        bool $needsReview,
        array $actionData = [],
    ): ?CompanyModel {
        if ($needsReview && $existingCompany) {
            self::createDataChangeRequest(
                company: $existingCompany,
                formState: $formState,
                pageData: $pageData,
                originalDocuments: $originalDocuments,
                actionData: $actionData,
            );

            return $existingCompany;
        }

        return self::saveCompanyDirectly($existingCompany, $formState, $pageData);
    }

    private static function createDataChangeRequest(
        CompanyModel $company,
        array $formState,
        array $pageData,
        array $originalDocuments,
        array $actionData,
    ): void {
        $existingRequest = DataChangeRequest::where('entity_type', CompanyModel::class)
            ->where('entity_id', $company->id)
            ->where('status', DataChangeStatus::PENDING)
            ->exists();

        if ($existingRequest) {
            CheerfulNotification::warning(
                CheerfulNotification::getByKey('data_change.existing.title'),
                CheerfulNotification::getByKey('data_change.existing.body')
            )->send();

            return;
        }

        $data = array_merge($formState, $actionData);
        $fieldLabels = CompanyModel::dataChangeEntryLabels();

        $editableFields = [
            'name',
            'email',
            'phone_number',
            '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 ($company->{$field} !== ($data[$field] ?? null)) {
                $label = $fieldLabels[$field] ?? $field;
                $changedFields[$label] = $data[$field] ?? null;
                $oldData[$label] = $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 = $pageData[$field] ?? [];
            $oldValue = $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(
                CheerfulNotification::getByKey('data_change.no_change.title'),
                CheerfulNotification::getByKey('data_change.no_change.body')
            )->send();

            return;
        }

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

        CheerfulNotification::success(
            CheerfulNotification::getByKey('data_change.success.title'),
            CheerfulNotification::getByKey('data_change.success.body')
        )->send();

        User::query()
            ->superAdmin()
            ->get()
            ->each(function ($admin) use ($dataChangeRequest): void {
                $admin->notify(new BroadcastNotification([
                    'title' => CheerfulNotification::getByKey('data_change.admin_notify.title'),
                    'body' => CheerfulNotification::getByKey('data_change.admin_notify.body', ['name' => auth()->user()->name]),
                    'action' => [
                        Action::make('view')
                            ->label('Lihat')
                            ->url(DataChangesResource::getUrl('view', ['record' => $dataChangeRequest->id])),
                    ],
                ]));
            });
    }

    private static function saveCompanyDirectly(?CompanyModel $existingCompany, array $formState, array $pageData): CompanyModel
    {
        $company = CompanyModel::updateOrCreate([
            'id' => $existingCompany?->id,
        ], [
            'user_id' => auth()->id(),
            'name' => $formState['name'],
            'email' => $formState['email'],
            'phone_number' => $formState['phone_number'],
            'address' => $formState['address'],
            'director_name' => $formState['director_name'],
            'director_nik' => $formState['director_nik'],
            'deed_incorporation' => $formState['deed_incorporation'],
            'trade_license' => $formState['trade_license'],
            'tax_id_number' => $formState['tax_id_number'],
            'taxable_enterprise' => $formState['taxable_enterprise'],
            'annual_tax_return' => $formState['annual_tax_return'],
            'domicile_certificate' => $formState['domicile_certificate'],
            'profile' => $formState['profile'],
        ]);

        $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($pageData[$field])) {
                continue;
            }

            foreach ((array) $pageData[$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');
            }
        }

        return $company;
    }
}
