<?php
/**
 * SimplyIN Payment Module
 *
 * Orlen shipping module integrator for setting pickup point extension attributes.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Model\Integrator;

use Magento\Framework\Module\Manager as ModuleManager;
use Magento\Quote\Api\Data\CartInterface;
use Psr\Log\LoggerInterface;
use Simplyin\Payment\Api\IntegratorInterface;

/**
 * Class OrlenIntegrator
 *
 * Handles integration with the Macopedia/OrlenShipping module.
 * Sets the orlenpaczka_destination_code and orlenpaczka_point_details
 * extension attributes on quotes when a user selects an Orlen pickup point.
 *
 * @see Requirements 3.1, 3.2, 3.3, 3.4
 */
class OrlenIntegrator implements IntegratorInterface
{
    /**
     * Module name for Macopedia OrlenShipping
     */
    private const MODULE_NAME = 'Macopedia_OrlenShipping';

    /**
     * Extension attribute name for Orlen destination code
     */
    private const EXTENSION_ATTRIBUTE_DESTINATION_CODE = 'orlenpaczka_destination_code';

    /**
     * Extension attribute name for Orlen point details
     */
    private const EXTENSION_ATTRIBUTE_POINT_DETAILS = 'orlenpaczka_point_details';

    /**
     * @var ModuleManager
     */
    private ModuleManager $moduleManager;

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

    /**
     * Constructor
     *
     * @param ModuleManager $moduleManager
     * @param LoggerInterface $logger
     */
    public function __construct(
        ModuleManager $moduleManager,
        LoggerInterface $logger
    ) {
        $this->moduleManager = $moduleManager;
        $this->logger = $logger;
    }

    /**
     * Check if the Macopedia/OrlenShipping module is available and enabled
     *
     * @return bool True if the Macopedia_OrlenShipping module is installed and active
     */
    public function isAvailable(): bool
    {
        return $this->moduleManager->isEnabled(self::MODULE_NAME);
    }

    /**
     * Set the Orlen pickup point data on the quote
     *
     * Extracts the destination code from the lockerId field and sets it as
     * the orlenpaczka_destination_code extension attribute. Also sets the
     * orlenpaczka_point_details with address/description information.
     *
     * @param CartInterface $quote The quote to set pickup point data on
     * @param array $data Pickup point data containing:
     *                    - lockerId: string - The Orlen destination code
     *                    - address: string - The pickup point address (optional)
     *                    - addressName: string - Human-readable name (optional)
     *                    - desc: string - Description (optional)
     * @return bool True if the pickup point data was successfully set
     */
    public function setPickupPoint(CartInterface $quote, array $data): bool
    {
        if (!$this->isAvailable()) {
            $this->logger->info(
                'OrlenIntegrator: Macopedia_OrlenShipping module is not enabled, skipping integration'
            );
            return false;
        }

        if (!isset($data['lockerId']) || empty($data['lockerId'])) {
            $this->logger->warning(
                'OrlenIntegrator: Missing or empty lockerId in pickup point data'
            );
            return false;
        }

        $destinationCode = (string) $data['lockerId'];
        $pointDetails = $this->buildPointDetails($data);

        try {
            $extensionAttributes = $quote->getExtensionAttributes();
            
            if ($extensionAttributes === null) {
                $this->logger->warning(
                    'OrlenIntegrator: Unable to get extension attributes from quote'
                );
                return false;
            }

            // Set the orlenpaczka_destination_code extension attribute
            $extensionAttributes->setOrlenpaczkaDestinationCode($destinationCode);
            
            // Set the orlenpaczka_point_details extension attribute
            $extensionAttributes->setOrlenpaczkaPointDetails($pointDetails);
            
            $quote->setExtensionAttributes($extensionAttributes);

            $this->logger->info(
                sprintf(
                    'OrlenIntegrator: Successfully set orlenpaczka_destination_code "%s" and point_details on quote %s',
                    $destinationCode,
                    $quote->getId() ?? 'new'
                )
            );

            return true;
        } catch (\Exception $e) {
            $this->logger->error(
                sprintf(
                    'OrlenIntegrator: Failed to set Orlen pickup point data: %s',
                    $e->getMessage()
                )
            );
            return false;
        }
    }

    /**
     * Build point details string from pickup point data
     *
     * Combines available address information into a human-readable string
     * for the orlenpaczka_point_details extension attribute.
     *
     * @param array $data Pickup point data
     * @return string Point details string
     */
    private function buildPointDetails(array $data): string
    {
        $parts = [];

        // Add address name if available
        if (!empty($data['addressName'])) {
            $parts[] = $data['addressName'];
        }

        // Add address if available
        if (!empty($data['address'])) {
            $parts[] = $data['address'];
        }

        // Add city and postal code if available
        $locationParts = [];
        if (!empty($data['postalCode'])) {
            $locationParts[] = $data['postalCode'];
        }
        if (!empty($data['city'])) {
            $locationParts[] = $data['city'];
        }
        if (!empty($locationParts)) {
            $parts[] = implode(' ', $locationParts);
        }

        // Add description if available and not already included
        if (!empty($data['desc']) && !in_array($data['desc'], $parts)) {
            $parts[] = $data['desc'];
        }

        return implode(', ', array_filter($parts));
    }

    /**
     * Get the provider names this integrator handles
     *
     * @return array List containing 'orlen' and 'orlenpaczka'
     */
    public function getProviderNames(): array
    {
        return ['orlen', 'orlenpaczka'];
    }
}
