<?php

namespace App\Services;

use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class ResponseService
{
    protected LoggingService $loggingService;

    public function __construct(LoggingService $loggingService)
    {
        $this->loggingService = $loggingService;
    }

    public function getLoggingService(): LoggingService
    {
        return $this->loggingService;
    }

    public function success(
        mixed $data = null,
        string $message = 'Success',
        int $statusCode = 200,
        array $meta = []
    ): JsonResponse {
        $response = $this->buildResponse(true, $message, $data, $meta, $statusCode);

        $this->loggingService->flush($statusCode, $response);

        return response()->json($response, $statusCode);
    }

    public function created(
        mixed $data = null,
        string $message = 'Resource created successfully'
    ): JsonResponse {
        return $this->success($data, $message, 201);
    }

    public function noContent(string $message = 'Resource deleted successfully'): JsonResponse
    {
        $response = $this->buildResponse(true, $message, null, [], 200);

        $this->loggingService->flush(200, $response);

        return response()->json($response, 200);
    }

    public function error(
        string $message = 'An error occurred',
        int $statusCode = 400,
        mixed $errors = null,
        ?string $errorCode = null
    ): JsonResponse {
        $response = [
            'success' => false,
            'message' => $message,
            'meta' => [
                'request_id' => $this->loggingService->getRequestId(),
                'timestamp' => now()->toIso8601String(),
            ],
        ];

        if ($errors !== null) {
            $response['errors'] = $errors;
        }

        if ($errorCode !== null) {
            $response['error_code'] = $errorCode;
        }

        $this->loggingService->logError($message, [
            'status_code' => $statusCode,
            'errors' => $errors,
        ]);
        $this->loggingService->flush($statusCode, $response);

        return response()->json($response, $statusCode);
    }

    public function validationError(
        mixed $errors,
        string $message = 'Validation failed'
    ): JsonResponse {
        return $this->error($message, 422, $errors, 'VALIDATION_ERROR');
    }

    public function unauthorized(string $message = 'Unauthorized'): JsonResponse
    {
        return $this->error($message, 401, null, 'UNAUTHORIZED');
    }

    public function forbidden(string $message = 'Forbidden'): JsonResponse
    {
        return $this->error($message, 403, null, 'FORBIDDEN');
    }

    public function notFound(string $message = 'Resource not found'): JsonResponse
    {
        return $this->error($message, 404, null, 'NOT_FOUND');
    }

    public function serverError(
        string $message = 'Internal server error',
        ?string $debugMessage = null
    ): JsonResponse {
        $errors = null;

        if (config('app.debug') && $debugMessage) {
            $errors = ['debug' => $debugMessage];
        }

        return $this->error($message, 500, $errors, 'SERVER_ERROR');
    }

    public function paginated(
        LengthAwarePaginator $paginator,
        string $message = 'Data retrieved successfully',
        ?string $resourceClass = null
    ): JsonResponse {
        $data = $resourceClass
            ? $resourceClass::collection($paginator->items())
            : $paginator->items();

        $meta = [
            'pagination' => [
                'current_page' => $paginator->currentPage(),
                'last_page' => $paginator->lastPage(),
                'per_page' => $paginator->perPage(),
                'total' => $paginator->total(),
                'from' => $paginator->firstItem(),
                'to' => $paginator->lastItem(),
            ],
        ];

        return $this->success($data, $message, 200, $meta);
    }

    protected function buildResponse(
        bool $success,
        string $message,
        mixed $data,
        array $meta,
        int $statusCode
    ): array {
        $response = [
            'success' => $success,
            'message' => $message,
        ];

        if ($data !== null) {
            $response['data'] = $data;
        }

        $response['meta'] = array_merge([
            'request_id' => $this->loggingService->getRequestId(),
            'timestamp' => now()->toIso8601String(),
        ], $meta);

        return $response;
    }
}
