<?php
namespace PortalPeople\GetAddressAutocomplete\Model;

use PortalPeople\GetAddressAutocomplete\Api\AddressAutocompleteInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\HTTP\ZendClientFactory;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Checkout\Model\Session as CheckoutSession;
use Psr\Log\LoggerInterface;

class AddressAutocompleteManagement implements AddressAutocompleteInterface
{
    const XML_PATH_API_KEY = 'checkout/getaddress_autocomplete/api_key';
    const XML_PATH_ENABLED = 'checkout/getaddress_autocomplete/enabled';
    const GETADDRESS_API_URL = 'https://api.getaddress.io/find/';

    protected $scopeConfig;
    protected $httpClientFactory;
    protected $cartRepository;
    protected $checkoutSession;
    protected $logger;

    public function __construct(
        ScopeConfigInterface $scopeConfig,
        ZendClientFactory $httpClientFactory,
        CartRepositoryInterface $cartRepository,
        CheckoutSession $checkoutSession,
        LoggerInterface $logger
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->httpClientFactory = $httpClientFactory;
        $this->cartRepository = $cartRepository;
        $this->checkoutSession = $checkoutSession;
        $this->logger = $logger;
    }

    /**
     * Search for addresses by postcode or text
     *
     * @param string $searchTerm
     * @return array
     */
    public function searchAddresses($searchTerm)
    {
        try {
            $apiKey = $this->getApiKey();
            if (!$apiKey) {
                $this->logger->error('GetAddress.io API key not configured');
                return ['success' => false, 'error' => 'API key not configured'];
            }

            $url = self::GETADDRESS_API_URL . urlencode($searchTerm) . '?api-key=' . $apiKey;
            
            $client = $this->httpClientFactory->create();
            $client->setUri($url);
            $client->setMethod('GET');
            $client->setConfig(['timeout' => 10]);
            
            $response = $client->request();
            $body = $response->getBody();
            
            $this->logger->info('GetAddress.io search response: ' . substr($body, 0, 200));
            
            $result = json_decode($body, true);
            
            if (isset($result['Addresses'])) {
                return [
                    'success' => true,
                    'addresses' => $result['Addresses']
                ];
            }
            
            return [
                'success' => false,
                'error' => isset($result['Message']) ? $result['Message'] : 'No addresses found'
            ];
            
        } catch (\Exception $e) {
            $this->logger->error('GetAddress.io search error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    /**
     * Get complete address details
     *
     * @param string $addressId
     * @return array
     */
    public function getAddressDetails($addressId)
    {
        try {
            $apiKey = $this->getApiKey();
            if (!$apiKey) {
                return ['success' => false, 'error' => 'API key not configured'];
            }

            // addressId contains postcode and part of address (format: postcode|building_name_or_number)
            list($postcode, $addressPart) = explode('|', $addressId);
            
            $url = self::GETADDRESS_API_URL . urlencode($postcode) . '?api-key=' . $apiKey;
            
            $client = $this->httpClientFactory->create();
            $client->setUri($url);
            $client->setMethod('GET');
            $client->setConfig(['timeout' => 10]);
            
            $response = $client->request();
            $body = $response->getBody();
            $result = json_decode($body, true);
            
            if (isset($result['Addresses'])) {
                return [
                    'success' => true,
                    'addresses' => $result['Addresses']
                ];
            }
            
            return [
                'success' => false,
                'error' => isset($result['Message']) ? $result['Message'] : 'Address not found'
            ];
            
        } catch (\Exception $e) {
            $this->logger->error('GetAddress.io details error: ' . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    /**
     * Validate and save address to quote
     *
     * @param string $postcode
     * @param int $udprn
     * @param string $organisation
     * @param string $building
     * @param string $street
     * @param string $city
     * @param string $county
     * @return bool
     */
    public function saveAddress($postcode, $udprn, $organisation = '', $building = '', $street = '', $city = '', $county = '')
    {
        try {
            $quote = $this->checkoutSession->getQuote();
            
            if ($quote && $quote->getId()) {
                $shippingAddress = $quote->getShippingAddress();
                
                // Save address components
                if ($postcode) {
                    $shippingAddress->setPostcode($postcode);
                }
                
                if ($street) {
                    $shippingAddress->setStreet([$street]);
                }
                
                if ($city) {
                    $shippingAddress->setCity($city);
                }
                
                if ($organisation) {
                    $shippingAddress->setCompany($organisation);
                }
                
                // Save extension attributes
                $extensionAttributes = $shippingAddress->getExtensionAttributes();
                if (!$extensionAttributes) {
                    $extensionAttributes = $shippingAddress->getExtensionAttributes();
                }
                
                $extensionAttributes->setGetaddressAddressId($udprn);
                $extensionAttributes->setGetaddressPostcode($postcode);
                $extensionAttributes->setGetaddressValidated(true);
                
                $shippingAddress->setExtensionAttributes($extensionAttributes);
                
                $this->cartRepository->save($quote);
                $this->logger->info('Address saved for quote ID: ' . $quote->getId());
                
                return true;
            }
            
            return false;
        } catch (\Exception $e) {
            $this->logger->error('Error saving address: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Get API key from configuration
     *
     * @return string|null
     */
    protected function getApiKey()
    {
        return $this->scopeConfig->getValue(
            self::XML_PATH_API_KEY,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );
    }

    /**
     * Check if module is enabled
     *
     * @return bool
     */
    public function isEnabled()
    {
        return (bool)$this->scopeConfig->getValue(
            self::XML_PATH_ENABLED,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );
    }
}
