<?php

namespace App\Services;

use App\Models\CompanyApi;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;

class GuzzleHttpService
{
    protected $baseUri = '';
    protected $client;
    private $token;

    public function __construct(ClientInterface $client = null, ?int $companyId = null){
        if ($client !== null) {
            $this->client = $client;
            return;
        }

        $resolvedCompanyId = $companyId ?? optional(auth()->user())->company_id;
        $companyApi = CompanyApi::where('company_id', $resolvedCompanyId)
            ->where('status', 1)
            ->first();
        if (!isset($companyApi)){
            return;
        }

        $this->client = new Client([
            'base_uri' => $companyApi->uri,
            'timeout' => 2.0,
            'cookies' => true,
            'headers' => [
                'User-Agent' => app()->environment() . '-bukkenkanri.com/1.0',
                'Accept' => 'application/json',
                'Authorization' => "Bearer " . $this->token
            ]
        ]);
    }

    public function getRequest($url, $params){
        if (!isset($this->client)){
            return  [];
        }
        try {
            return $this->client->request('GET', $url, ['query'=> $params]);
        }catch (ClientException $e) {

        }catch (RequestException $rq){

        }catch (\Exception $e){
        }
        return [];
    }

    public function postRequest($url, $data){
        if (!isset($this->client)){
            return  [];
        }
        if($data instanceof Collection)
            $data = $data->toArray();

        $data = $this->normalizeDates($data);

        try {
           $res = $this->client->request('POST', $url, [
                'json' => $data
            ]);
           return $res->getBody();
        }catch (ClientException $e) {
            Log::debug(json_encode($e->getMessage()));
        }catch (RequestException $rq){
            //dd($rq);
            Log::debug(json_encode($rq->getMessage()));
        }catch (\Exception $e){
            Log::debug(json_encode($e->getMessage()));
        }
        return [];
    }

    public function postMansionRequest($url, $data): SiteSyncResult
    {
        if ($data instanceof Collection) {
            $data = $data->toArray();
        } elseif (is_object($data) && method_exists($data, 'toArray')) {
            $data = $data->toArray();
        }
        if (is_array($data)) {
            $data = $this->normalizeDates($data);
        }

        $context = [
            'endpoint' => $url,
            'company_id' => is_array($data) ? ($data['company_id'] ?? null) : null,
            'building_id' => is_array($data) ? ($data['building_id'] ?? basename($url)) : basename($url),
        ];

        if (!isset($this->client)) {
            Log::warning('Mansion site synchronization is not configured', $context);
            return SiteSyncResult::failure(null, 'Site API is not configured.');
        }

        try {
            $response = $this->client->request('POST', $url, ['json' => $data]);
            $statusCode = $response->getStatusCode();

            if ($statusCode >= 200 && $statusCode < 300) {
                return SiteSyncResult::success($statusCode);
            }

            Log::error('Mansion site synchronization returned an error', $context + [
                'status' => $statusCode,
            ]);
            return SiteSyncResult::failure($statusCode, 'Site synchronization failed.');
        } catch (RequestException $exception) {
            $statusCode = $exception->hasResponse() ? $exception->getResponse()->getStatusCode() : null;
            Log::error('Mansion site synchronization request failed', $context + [
                'status' => $statusCode,
                'exception' => get_class($exception),
                'exception_message' => $exception->getMessage(),
            ]);
            return SiteSyncResult::failure($statusCode, 'Site synchronization failed.');
        } catch (\Throwable $exception) {
            Log::error('Mansion site synchronization failed', $context + [
                'status' => null,
                'exception' => get_class($exception),
                'exception_message' => $exception->getMessage(),
            ]);
            return SiteSyncResult::failure(null, 'Site synchronization failed.');
        }
    }

    private function normalizeDates($data)
    {
        $dateFields = [
            'created_at', 'updated_at', 'close_date', 'from_event', 'to_event',
            'parking_yes_cost_date', 'conf_day', 'parking_out_cost_date',
        ];

        foreach ($dateFields as $field) {
            if (isset($data[$field]) && (strtotime($data[$field]) < 0 || strtotime($data[$field]) == false)) {
                $data[$field] = null;
            }
        }

        return $data;
    }
}
