<?php

namespace App\Helpers;

use App\Exceptions\SlugScopedException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;

class ApiResponse
{
    public static function success($data = null, $message = 'Success', $code = Response::HTTP_OK)
    {
        return response()->json([
            'status' => true,
            'message' => $message,
            'data' => $data
        ], $code);
    }

    public static function error($message = 'Something went wrong. Please try again.', $code = Response::HTTP_BAD_REQUEST)
    {
        return response()->json([
            'status' => false,
            'message' => $message
        ], $code);
    }

    public static function slugConflict(SlugScopedException $e)
    {
        return response()->json([
            'status' => false,
            'code' => $e->errorCode,
            'message' => $e->getMessage(),
            'requires_confirmation' => $e->requiresConfirmation,
            'conflict' => $e->conflict,
        ], $e->httpStatus);
    }

    public static function successWithMeta($data = null, $message = 'Success', array $meta = [], $code = Response::HTTP_OK)
    {
        return response()->json([
            'status' => true,
            'message' => $message,
            'data' => $data,
            'meta' => $meta,
        ], $code);
    }

    public static function exception(\Throwable $e, $defaultMessage = 'Something went wrong. Please try again.')
    {
        // Controllers catch \Throwable around $request->validate(), so validation
        // failures land here instead of Laravel's handler. Without this they fell
        // through to a generic 500 and the user never saw which field was wrong.
        if ($e instanceof ValidationException) {
            return response()->json([
                'status' => false,
                'message' => $e->validator->errors()->first() ?: $e->getMessage(),
                'errors' => $e->errors(),
            ], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        Log::error('API Exception', [
            'error' => $e->getMessage(),
            'file' => $e->getFile(),
            'line' => $e->getLine(),
        ]);

        if ($e instanceof SlugScopedException) {
            return self::slugConflict($e);
        }

        if ($e instanceof ModelNotFoundException) {
            return self::error('Record not found.', Response::HTTP_NOT_FOUND);
        }

        if ($e instanceof QueryException) {
            if (str_contains($e->getMessage(), 'invalid input syntax for type uuid')) {
                return self::error('Invalid ID format.', Response::HTTP_UNPROCESSABLE_ENTITY);
            }

            $queryMessage = $e->getMessage();
            $lowerMessage = strtolower($queryMessage);
            if (str_contains($lowerMessage, 'not-null constraint') || str_contains($lowerMessage, 'null value in column')) {
                return self::error('Required data is missing. Please review the form and try again.', Response::HTTP_UNPROCESSABLE_ENTITY);
            }

            if (str_contains($lowerMessage, 'duplicate key value') || str_contains($lowerMessage, 'unique constraint')) {
                if (str_contains($lowerMessage, '(slug)=') || str_contains($lowerMessage, '_slug_unique')) {
                    return self::error('Slug already exists. Please use a different slug.', Response::HTTP_UNPROCESSABLE_ENTITY);
                }

                if (preg_match('/Key \(([^)]+)\)=\(([^)]+)\) already exists/i', $queryMessage, $matches)) {
                    $field = isset($matches[1]) ? str_replace('_', ' ', trim($matches[1])) : 'field';
                    return self::error(ucfirst($field) . ' already exists. Please use a different value.', Response::HTTP_UNPROCESSABLE_ENTITY);
                }

                return self::error('Duplicate value detected. Please use a different value.', Response::HTTP_UNPROCESSABLE_ENTITY);
            }

            return self::error('Invalid request data.', Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        if ($e instanceof \InvalidArgumentException) {
            return self::error($e->getMessage(), Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        if ($e instanceof \RuntimeException) {
            return self::error($e->getMessage(), Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        if ($e instanceof \Stripe\Exception\ApiErrorException) {
            return self::error($e->getMessage(), Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        if (str_contains($e->getMessage(), 'No query results for model')) {
            return self::error('Record not found.', Response::HTTP_NOT_FOUND);
        }

        if (str_contains($e->getMessage(), 'invalid input syntax for type uuid')) {
            return self::error('Invalid ID format.', Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        return self::error($defaultMessage, Response::HTTP_INTERNAL_SERVER_ERROR);
    }
}
