<?php

namespace App\Services\Property;

use App\Enums\PropertyStatus;
use Illuminate\Support\Facades\DB;
use App\Http\Messages\ErrorMessages;
use App\Repositories\Property\PropertyRepositoryInterface;

class PropertyService
{
    protected $propertyrepository;
    protected $propertyfactory;

    public function __construct(
        PropertyRepositoryInterface $propertyrepository,
        PropertyFactory  $propertyfactory,
    ) {
        $this->propertyrepository = $propertyrepository;
        $this->propertyfactory = $propertyfactory;
    }

    public function createProperty($data)
    {
        return DB::transaction(function () use ($data) {
            $data['initial_fee'] = $this->cuota_Inicial($data['base_price'],  $data['percentage_initial_fee']);
            $property = $this->propertyfactory
                ->create($data['property_type'])
                ->createProperty($data);
            $this->propertyfactory->assingBenefits($property, $data['benefits']);
            $this->propertyfactory->assingFeatures($property, $data['features']);
            return $property;
        });
    }

    public function updateProperty($id, $data)
    {
        $data['initial_fee'] = $this->cuota_Inicial($data['base_price'],  $data['percentage_initial_fee']);
        $property = $this->propertyfactory
            ->create($data['property_type'])
            ->update_Property($id, $data);
        if (!$property) {
            throw new \Exception(ErrorMessages::PROPERTY_NOT_FOUND, 404);
        }
        return $property;
    }

    public function deleteProperty($id)
    {
        return DB::transaction(fn() => $this->propertyrepository->delete($id));
    }

    public function allPropertiesToProject($request, $project_id)
    {
        $query = $this->propertyrepository->allPropertiesToProject($project_id);

        if ($request->filled('search')) {
            $searchTerm = $request->query('search');
            $query->where(function ($query) use ($searchTerm) {
                $query->where('title', 'like', '%' . $searchTerm . '%')
                    ->orWhere('code', 'like', '%' . $searchTerm . '%')
                    ->orWhere('location', 'like', '%' . $searchTerm . '%');
            });
        }

        if ($request->filled('typeProperty')) {
            $typeProperty = $request->query('typeProperty');
            $query->where('property_type', $typeProperty);
        }

        if ($request->has('sortBy') && $request->has('orderBy')) {
            $query->when($request->filled(['sortBy', 'orderBy']), function ($query) use ($request) {
                return $query->orderBy($request->query('sortBy'), $request->query('orderBy'));
            });
        }
        $itemsPerPage = $request->query('itemsPerPage', 10);
        $page = $request->query('page', 1);
        return $query->paginate($itemsPerPage, ['*'], 'page', $page);
    }

    public function getAllProperties($request)
    {
        $query = $this->propertyrepository->allquery();
        if ($request->filled('search')) {
            $searchTerm = $request->query('search');
            $query->where(function ($query) use ($searchTerm) {
                $query->where('title', 'like', '%' . $searchTerm . '%')
                ->orWhere('code', 'like', '%' . $searchTerm . '%')
                    ->orWhere('location', 'like', '%' . $searchTerm . '%');
            });
        }
        if ($request->filled('typeProperty')) {
            $typeProperty = $request->query('typeProperty');
            $query->where('property_type', $typeProperty);
        }

        if ($request->has('sortBy') && $request->has('orderBy')) {
            $query->orderBy($request->query('sortBy'), $request->query('orderBy'));
        }

        $itemsPerPage = $request->query('itemsPerPage', 10);
        $page = $request->query('page', 1);

        return  $query->paginate($itemsPerPage, ['*'], 'page', $page);
    }

    public function getAllPropertiesType($typeProperty)
    {
        return  $this->propertyrepository->allPropertiesToType($typeProperty);
    }

    public function get_available()
    {
        $query = $this->propertyrepository->allquery();
        $query  =  $query->where('status', PropertyStatus::AVAILABLE->name);
        return $query->get();
    }

    public function isAvailableProperty($id){
       $property =  $this->isProPertyExists($id);
       if($property->status != PropertyStatus::AVAILABLE->name){
        throw new \Exception(ErrorMessages::PROPERTY_NOT_AVAILABLE, 409);
       }
    }

    public function getPropertyById($id)
    {
        return $this->isProPertyExists($id);
    }

    private function isProPertyExists($id)
    {
        return $this->propertyrepository->find($id)
            ?? throw new \Exception(ErrorMessages::PROPERTY_NOT_FOUND, 404);
    }

    public function cuota_Inicial($price, $percentage_initial): float
    {
        return  $price * ($percentage_initial  / 100);
    }

    public function changeStatus($id , $status){
         $this->propertyrepository->update($id, ['status' => $status]);
        return $this->isProPertyExists($id);
    }

    public function AllProperties(){
        return $this->propertyrepository->all();
        $this->propertyrepository->update($id, ['status' => $status]);
        return $this->isProPertyExists($id);
    }
}
