<?php

namespace App\Processors\Equipment;

use App\Entities\Equipment\ServerEntity;
use App\Entities\Equipment\ServerPartEntity;
use App\Services\Equipment\ServerPartService;
use App\Services\Equipment\ServerService;
use App\Services\MyLogService;
use App\Services\Part\IPService;
use App\Services\Part\SWITCHService;
use App\Services\PaymentService;
use CodeIgniter\Database\BaseConnection;
use RuntimeException;

class ServerPartV1Processor
{
  public function __construct(
    private BaseConnection $db,
    private ServerPartService $service,
    private ServerService $serverService,
    private PaymentService $paymentService,
    private IPService $ipService,
    private SWITCHService $switchService,
    private MyLogService $logService,
  ) {}

  public function create(array $formDatas): ServerPartEntity
  {
    //서버정보가져오기
    if (!array_key_exists('serverinfo_uid', $formDatas)) {
      throw new \Exception(__METHOD__ . "에서 오류발생: 서버 정보가 지정되지 않았습니다.");
    }
    $serverEntity = $this->serverService->getEntity($formDatas['serverinfo_uid']);
    if (!$serverEntity instanceof ServerEntity) {
      throw new \Exception(__METHOD__ . "에서 오류발생: {$formDatas['serverinfo_uid']} 서버 정보를 찾을수 없습니다.");
    }
    //서비스정의확인(기본은 제외)
    if ($formDatas['billing'] !== PAYMENT['BILLING']['BASE'] && $serverEntity->getServiceInfoUID() === null) {
      throw new \Exception(__METHOD__ . "에서 오류발생:서비스가 지정되어야 작업이 가능합니다.");
    }
    $this->db->transStart();
    // 1) 생성작업
    $formDatas["clientinfo_uid"]  = $serverEntity->getClientInfoUID();
    $formDatas["serviceinfo_uid"]  = $serverEntity->getServiceInfoUID();
    $formDatas["serverinfo_uid"] = $serverEntity->getPK();
    $entity = $this->service->getModel()->create($formDatas);
    // 2) Type에 따른 각 파트 정의
    $this->service->getPartService($entity->getType())->attachToServerPart($entity);
    // 3) 과금정의
    $this->service->setAmount($entity,  "createForServerPart");
    // 4) 로그
    $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 modify(ServerPartEntity $entity, array $formDatas): ServerPartEntity
  {
    //서버정보가져오기
    if (!array_key_exists('serverinfo_uid', $formDatas)) {
      throw new \Exception(__METHOD__ . "에서 오류발생: 서버 정보가 지정되지 않았습니다.");
    }
    $this->db->transStart();
    // 1) 수정전 정보
    //파트값이 정의되어 있으면
    $isChangedPart = false;
    //기존파트값과 다르면
    if ($entity->getPartUID() != $formDatas['part_uid']) {
      //기존 Part_UID값과 다르고 기존 Part_UID값이 있으면 해지
      if ($entity->getPartUID()) {
        $this->service->getPartService($entity->getType())->detachFromServerPart($entity);
      }
      $isChangedPart = true;
    }
    // 2) 서버연결정보 수정
    $serverEntity = $this->serverService->getEntity($formDatas['serverinfo_uid']);
    if (!$serverEntity instanceof ServerEntity) {
      throw new \Exception(__METHOD__ . "에서 오류발생: {$formDatas['serverinfo_uid']} 서버 정보를 찾을수 없습니다.");
    }
    $formDatas["clientinfo_uid"]  = $serverEntity->getClientInfoUID();
    $formDatas["serviceinfo_uid"]  = $serverEntity->getServiceInfoUID();
    $formDatas["serverinfo_uid"] = $serverEntity->getPK();
    $entity = $this->service->getModel()->modify($entity, $formDatas);
    // 3) Part_UID값이 있고 신규값인경우
    if ($entity->getPartUID() && $isChangedPart) {
      $this->service->getPartService($entity->getType())->attachToServerPart($entity);
    }
    // 3) 과금정의
    $this->service->setAmount($entity,  "updateForServerPart");
    // 4) 로그
    $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(ServerPartEntity $entity): ServerPartEntity
  {
    $this->db->transStart();
    // 1) 기존파트값이 있으면 해지
    if ($entity->getPartUID() != null) {
      $this->service->getPartService($entity->getType())->detachFromServerPart($entity);
    }
    // 2) 서버파트정보 삭제
    $serverEntity = $this->serverService->getEntity($entity->getServerInfoUID());
    if (!$serverEntity instanceof ServerEntity) {
      throw new \Exception(__METHOD__ . "에서 오류발생: {$entity->getServerInfoUID()} 서버 정보를 찾을수 없습니다.");
    }
    $this->service->getModel()->delete($entity->getPK());
    // 3) 과금정의
    $this->service->setAmount($entity, "unlinkFromServerPart");
    // 4) 로그
    $this->logService->create(formDatas: [
      'title'  => "{$entity->getTitle()} 서버파트 삭제",
      'status' => $entity->getStatus(),
    ]);
    $this->db->transComplete();
    if ($this->db->transStatus() === false) {
      throw new RuntimeException('트랜잭션 실패');
    }
    return $entity;
  }
}
