<?php

namespace App\Controllers\CLI\DBMigration;

use App\Controllers\BaseController;
use CodeIgniter\Database\BaseConnection;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
use App\Libraries\DBMigration\Process\ClientProcess;
use App\Libraries\DBMigration\Process\LineProcess;
use App\Libraries\DBMigration\Process\ServerCodeProcess;
use App\Libraries\DBMigration\Process\SwitchCodeProcess;
use App\Libraries\DBMigration\Process\PartCodeProcess;
use App\Libraries\DBMigration\Process\MigrationProcessInterface;

abstract class DBMigration extends BaseController
{
    private $_targetDB = null;

    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
    }

    abstract protected function getSourceDB(): BaseConnection;
    abstract protected function getClient(): array;
    abstract protected function getLine(): array;
    abstract protected function getServerCode(): array;
    abstract protected function getSwitchCode(): array;
    abstract protected function getPartCode(): array;

    final protected function getTargetDB(): BaseConnection
    {
        if ($this->_targetDB === null) {
            $this->_targetDB = \Config\Database::connect('default');
        }
        return $this->_targetDB;
    }

    /**
     * 공통 마이그레이션 처리 로직
     */
    private function migration(MigrationProcessInterface $processor, array $rows, string $functionName): void
    {
        $this->getTargetDB()->transStart();
        try {
            $cnt = 1;
            foreach ($rows as $row) {
                $processor->process($row, $cnt);
                $cnt++;
            }
            echo "{$functionName} 작업을 완료하였습니다.";
            $this->getTargetDB()->transCommit();
        } catch (\Exception $e) {
            $this->getTargetDB()->transRollback();
            echo "{$functionName} 작업을 실패하였습니다.\n--------------\n" . $e->getMessage() . "\n--------------\n";
        }
    }

    final public function client(): void
    {
        $this->migration(
            new ClientProcess($this->getTargetDB()),
            $this->getClient(),
            __FUNCTION__
        );
    }

    final public function line(): void
    {
        $this->migration(
            new LineProcess($this->getTargetDB()),
            $this->getLine(),
            __FUNCTION__
        );
    }

    final public function servercode(): void
    {
        $this->migration(
            new ServerCodeProcess($this->getTargetDB()),
            $this->getServerCode(),
            __FUNCTION__
        );
    }

    final public function switchcode(): void
    {
        $this->migration(
            new SwitchCodeProcess($this->getTargetDB()),
            $this->getSwitchCode(),
            __FUNCTION__
        );
    }
    final public function partcode(): void
    {
        $this->migration(
            new PartCodeProcess($this->getTargetDB()),
            $this->getPartCode(),
            __FUNCTION__
        );
    }
}
