<?php

namespace App\Services;

use App\Crm\Config\BrevoConfig;
use Brevo\Client\Api\ContactsApi;
use Brevo\Client\ApiException;
use Brevo\Client\Configuration;
use Brevo\Client\Model\CreateContact;
use GuzzleHttp\Client;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Mtc\Crm\Contracts\EnquiryActionModel;
use Mtc\Crm\Contracts\EnquiryModel;
use Mtc\Crm\Models\FormQuestion;
use Mtc\MercuryDataModels\Vehicle;

class BrevoApi
{
    /**
     * Brevo Contacts API
     *
     * @var ContactsApi
     */
    private readonly ContactsApi $api_instance;

    /**
     * Stores the response message.
     *
     * @var string|null
     */
    protected ?string $responseMessage = null;

    public function __construct(
        protected readonly BrevoConfig $config,
        ?Client $httpClient = null,
        ?ContactsApi $contactsApi = null
    ) {
        $httpClient ??= new Client();
        $this->api_instance = $contactsApi ?? new ContactsApi(
            $httpClient,
            Configuration::getDefaultConfiguration()->setApiKey('api-key', $this->config->apiKey())
        );
    }

    public function addCustomerToBrevo(EnquiryModel $enquiry, EnquiryActionModel $action): bool
    {
        $createContact = $this->createContactFromEnquiry($enquiry, $action);
        $success = false;
        try {
            $this->api_instance->createContact($createContact);
            $success = true;
            $this->responseMessage = sprintf(
                'Contact with email %s has been successfully created and added to the following list(s): %s.',
                $createContact->getEmail(),
                implode(', ', $createContact->getListIds())
            );
        } catch (ApiException $exception) {
            $response = json_decode((string) $exception->getResponseBody());
            $this->responseMessage = $response->message;
        } catch (\Exception $exception) {
            Log::error('Exception: ' . $exception->getMessage());
        } finally {
            return $success;
        }
    }

    protected function createContactFromEnquiry(EnquiryModel $enquiry, EnquiryActionModel $action): CreateContact
    {
        $enquiryParams = $this->getEnquiryParams($enquiry);
        $attributes = $enquiryParams
            ->except('EMAIL')
            ->toArray();

        $createContact = new CreateContact();
        $createContact->setAttributes((object)$attributes);
        $createContact->setEmail($enquiryParams->has('EMAIL') ? $enquiryParams->get('EMAIL') : $enquiry->email);
        if (isset($action->data['brevo_update_enabled'])) {
            $createContact->setUpdateEnabled((bool)$action->data['brevo_update_enabled']);
        }
        if (isset($action->data['brevo_list_id'])) {
            $createContact->setListIds([(int)$action->data['brevo_list_id']]);
        }

        return $createContact;
    }

    protected function getEnquiryParams(EnquiryModel $enquiry): Collection
    {
        $answers = $enquiry->getNormalizedAnswers()->keyBy('question_id')->map(fn ($item) => $item['answer']);
        return FormQuestion::query()
            ->whereIn('id', $answers->keys())
            ->get()
            ->keyBy('id')
            ->map(fn ($question) => $question->data['brevo-field'] ?? null)
            ->filter()
            ->flip()
            ->map(function ($id, $key) use ($answers, $enquiry) {
                if ($key === 'VEHICLE_MODEL' && $enquiry->reason_type === 'vehicle') {
                    return Vehicle::find($answers[$id] ?? null)?->title;
                }
                return $answers[$id] ?? null;
            });
    }

    /**
     * Gets the response message from the last API call.
     *
     * @return string|null The response message or null if not set.
     */
    public function getResponseMessage(): ?string
    {
        return $this->responseMessage;
    }
}
