<?php

namespace WPStaging\Staging\Service\Database;

use WPStaging\Framework\Adapter\Database;
use WPStaging\Framework\Database\Exporter\AbstractRowsExporter;
use WPStaging\Framework\Database\SearchReplace;
use WPStaging\Framework\Database\TableService;
use WPStaging\Staging\Interfaces\StagingOperationDtoInterface;

/**
 * @see src\Framework\CloningProcess\Database\DatabaseCloningService for existing logic
 * @see src\Staging\Service\Database\TableCreateService for logic related to creating tables
 */
class RowsExporter extends AbstractRowsExporter
{
    const FILTER_EXCLUDE_TABLES_DATA = 'wpstg.cloning.database.exclude_tables_data';

    /**
     * Tables without prefix to exclude from data copying. If not excluded in UI or other filters these tables will be created without data.
     * @var string[]
     */
    const TABLES_EXCLUDED_FROM_DATA_COPYING = [
        'wpstg_queue',
        'wpstg_settings',
    ];

    /** @var string */
    protected $stagingPrefix;

    public function setupDatabase(Database $database)
    {
        $this->setDatabase($database);
        $this->tableService = new TableService($database);
        $this->databaseName = $this->database->getWpdba()->getClient()->__get('dbname');
    }

    public function setStagingPrefix(string $stagingPrefix)
    {
        $this->stagingPrefix = $stagingPrefix;
    }

    /**
     * @param int $tableIndex
     */
    public function setTableIndex(int $tableIndex)
    {
        if ($this->tableIndex !== $tableIndex) {
            $this->rowsExporterDto->reset();
        }

        $this->tableIndex = $tableIndex;

        if (!array_key_exists($this->tableIndex, $this->tables)) {
            throw new \RuntimeException('Table not found.');
        }

        $this->tableName = $this->tables[$this->tableIndex]['source'];
    }

    /**
     * @return void.
     */
    protected function setupSearchReplace()
    {
        $searchReplaceParams = $this->getSearchReplaceParams();
        $this->searchReplace = new SearchReplace(
            $searchReplaceParams['search'],
            $searchReplaceParams['replace'],
            true,
            []
        );
    }

    protected function getFinalPrefix()
    {
        return $this->stagingPrefix;
    }

    protected function getFinalTableName()
    {
        return $this->tables[$this->tableIndex]['destination'];
    }

    protected function getSearchReplaceParams(): array
    {
        if (!$this->jobDataDto instanceof StagingOperationDtoInterface) {
            throw new \RuntimeException('JobDataDto must be an instance of StagingOperationDtoInterface.');
        }

        $search    = $this->generateHostnamePatterns($this->getSourceHostname());
        $replace   = $this->generateHostnamePatterns($this->getHostnameWithoutScheme($this->jobDataDto->getStagingSiteUrl()));
        $search[]  = $this->getPrefix();
        $replace[] = $this->getFinalPrefix();

        return [
            'search'  => $search,
            'replace' => $replace,
        ];
    }

    /**
     * Return Hostname without scheme
     * @param string $string
     * @return string
     */
    protected function getHostnameWithoutScheme(string $string): string
    {
        return preg_replace('#^https?://#', '', rtrim($string, '/'));
    }
}
