<?php

namespace App\Http\Controllers\Realty;

use App\Enums\SeveritySystemLog;
use App\Exports\PropertyExport;
use App\Http\Controllers\Controller;
use App\Http\Messages\ErrorMessages;
use App\Http\Messages\SuccessMessages;
use App\Http\Requests\PaginationRequest;
use App\Http\Requests\Realty\PropertyRequest;
use App\Http\Requests\Realty\UpdatePropertyRequest;
use App\Http\Resources\PaginacionResource;
use App\Http\Resources\Realty\PropertyResource;
use App\Http\Responses\ApiResponse;
use App\Services\Property\PropertyService;
use App\Services\SystemLogService;
use Maatwebsite\Excel\Facades\Excel;

class PropertyController extends Controller
{
    protected $propertyService;
    protected $systemLogService;

    public function __construct(PropertyService $propertyService,
    SystemLogService $systemLogService
    )
    {
        $this->propertyService = $propertyService;
        $this->systemLogService = $systemLogService;
    }

    /**
     * @OA\Post(
     *     path="/api/property",
     *     summary="Register Property",
     *     tags={"Property"},
     *     @OA\RequestBody(
     *         required=true,
     *         @OA\JsonContent(
     *             type="object",
     *             required={ "code", "location", "latitud", "longitud", "surface", "description", "delivery_date", "type_department_id", "base_price", "property_type", "property_type_id", "project_id", "benefits"},
     *             @OA\Property(property="title", type="string", example="Luxury Apartment"),
     *             @OA\Property(property="code", type="string", example="APT-2024"),
     *             @OA\Property(property="location", type="string", example="Av. Siempre Viva 742"),
     *             @OA\Property(property="latitud", type="string", example="-16.5000"),
     *             @OA\Property(property="longitud", type="string", example="-68.1500"),
     *             @OA\Property(property="surface", type="number", example=120.5),
     *             @OA\Property(property="description", type="string", example="Beautiful apartment with city view."),
     *             @OA\Property(property="delivery_date", type="string", format="date", example="2024-12-31"),
     *             @OA\Property(property="precio_por_m2", type="number", example=1500),
     *             @OA\Property(property="base_price", type="number", example=170000),
     *             @OA\Property(property="property_type", type="string", enum={"DEPARTAMENT", "HOUSE", "LAND", "OFFICE", "PARK"}, example="DEPARTAMENT"),
     *             @OA\Property(property="property_type_id", type="integer", example=1),
     *             @OA\Property(property="project_id", type="integer", example=1),
     *             @OA\Property(property="type_department_id", type="integer", example=1),
     *             @OA\Property(property="floors", type="integer", example=10),
     *             @OA\Property(property="number_bathrooms", type="integer", example=2),
     *             @OA\Property(property="number_bedrooms", type="integer", example=3),
     *             @OA\Property(property="builded_surface", type="number", example=90),
     *             @OA\Property(property="benefits", type="array", @OA\Items(type="string"), example={1, 2, 3}),
     *             @OA\Property(property="features", type="array", @OA\Items(type="string"), example={1, 2}),
     *             @OA\Property(property="land_use", type="string", example="residential"),
     *             @OA\Property(property="percentage_initial_fee", type="number", example=30),
     *
     *         )
     *     ),
     *     @OA\Response(response=200, description="Successful operation"),
     *     @OA\Response(response=400, description="Invalid request"),
     *     @OA\Response(response=401, description="Unauthorized"),
     *     @OA\Response(response=500, description="Internal server error")
     * )
     */

    public function register(PropertyRequest $request)
    {
        try {
            $property = $this->propertyService->createProperty($request->all());
            // return ApiResponse::success(SuccessMessages::CREATE_SUCCESS, new PropertyResource($property), [], 201);
            $this->systemLogService->logActivity('propiedad','Propiedad Registrada', SeveritySystemLog::info->name,$property);
            return ApiResponse::success(SuccessMessages::CREATE_SUCCESS, $property, [], 201);
        } catch (\Exception $e) {
            $this->systemLogService->logActivity('payments','Registro de Propiedad Fallida' , SeveritySystemLog::error->name);
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], 500);
        }
    }

    /**
     * @OA\Get(
     *     path="/api/property/{id}",
     *     summary="Get Propiedad by ID",
     *     tags={"Property"},
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         description="ID of the Property",
     *         required=true,
     *         @OA\Schema(
     *             type="integer",
     *             format="int64"
     *         )
     *     ),
     *     @OA\Response(response=200, description="Successful operation"),
     *     @OA\Response(response=404, description="Customer not found"),
     *     @OA\Response(response=500, description="Internal server error"),
     * )
     */

    public function get($id)
    {
        try {
            $Property = $this->propertyService->getPropertyById($id);
            return ApiResponse::success(SuccessMessages::SUCCESSFUL, new PropertyResource($Property), [], 200);
        } catch (\Exception $e) {
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], $e->getCode());
        }
    }

    /**
     * @OA\Get(
     *     path="/api/properties",
     *     summary="List properties with pagination",
     *     tags={"Property"},
     *     @OA\Parameter(
     *         name="search",
     *         in="query",
     *         description="Search query",
     *         required=false,
     *         @OA\Schema(type="string", maxLength=255)
     *     ),
     *     @OA\Parameter(
     *         name="itemsPerPage",
     *         in="query",
     *         description="Items per page",
     *         required=true,
     *         @OA\Schema(type="integer", minimum=1)
     *     ),
     *     @OA\Parameter(
     *         name="page",
     *         in="query",
     *         description="Page number",
     *         required=true,
     *         @OA\Schema(type="integer", minimum=1)
     *     ),
     *     @OA\Parameter(
     *         name="sortBy",
     *         in="query",
     *         description="Sort by field",
     *         required=false,
     *         @OA\Schema(type="string", maxLength=255)
     *     ),
     *     @OA\Parameter(
     *         name="orderBy",
     *         in="query",
     *         description="Sort order",
     *         required=false,
     *         @OA\Schema(type="string", enum={"asc", "desc"})
     *     ),
     *     @OA\Response(response=200, description="Successful operation"),
     *     @OA\Response(response=500, description="Internal server error")
     * )
     */

    public function list_Property_pagination(PaginationRequest $pagerequest)
    {
        try {
            $properties = $this->propertyService->getAllProperties($pagerequest);
            $properties->data = PropertyResource::collection($properties->getCollection());
            return ApiResponse::success(SuccessMessages::SUCCESSFUL, new PaginacionResource($properties), [], 200);
        } catch (\Exception $e) {
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], 500);
        }
    }

    /**
     * @OA\Get(
     *     path="/api/available/properties",
     *     summary="List properties",
     *     tags={"Property"},
     *     @OA\Response(response=200, description="Successful operation"),
     *     @OA\Response(response=500, description="Internal server error")
     * )
     */

    public function properties_available()
    {
        try {
            $properties = $this->propertyService->get_available();
            return ApiResponse::success(SuccessMessages::SUCCESSFUL, PropertyResource::collection($properties), [], 200);
        } catch (\Exception $e) {
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], 500);
        }
    }

    /**
     * @OA\Get(
     *     path="/api/project/{id}/properties",
     *     summary="List properties with pagination",
     *     tags={"Property"},
     *    @OA\Parameter(
     *         name="id",
     *         in="path",
     *         description="ID of the project",
     *         required=true,
     *         @OA\Schema(
     *             type="integer",
     *             format="int64"
     *         )
     *     ),
     *     @OA\Parameter(
     *         name="search",
     *         in="query",
     *         description="Search query",
     *         required=false,
     *         @OA\Schema(type="string", maxLength=255)
     *     ),
     *     @OA\Parameter(
     *         name="itemsPerPage",
     *         in="query",
     *         description="Items per page",
     *         required=true,
     *         @OA\Schema(type="integer", minimum=1)
     *     ),
     *     @OA\Parameter(
     *         name="page",
     *         in="query",
     *         description="Page number",
     *         required=true,
     *         @OA\Schema(type="integer", minimum=1)
     *     ),
     *     @OA\Parameter(
     *         name="sortBy",
     *         in="query",
     *         description="Sort by field",
     *         required=false,
     *         @OA\Schema(type="string", maxLength=255)
     *     ),
     *     @OA\Parameter(
     *         name="orderBy",
     *         in="query",
     *         description="Sort order",
     *         required=false,
     *         @OA\Schema(type="string", enum={"asc", "desc"})
     *     ),
     *     @OA\Response(response=200, description="Successful operation"),
     *     @OA\Response(response=500, description="Internal server error")
     * )
     */

    public function list_Property_to_project(PaginationRequest $pagerequest, $id)
    {
        try {
            $properties = $this->propertyService->allPropertiesToProject($pagerequest, $id);
            $properties->data = PropertyResource::collection($properties->getCollection());
            return ApiResponse::success(SuccessMessages::SUCCESSFUL, new PaginacionResource($properties), [], 200);
        } catch (\Exception $e) {
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], 500);
        }
    }

    /**
     * @OA\Get(
     *     path="/api/properties/{type}",
     *     summary="List properties with pagination",
     *     tags={"Property"},
     *     @OA\Parameter(
     *         name="type",
     *         in="path",
     *         description="Type of the Property",
     *         required=true,
     *         @OA\Schema(
     *             type="string"
     *         )
     *     ),
     *     @OA\Response(response=200, description="Successful operation"),
     *     @OA\Response(response=500, description="Internal server error")
     * )
     */

    public function list_Property_type($type)
    {
        try {
            $properties = $this->propertyService->getAllPropertiesType($type);
            return ApiResponse::success(SuccessMessages::SUCCESSFUL, PropertyResource::collection($properties), [], 200);
        } catch (\Exception $e) {
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], 500);
        }
    }

    /**
     * @OA\patch(
     *     path="/api/property/{id}",
     *     summary="Update Property",
     *     tags={"Property"},
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         description="ID of the property to update",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\RequestBody(
     *         required=true,
     *         @OA\JsonContent(
     *             @OA\Property(property="title", type="string", maxLength=255, description="Title of the property"),
     *             @OA\Property(property="code", type="string", maxLength=255, description="Unique code for the property"),
     *             @OA\Property(property="surface", type="number", format="float", description="Surface area of the property"),
     *             @OA\Property(property="base_price", type="number", format="float", description="Base price of the property"),
     *             @OA\Property(property="percentage_initial_fee", type="number", format="float", description="Base price of the property"),
     *             @OA\Property(
     *                 property="property_type",
     *                 type="string",
     *                 enum={"DEPARTAMENT", "HOUSE", "PARK"},
     *                 description="Type of property (DEPARTAMENT, HOUSE, PARK)"
     *             ),
     *             @OA\Property(property="number_bathrooms", type="integer", description="Number of bathrooms, required if property type is DEPARTAMENT"),
     *             @OA\Property(property="number_bedrooms", type="integer", description="Number of bedrooms, required if property type is DEPARTAMENT"),
     *             @OA\Property(property="floor", type="integer", description="Floor number, required if property type is PARK"),
     *             @OA\Property(property="covered", type="boolean", description="Indicates if the park is covered, required if property type is PARK")
     *         )
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="Successful operation",
     * )
     * )
     */

    public function updateProperty(UpdatePropertyRequest $project_request, $id)
    {
        try {
            $project = $this->propertyService->updateProperty($id, $project_request->all());
            $this->systemLogService->logActivity('property','Propiedad Actualizada', SeveritySystemLog::info->name);

            return ApiResponse::success(SuccessMessages::UPDATE_SUCCESS, new PropertyResource($project), [], 200);
        } catch (\Exception $e) {
            $this->systemLogService->logActivity('payments','Actualización de propiedad fallida' , SeveritySystemLog::error->name);
            return ApiResponse::error(ErrorMessages::BAD_REQUEST, $e->getMessage(), [], 500);
        }
    }

    public function property_export()
    {
        try {
            $properties = $this->propertyService->AllProperties();
            $this->systemLogService->logActivity('Exportar','Propiedades Exportadas', SeveritySystemLog::info->name);
            return Excel::download(new PropertyExport($properties), 'Propiedades.xlsx');
        } catch (Exception $e) {
            return ApiResponse::error($e->getMessage(), $e, [], $e->getCode());
        }
    }
}
