<?php

namespace KupShop\UserBundle\Util;

use KupShop\KupShopBundle\Util\StringUtil;
use Query\Operator;

class UserImporter
{
    protected $mainIdentifier = 'id';

    /**
     * @param $xml string | \DomDocument
     */
    public function importUsers($xml)
    {
        if ($xml instanceof \DOMDocument) {
            $users = simplexml_import_dom($xml);
        } else {
            $users = simplexml_load_string($xml);
        }

        $usersArray = [];
        foreach ($users as $user) {
            if (!filter_var(trim(strval($user->EMAIL)), FILTER_VALIDATE_EMAIL)) {
                continue;
            }
            $userArray = $this->importUser($user);
            $usersArray[trim(StringUtil::normalize($userArray['email']))] = $userArray;
        }

        $existingUsers = $this->getExistingUsers($usersArray);

        foreach ($usersArray as $localUser) {
            if (!empty($localUser['groups']->GROUP)) {
                foreach ($localUser['groups']->GROUP as $group) {
                    $params = [
                        'group_id' => (string) $group->ID,
                        'email' => $localUser['email'],
                    ];
                    if ((string) $group->VALUE == 'true') {
                        sqlQuery('INSERT IGNORE INTO users_groups_relations (id_group, id_user)
                                SELECT :group_id, id
                                FROM users
                                WHERE email = :email', $params);
                    } else {
                        sqlQuery(
                            'DELETE FROM users_groups_relations
                        WHERE id_group = :group_id
                        AND id_user = (SELECT id FROM users WHERE email=:email )', $params);
                    }
                }
            }
            unset($localUser['groups']);

            $this->processUser($localUser, $existingUsers);
        }
    }

    public function importUser($user)
    {
        $userArray = [
            // INVOICE
            'name' => strval($user->INVOICE->NAME),
            'surname' => strval($user->INVOICE->SURNAME),
            'firm' => strval($user->INVOICE->COMPANY),
            'street' => strval($user->INVOICE->ADDRESS),
            'city' => strval($user->INVOICE->CITY),
            'zip' => strval($user->INVOICE->ZIP),
            'country' => strval($user->INVOICE->COUNTRY),
            'email' => trim(strval($user->EMAIL)),
            'ico' => strval($user->INVOICE->ICO),
            'dic' => strval($user->INVOICE->DIC),
            'phone' => strval($user->INVOICE->PHONE),
            'custom_address' => strval($user->INVOICE->ADDRESS2),
            'state' => strval($user->INVOICE->STATE),

            // DELIVERY
            'delivery_name' => strval($user->DELIVERY->NAME),
            'delivery_surname' => strval($user->DELIVERY->SURNAME),
            'delivery_firm' => strval($user->DELIVERY->COMPANY),
            'delivery_street' => strval($user->DELIVERY->ADDRESS),
            'delivery_city' => strval($user->DELIVERY->CITY),
            'delivery_zip' => strval($user->DELIVERY->ZIP),
            'delivery_country' => strval($user->DELIVERY->COUNTRY),
            'delivery_phone' => strval($user->DELIVERY->PHONE),
            'delivery_custom_address' => strval($user->DELIVERY->ADDRESS2),
            'delivery_state' => strval($user->DELIVERY->STATE),

            // DATE
            'date_reg' => strval($user->DATE->REG),
            'date_subscribe' => strval($user->DATE->SUBSCRIBE),
            'date_unsubscribe' => strval($user->DATE->UNSUBSCRIBE),
            'groups' => $user->GROUPS,
        ];

        $this->addAdditionalFields($userArray, $user);

        return $userArray;
    }

    protected function getExistingUsers($usersArray)
    {
        $identifierArray = array_column($usersArray, $this->mainIdentifier);
        $emailsArray = array_column($usersArray, 'email');

        $myUsers = $this->selectExistingUsers($emailsArray, $identifierArray);

        $convertedUsers = [];
        foreach ($myUsers as $user) {
            $convertedUsers[trim(StringUtil::normalize($user['email']))] = $user[$this->mainIdentifier];
        }

        return $convertedUsers;
    }

    protected function selectExistingUsers($emailsArray, $identifierArray)
    {
        return sqlQueryBuilder()
            ->select($this->mainIdentifier.',email')
            ->from('users')
            ->andWhere(Operator::orX(Operator::inStringArray($emailsArray, 'email'), Operator::inIntArray($identifierArray, $this->mainIdentifier)))
            ->execute()
            ->fetchAll();
    }

    protected function addAdditionalFields(&$userArray, \SimpleXMLElement $user)
    {
    }

    protected function insertUserAction($userId)
    {
    }

    protected function processUser(array $localUser, array $existingUsers): void
    {
        if (array_key_exists(trim(StringUtil::normalize($localUser['email'])), $existingUsers)) {
            sqlQueryBuilder()
                ->update('users')
                ->directValues($localUser)
                ->andWhere(Operator::equals(['email' => $localUser['email']]))
                ->execute();
        } elseif (array_key_exists($this->mainIdentifier, $localUser) && in_array($localUser[$this->mainIdentifier], $existingUsers)) {
            sqlQueryBuilder()
                ->update('users')
                ->directValues($localUser)
                ->andWhere(Operator::equals([$this->mainIdentifier => $localUser[$this->mainIdentifier]]))
                ->execute();
        } else {
            $this->beforeInsertUserAction($localUser);
            sqlQueryBuilder()
                ->insert('users')
                ->directValues($localUser)
                ->execute();
            $userId = sqlInsertId();
            $this->insertUserAction($userId);
        }
    }

    protected function beforeInsertUserAction($userRow)
    {
    }
}
