<?php

namespace App\Helper;

use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\TransferStats;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Facades\Storage;

class Helper
{
    public static function GetApi($url, array $headers = [], bool $associativeResponse = false)
    {
        return self::RequestApi($url, "GET", $body = [], $contentType = null, $headers, $associativeResponse);
    }

    public static function PostApi($url, $body = [], $contentType = "form-data", array $headers = [])
    {
        return self::RequestApi($url, "POST", $body, $contentType, $headers);
    }

    public static function RequestApi($url, $method = "GET", $body = [], $contentType = "form-data", array $headers = [], bool $associativeResponse = false)
    {
        $client = new \GuzzleHttp\Client(['headers' => $headers]);
        $options = [
            'headers' => array_merge([
                "x-client" => env("X_CLIENT"),
                "Accept" => "application/json",
                "Authorization" => "Bearer " . Session::get("tokenId"),
                "parent-id" => Session::get("parentId")
            ], $headers)
        ];

        if ($contentType === "form-data") {
            $options["form_params"] = $body;
        } elseif ($contentType === "json") {
            $options["headers"] = array_merge($options["headers"], ['Content-Type' => 'application/json']);
            $options["json"] = $body;
        }

        $time = null;
        $calcTime = null;
        $profiler = new ExecutionProfiler();
        $options['on_stats'] = function (TransferStats $stats) use (&$time) {
            // Estimated time the request was being transferred
            $time = $stats->getTransferTime();
        };

        $profiler->addInterval("sending");

        try {

            $response = $client->request($method, $url, $options);
            $profile = $profiler->calculate();
            $result = $response->getBody()->getContents();

            $json_result = json_decode($result, $associativeResponse);
            unset($options["headers"]);
            unset($options["on_stats"]);
            Log::channel("backend-request-" . app()->environment())->info("backend.request", [
                "method" => $method,
                "url" => $url,
                "options" => $options,
                "response" => $json_result,
                "time" => $time,
                "calcTime" => $profile
            ]);

            return $json_result;
        } catch (RequestException $re) {
            $httpRequest = $re->getRequest();
            $httpResponse = $re->getResponse();
            $message = $re->getMessage();
            $responseBody = null;
            $errorsReturned = false;
            if ($httpResponse) {
                $responseBody = json_decode($httpResponse->getBody()->getContents(), true);
                if (isset($responseBody['message']) || isset($responseBody['errors'])) {
                    $errorsReturned = true;
                }
            }
            $requestBody = $httpRequest->getBody()->getContents();
            $log = [
                "parent-id" => Session::get("parentId"),
                "user-id" => Session::get("id"),
                "endpoint" => $httpRequest->getMethod() . " " . $httpRequest->getUri(),
                "options" => $options,
                "requestBody" => $requestBody,
                "requestHeaders" => $options["headers"],
                "responseStatusCode" => $re->getCode(),
                "responseBody" => $responseBody,
                "errorsReturned" => $errorsReturned
            ];
            Log::error("backend.response.error", $log);
            if ($errorsReturned) {
                if ($associativeResponse)
                    return $responseBody;
                else
                    return (object)$responseBody;
            } else {
                throw $re;
            }
        }
    }

    public static function buildContext(\Throwable $throwable, array $context = []): array
    {
        $context["message"] = $throwable->getMessage();
        $context["file"] = $throwable->getFile();
        $context["line"] = $throwable->getLine();
        $context["code"] = $throwable->getCode();
        self::buildPrevious($throwable, $context);
        return $context;
    }

    public static function buildPrevious(\Throwable $throwable, array &$context, $index = 0)
    {
        $previous = $throwable->getPrevious();
        if ($previous) {
            $context["previous.$index"] = [
                "message" => $throwable->getMessage(),
                "file" => $throwable->getFile(),
                "line" => $throwable->getLine(),
                "code" => $throwable->getCode()
            ];
            self::buildPrevious($previous, $context, $index++);
        }
    }


    public static function rekeyArray( $arrDataToRekey, $key )
    {
        if( empty( $arrDataToRekey ) ) return [];
        $arrDataToReturn = [];
        foreach ($arrDataToRekey as $arrSingleData )
        {
            $arrDataToReturn[$arrSingleData->$key] = $arrSingleData;
        }
        return $arrDataToReturn;
    }

    public static function phone_number($number) {

        $number_count  = strlen((string)$number);
        if($number_count < 10)
        {
            return $number;
        }
        else
        {
        $cleaned = preg_replace('/[^[:digit:]]/', '', $number);
        preg_match('/(\d{3})(\d{3})(\d{4})/', $cleaned, $matches);
        return "({$matches[1]}) {$matches[2]}-{$matches[3]}";

        }
    }

    public static function shout(string $string) {
        return strtoupper($string);
    }

    public static function changeDateFormate($date,$date_format) {
        return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $date)->format($date_format);
    }
 public static function formatDateMMDDYYYY($date)
    {
        // Check if the date is null or '0000-00-00' and return an empty string
        if (is_null($date) || $date === '0000-00-00') {
            return '';
        }

        // Ensure the date is in Y-m-d format before formatting
        if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
            $dateParts = explode('-', $date);
            return $dateParts[1] . '/' . $dateParts[2] . '/' . $dateParts[0]; // m/d/Y format
        }

        // Return the original date if it does not match the expected format
        return $date;
    }
    public static function getFormattedDateTimeWithTimezone($datetime = null, $timezone = 'UTC')
{
    $timestamp = $datetime ? \Carbon\Carbon::parse($datetime) : now();
    return $timestamp->setTimezone($timezone)->format('d M, Y H:i A');
}
public static function formatPhone($number)
{
    // Remove any non-digit characters
    $number = preg_replace('/\D/', '', $number);

    // Format for US numbers (10 digits)
    if (strlen($number) === 10) {
        return '(' . substr($number, 0, 3) . ') ' .
                     substr($number, 3, 3) . '-' .
                     substr($number, 6);
    }

    // Format for Indian numbers (10 digits, starting with 7-9)
    if (strlen($number) === 10 && preg_match('/^[7-9]/', $number)) {
        return '+91-' . substr($number, 0, 5) . '-' . substr($number, 5);
    }

    // Format for Indian numbers with country code (91xxxxxxxxxx)
    if (strlen($number) === 12 && substr($number, 0, 2) === '91') {
        return '+91-' . substr($number, 2, 5) . '-' . substr($number, 7);
    }

    // Format for US numbers with country code (1XXXXXXXXXX)
    if (strlen($number) === 11 && substr($number, 0, 1) === '1') {
        return '+1 (' . substr($number, 1, 3) . ') ' .
                     substr($number, 4, 3) . '-' .
                     substr($number, 7);
    }

    // If format not recognized, return as is
    return $number;
}
  public static function get_timezone_from_json()
    {
        // Read the JSON file from storage
        $json = Storage::get('timezone.json');
        $timezone = json_decode($json, true)['timezone'] ?? [];

        return $timezone;
    }
}
