<?php

namespace Myvetshop\Module\Clinique\Import\Sync\Syncer;

use Myvetshop\Module\Clinique\Import\Model\AddressModel;
use Myvetshop\Module\Clinique\Import\Sync\SyncStatistics;

class AddressesSyncer
{
    protected \Db $db;

    protected function createAddress(): \Address
    {
        return new \Address();
    }

    /**
     * @return list<\Address>
     */
    protected function getAddresses(int $customerId): array
    {
        $rows = $this->db->executeS(
            'SELECT a.*'
            . ' FROM ' . _DB_PREFIX_ . 'address a'
            . ' WHERE a.id_customer = ' . $customerId
            . ' AND a.deleted = 0',
            true,
            false
        );

        if (!\is_array($rows)) {
            $rows = [];
        }

        return \ObjectModel::hydrateCollection(
            \Address::class,
            $rows
        );
    }

    /**
     * @param list<\Address> $addresses
     * @param AddressModel $addressModel
     */
    protected function getExistingAddress(array $addresses, AddressModel $addressModel): ?\Address
    {
        $potentialAddresses = \array_values(
            \array_filter(
                $addresses,
                fn (\Address $address) => (
                    \strval($address->other) === \strval($addressModel->idAddress)
                )
            )
        );

        if (\count($potentialAddresses) > 1) {
            throw new \Exception('Too much addresses for ' . $addressModel->email);
        }

        return $potentialAddresses[0] ?? null;
    }

    protected function syncAddress(
        SyncStatistics $syncStatistics,
        \Customer $customer,
        ?\Address $localAddress,
        AddressModel $addressModel
    ): \Address {
        if ($localAddress) {
            ++$syncStatistics->nbAddressesUpdated;

            return $localAddress;
        }

        $address = $this->createAddress();
        $address->id_customer = $customer->id;
        $address->id_country = $addressModel->idCountry;
        $address->alias = $addressModel->alias;
        $address->company = $addressModel->company ?? '';
        $address->lastname = $addressModel->lastname;
        $address->firstname = $addressModel->firstname;
        $address->address1 = $addressModel->address1;
        $address->address2 = $addressModel->address2 ?? '';
        $address->postcode = $addressModel->postcode;
        $address->city = $addressModel->city;
        $address->other = \strval($addressModel->idAddress);
        $address->phone = $addressModel->phone ?? '';
        $address->phone_mobile = $addressModel->phoneMobile ?? '';
        $address->vat_number = $addressModel->vatNumber ?? '';
        $address->dni = $addressModel->dni ?? '';
        $address->date_add = $addressModel->dateAdd->format('Y-m-d H:i:s');
        $address->date_upd = $addressModel->dateUpd->format('Y-m-d H:i:s');

        $address->save(false, false);

        ++$syncStatistics->nbAddressesCreated;

        return $address;
    }

    public function __construct(\Db $db)
    {
        $this->db = $db;
    }

    /**
     * @param SyncStatistics $syncStatistics
     * @param \Customer $customer
     * @param list<AddressModel> $addresses
     *
     * @return array<int, \Address>
     */
    public function sync(
        SyncStatistics $syncStatistics,
        \Customer $customer,
        array $addresses
    ): array {
        $existingAddresses = $this->getAddresses((int) $customer->id);

        $ret = [];

        foreach ($addresses as $addressModel) {
            $ret[$addressModel->idAddress] = $this->syncAddress(
                $syncStatistics,
                $customer,
                $this->getExistingAddress($existingAddresses, $addressModel),
                $addressModel
            );
        }

        return $ret;
    }
}
