<?php

namespace Botble\RealEstate\Http\Controllers;

use Botble\Base\Events\BeforeEditContentEvent;
use Botble\Base\Facades\Assets;
use Botble\Base\Http\Actions\DeleteResourceAction;
use Botble\RealEstate\Facades\RealEstateHelper;
use Botble\RealEstate\Forms\PropertyForm;
use Botble\RealEstate\Http\Requests\PropertyRequest;
use Botble\RealEstate\Models\Account;
use Botble\RealEstate\Models\CustomFieldValue;
use Botble\RealEstate\Models\Property;
use Botble\RealEstate\Services\SaveFacilitiesService;
use Botble\RealEstate\Services\StorePropertyCategoryService;
use Botble\RealEstate\Tables\PropertyTable;
use Carbon\Carbon;
use Illuminate\Http\Request;

class PropertyController extends BaseController
{
    public function __construct()
    {
        parent::__construct();

        $this
            ->breadcrumb()
            ->add(trans('plugins/real-estate::property.name'), route('property.index'));
    }

    public function index(PropertyTable $dataTable)
    {
        $this->pageTitle(trans('plugins/real-estate::property.name'));

        return $dataTable->renderTable();
    }

    public function create()
    {
        $this->pageTitle(trans('plugins/real-estate::property.create'));

        return PropertyForm::create()->renderForm();
    }

    public function store(
        PropertyRequest $request,
        StorePropertyCategoryService $propertyCategoryService,
        SaveFacilitiesService $saveFacilitiesService
    ) {
        $request->merge([
            'expire_date' => Carbon::now()->addDays(RealEstateHelper::propertyExpiredDays()),
            'images' => array_filter($request->input('images', [])),
            'author_type' => Account::class,
        ]);

        $propertyForm = PropertyForm::create()->setRequest($request);

        $propertyForm->saving(function (PropertyForm $form) use ($propertyCategoryService, $saveFacilitiesService) {
            $request = $form->getRequest();

            /** @var Property $property */
            $property = $form->getModel();
            $property->fill($request->input());
            $property->moderation_status = $request->input('moderation_status');
            $property->never_expired = $request->input('never_expired');
            $property->save();

            $form->fireModelEvents($property);

            if (RealEstateHelper::isEnabledCustomFields()) {
                $this->saveCustomFields($property, $request->input('custom_fields', []));
            }

            $property->features()->sync($request->input('features', []));

            $saveFacilitiesService->execute($property, $request->input('facilities', []));
            $propertyCategoryService->execute($request, $property);
        });

        return $this
            ->httpResponse()
            ->setPreviousUrl(route('property.index'))
            ->setNextUrl(route('property.edit', $propertyForm->getModel()->getKey()))
            ->setMessage(trans('core/base::notices.create_success_message'));
    }

    public function edit(int|string $id, Request $request)
    {
        $property = Property::query()->with(['features', 'author'])->findOrFail($id);

        Assets::addScriptsDirectly(['vendor/core/plugins/real-estate/js/duplicate-property.js']);

        $this->pageTitle(trans('plugins/real-estate::property.edit') . ' "' . $property->name . '"');

        event(new BeforeEditContentEvent($request, $property));

        return PropertyForm::createFromModel($property)->renderForm();
    }

    public function update(
        int|string $id,
        PropertyRequest $request,
        StorePropertyCategoryService $propertyCategoryService,
        SaveFacilitiesService $saveFacilitiesService
    ) {
        $property = Property::query()->findOrFail($id);

        PropertyForm::createFromModel($property)
            ->setRequest($request)
            ->saving(function (PropertyForm $form) use ($propertyCategoryService, $saveFacilitiesService) {
                $request = $form->getRequest();

                /** @var Property $property */
                $property = $form->getModel();
                $property->fill($request->except(['expire_date']));
                $property->author_type = Account::class;
                $property->images = array_filter($request->input('images', []));
                $property->moderation_status = $request->input('moderation_status');
                $property->never_expired = $request->input('never_expired');
                $property->save();

                $form->fireModelEvents($property);

                if (RealEstateHelper::isEnabledCustomFields()) {
                    $this->saveCustomFields($property, $request->input('custom_fields', []));
                }

                $property->features()->sync($request->input('features', []));

                $saveFacilitiesService->execute($property, $request->input('facilities', []));
                $propertyCategoryService->execute($request, $property);
            });

        return $this
            ->httpResponse()
            ->setPreviousUrl(route('property.index'))
            ->setNextUrl(route('property.edit', $property->getKey()))
            ->setMessage(trans('core/base::notices.update_success_message'));
    }

    public function destroy(Property $property)
    {
        return DeleteResourceAction::make($property);
    }

    protected function saveCustomFields(Property $property, array $customFields = []): void
    {
        $customFields = CustomFieldValue::formatCustomFields($customFields);

        $property->customFields()
            ->whereNotIn('id', collect($customFields)->pluck('id')->all())
            ->delete();

        $property->customFields()->saveMany($customFields);
    }
}
