<?php

namespace App\Processors\Customer;

use App\Entities\Customer\ServiceEntity;
use App\Processors\Customer\{ServiceInterface, ServiceComposite, ServiceContext};
use App\Services\Customer\ServiceService;
use App\Services\Equipment\ServerService;
use App\Services\PaymentService;
use App\Services\MyLogService;
use CodeIgniter\Database\BaseConnection;
use RuntimeException;

final class ServiceV2Processor
{
  public function __construct(
    private BaseConnection $db,
    private ServiceService $serviceService,
    private ServerService  $serverService,
    private PaymentService $paymentService,
    private MyLogService   $logService,
  ) {}

  public function create(array $formDatas): ServiceEntity
  {
    $pipeline = new ServiceComposite([
      new \App\Processors\Service\CreateServiceProcessor($this->serviceService),
      new \App\Processors\Server\ServerAttachProcessor($this->serverService),
      new \App\Processors\Payment\PaymentCreateProcessor($this->serviceService, $this->paymentService),
      new \App\Processors\Log\LogProcessor($this->logService, '서비스정보 추가'),
    ]);
    return $this->runPipeline($pipeline, $formDatas);
  }

  public function modify(array $formDatas, ServiceEntity $serviceEntity): ServiceEntity
  {
    $ctx = new ServiceContext($formDatas);
    $ctx->serviceEntity = $serviceEntity;

    $pipeline = new ServiceComposite([
      new \App\Processors\Server\ServerUnsetProcessor($this->serverService),
      new \App\Processors\Service\ServiceModifyProcessor($this->serviceService),
      new \App\Processors\Server\ServerAttachProcessor($this->serverService),
      new \App\Processors\Payment\PaymentUpdateProcessor($this->serviceService, $this->paymentService),
      new \App\Processors\Log\LogProcessor($this->logService, '서비스정보 수정'),
    ]);
    return $this->runPipeline($pipeline, $formDatas, $ctx);
  }

  public function delete(ServiceEntity $serviceEntity): bool
  {
    $ctx = new ServiceContext([]);
    $ctx->serviceEntity = $serviceEntity;

    $pipeline = new ServiceComposite([
      new \App\Processors\Server\ServerUnsetProcessor($this->serverService),
      new \App\Processors\Payment\PaymentCancelProcessor($this->paymentService),
      new \App\Processors\Service\ServiceDeleteProcessor($this->serviceService),
      new \App\Processors\Log\LogProcessor($this->logService, '서비스정보 삭제'),
    ]);

    $this->runPipeline($pipeline, [], $ctx);
    return true;
  }

  private function runPipeline(ServiceComposite $pipeline, array $formDatas, ?ServiceContext $ctx = null): ServiceEntity
  {
    $this->db->transStart();

    $ctx ??= new ServiceContext($formDatas);
    $ctx = $pipeline->process($ctx);

    $this->db->transComplete();

    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }

    return $ctx->serviceEntity;
  }
}
