<?php

namespace App\Processors\Customer;

use App\Entities\Customer\ServiceEntity;
use App\Entities\Equipment\ServerEntity;
use App\Services\Customer\ServiceService;
use App\Services\Equipment\ServerService;
use App\Services\MyLogService;
use App\Services\PaymentService;
use CodeIgniter\Database\BaseConnection;
use RuntimeException;

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

  public function create(array $formDatas): ServiceEntity
  {
    $this->db->transStart();
    // 1) 서비스 생성
    $entity = $this->service->getModel()->create($formDatas);
    // 2) 서버 연결 
    $serverEntity = $this->serverService->attachToService(
      $entity,
      $entity->getServerInfoUID()
    );
    // 3) 결제정보반영
    $this->service->setAmount(
      $entity,
      $this->serverService->getCalculatedAmount($serverEntity),
      'createForService'
    );
    // 4) 서비스 FK 동기화
    $entity = $this->service->getModel()->modify($entity, [
      'title'         => $entity->getTitle(),
      'serverinfo_id' => $serverEntity->getPK(),
    ]);
    // 6) 로그
    $this->logService->create([
      'title'  => "{$entity->getTitle()} 서비스 추가",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }

  public function modify(ServiceEntity $entity, array $formDatas): ServiceEntity
  {
    $this->db->transStart();
    // 서버 변경이면 기존 서버 해지
    if ($entity->getServerInfoUID() !== null && $entity->getServerInfoUID() != $formDatas['serverinfo_uid']) {
      $this->serverService->detachFromService($entity->getServerInfoUID());
    }
    // 1) 서비스 정보 수정
    $entity = $this->service->getModel()->modify($entity, $formDatas);
    // 2) 서버 재지정
    $serverEntity = $this->serverService->attachToService(
      $entity,
      $entity->getServerInfoUID()
    );
    // 3) 결제정보반영
    $this->service->setAmount(
      $entity,
      $this->serverService->getCalculatedAmount($serverEntity)
    );
    // 5) 서비스 FK 동기화
    $entity = $this->service->getModel()->modify($entity, [
      'title'         => $entity->getTitle(),
      'serverinfo_id' => $serverEntity->getPK()
    ]);
    // 6) 로그
    $this->logService->create(formDatas: [
      'title'  => "{$entity->getTitle()} 서비스 수정",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }

  public function delete(ServiceEntity $entity): ServiceEntity
  {
    $this->db->transStart();
    // 1) 결제 분리
    if ($entity->getPaymentUID()) {
      $this->paymentService->unlinkFromService($entity);
    }
    // 2) 연결된 모든 서버 해지
    foreach ($this->serverService->getEntities(['serviceinfo_uid' => $entity->getPK()]) as $serverEntity) {
      $this->serverService->detachFromService($serverEntity->getPK());
    }
    // 3) 서비스 삭제
    $this->service->getModel()->delete($entity->getPK());
    // 4) 결제정보 반영(서비스번호,서버번호 Null처리)
    $this->paymentService->unlinkFromService($entity);
    // 4) 로그
    $this->logService->create([
      'title'  => "[{$entity->getTitle()}] 서비스 해지",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }

  public function addeAlternativeServer(ServiceEntity $entity, string $serverinfo_uid): ServiceEntity
  {
    if (!$serverinfo_uid) {
      throw new \Exception("대체 서버의 UID[{$serverinfo_uid}]값이 비정상적입니다.");
    }

    $this->db->transStart();
    // 1) 대체서버 추가
    $this->serverService->attachToService(
      $entity,
      $serverinfo_uid,
      [
        'type' => SERVER['TYPES']['ALTERNATIVE'],
      ]
    );
    // 2) 로그
    $this->logService->create([
      'title'  => "[{$entity->getTitle()}] 대체서버 추가",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }
  public function replaceMainServer(ServiceEntity $entity, string $serverinfo_uid): ServiceEntity
  {
    $this->db->transStart();
    // 1) 기존 메인서버정보 가져오기
    $oldServerEntity = $this->serverService->getEntity($entity->getServerInfoUID());
    if (!$oldServerEntity instanceof ServerEntity) {
      throw new \Exception(__METHOD__ . "에서 오류발생: {$entity->getServerInfoUID()}에 대한 서버정보를 찾을수 없습니다.");
    }
    // 2) 대체서버 형식 변경
    $serverEntity = $this->serverService->attachToService(
      $entity,
      $serverinfo_uid,
      ['type' => $oldServerEntity->getType()]
    );
    // 3) 서비스 메인서버 변경
    $entity = $this->service->getModel()->modify($entity, [
      'title'         => $serverEntity->getCustomTitle(),
      'serverinfo_uid' => $serverEntity->getPK()
    ]);
    // 4) 결제정보반영
    $this->service->setAmount(
      $entity,
      $this->serverService->getCalculatedAmount($serverEntity)
    );
    // 5) 로그
    $this->logService->create([
      'title'  => "{$oldServerEntity->getCustomTitle()}=>{$serverEntity->getCustomTitle()} 메인서버변경",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }

  public function terminateServer(ServiceEntity $entity, string $serverinfo_uid): ServiceEntity
  {
    if ($entity->getServerInfoUID() === $serverinfo_uid) {
      throw new \Exception(__METHOD__ . "에서 오류발생: 서비스의 메인 서버정보는 해지할 수 없습니다.");
    }
    $this->db->transStart();
    $this->serverService->detachFromService($serverinfo_uid);
    // 4) 로그
    $this->logService->create([
      'title'  => "[{$entity->getTitle()}] 대체서버 해지",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }
}
