<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonCommon\Classes\Installation\OrderNumber;

use Shopware\Plugins\ViisonCommon\Classes\Installation\SQLHelper;
use Zend_Db_Adapter_Abstract;

/**
 * Manage the installation of sequence number generators in s_order_number.
 */
class InstallationHelper
{

    /** @var Zend_Db_Adapter_Abstract $db */
    private $db;
    /** @var SQLHelper $sqlHelper */
    private $sqlHelper;

    public function __construct(Zend_Db_Adapter_Abstract $db)
    {
        $this->db = $db;
        $this->sqlHelper = new SQLHelper($db);
    }

    /**
     * Creates an entry in s_order_number that can be used to generate incrementing sequence numbers, e.g. using the
     * \Shopware\Components\NumberRangeIncrementer service.
     *
     * @see \Shopware\Components\NumberRangeIncrementer for how these entries will be used
     * @param string $name the name of the number range to create
     * @param integer $start the initial value of the number range. The first generated number will be $start + 1.
     * @param string $description a description for the number range that is shown in the backend.
     */
    public function createSequenceNumberGeneratorIfNotExists($name, $start, $description)
    {
        if (!$this->sqlHelper->doesRowExist('s_order_number', ['name'], [$name])) {
            $this->sqlHelper->insertIfNotExists(
                's_order_number',
                [
                    'name',
                    'number',
                    'desc',
                ],
                [
                    $name,
                    $start,
                    $description,
                ]
            );
        }
    }

    /**
     * Rename an entry in s_order_number safely (i.e. in an idempotent manner).
     *
     * @param string $oldName the current name of the sequence number generator
     * @param string $newName the desired new name of the sequence number generator
     * @param bool $updateDocuments whether to replace references to $oldName with $newName in s_core_documents.numbers
     */
    public function renameSequenceNumberGenerator($oldName, $newName, $updateDocuments = false)
    {
        if (!$this->sqlHelper->doesRowExist('s_order_number', ['name'], [$newName])) {
            $this->db->query(
                'UPDATE s_order_number
                SET name = :newName
                WHERE name = :oldName',
                [
                    ':oldName' => $oldName,
                    ':newName' => $newName,
                ]
            );
        } elseif ($this->sqlHelper->doesRowExist('s_order_number', ['name'], [$oldName])) {
            // If versions that are installed / updated include both the creation of the $oldName sequence and its
            // rename to $newName, and the install crashes after this point, the original sequence will be re-created.
            // To handle this case cleanly, delete the re-created sequence here.
            $this->db->query(
                'DELETE FROM s_order_number
                WHERE name = :oldName',
                [':oldName' => $oldName]
            );
        }

        // update documents that use this sequence to generate their document ID
        if ($updateDocuments) {
            $this->db->query(
                'UPDATE s_core_documents
                SET numbers=:newName
                WHERE numbers=:oldName',
                [
                    ':oldName' => $oldName,
                    ':newName' => $newName,
                ]
            );
        }
    }
}
