<?php
// =========================================================
// AbstractCRUDController.php  (FINAL)
// - 모든 "결과/리다이렉트"는 RedirectResponse|ResponseInterface로 엄격 정리
// - create/modify/delete/view/create_form/modify_form 모두 runAction 적용
// - delete_result_process도 정책에 맞게 RedirectResponse|ResponseInterface로 정리
// =========================================================

namespace App\Controllers;

use RuntimeException;
use Psr\Log\LoggerInterface;
use App\Entities\CommonEntity;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

/**
 * AbstractCRUDController
 * 단일 레코드 생성(C), 조회(R), 수정(U), 삭제(D) 로직을 담당합니다. (SRP: Single Record Management)
 */
abstract class AbstractCRUDController extends AbstractWebController
{
  public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
  {
    parent::initController($request, $response, $logger);
  }

  // =========================================================
  // CRUD 공통 보조
  // =========================================================

  protected function assertUid($uid, string $action): void
  {
    if (!$uid) {
      throw new RuntimeException(static::class . '->' . $action . "에서 {$this->getTitle()}에 번호가 정의 되지 않았습니다.");
    }
  }

  protected function assertEntityClass(CommonEntity $entity, string $action): void
  {
    $entityClass = $this->service->getEntityClass();
    if (!$entity instanceof $entityClass) {
      throw new RuntimeException(static::class . '->' . $action . "에서 오류발생:Return Type은 {$entityClass}만 가능");
    }
  }

  protected function buildViewRedirectUrl(CommonEntity $entity): string
  {
    return '/' . implode('/', [...$this->getActionPaths(), 'view']) . '/' . $entity->getPK();
  }

  protected function buildListRedirectUrl(): string
  {
    return implode(DIRECTORY_SEPARATOR, $this->getActionPaths());
  }

  // =========================================================
  // Create Form
  // =========================================================

  protected function create_form_process(array $formDatas = []): array
  {
    return $this->request->getVar();
  }

  public function create_form(): string|RedirectResponse|ResponseInterface
  {
    $action = __FUNCTION__;

    return $this->runAction($action, function () use ($action) {
      $formDatas = $this->create_form_process();
      $this->action_init_process($action, $formDatas);
      $this->addViewDatas('formDatas', $formDatas);
      return $this->action_render_process($action, $this->getViewDatas(), $this->request->getVar('ActionTemplate'));
    });
  }

  // =========================================================
  // Create
  // =========================================================

  protected function create_process(array $formDatas): CommonEntity
  {
    return $this->service->create($formDatas);
  }

  final public function create(): RedirectResponse|ResponseInterface|string
  {
    $action = __FUNCTION__;

    return $this->runAction($action, function () use ($action) {
      $this->action_init_process($action);

      $entity = $this->create_process($this->request->getPost());
      $this->assertEntityClass($entity, $action);

      $message = "{$this->getTitle()}에서 {$entity->getTitle()} 생성이 완료되었습니다.";
      return $this->okResponse($message, ['id' => $entity->getPK()], $this->buildViewRedirectUrl($entity));
    });
  }

  // =========================================================
  // Modify Form
  // =========================================================

  protected function modify_form_process($uid): CommonEntity
  {
    return $this->service->getEntity($uid);
  }

  protected function modify_form_result_process(string $action): string
  {
    return $this->action_render_process($action, $this->getViewDatas(), $this->request->getVar('ActionTemplate'));
  }

  final public function modify_form($uid): string|RedirectResponse|ResponseInterface
  {
    $action = __FUNCTION__;

    return $this->runAction($action, function () use ($action, $uid) {
      $this->assertUid($uid, $action);

      $entity = $this->modify_form_process($uid);
      $this->addViewDatas('entity', $entity);

      $this->action_init_process($action, $entity->toArray());
      return $this->modify_form_result_process($action);
    });
  }

  // =========================================================
  // Modify
  // =========================================================

  protected function modify_process($uid, array $formDatas): CommonEntity
  {
    return $this->service->modify($uid, $formDatas);
  }

  /**
   * 기본 결과 처리 (필요시 자식에서 override)
   */
  protected function result_process(CommonEntity $entity, string $message): RedirectResponse|ResponseInterface
  {
    return $this->okResponse($message, ['id' => $entity->getPK()], $this->buildViewRedirectUrl($entity));
  }

  final public function modify($uid): string|RedirectResponse|ResponseInterface
  {
    $action = __FUNCTION__;

    return $this->runAction($action, function () use ($action, $uid) {
      $this->assertUid($uid, $action);

      $this->action_init_process($action);

      $entity = $this->modify_process($uid, $this->request->getPost());
      $this->assertEntityClass($entity, $action);

      $this->addViewDatas('entity', $entity);
      return $this->result_process($entity, "{$this->getTitle()}에서 {$entity->getTitle()} 수정이 완료되었습니다.");
    });
  }

  // =========================================================
  // Delete
  // =========================================================

  protected function delete_process($uid): CommonEntity
  {
    return $this->service->delete($uid);
  }

  protected function delete_result_process(CommonEntity $entity, ?string $redirect_url = null): RedirectResponse|ResponseInterface
  {
    // AJAX면 action_redirect_process가 JSON으로 자동 변환
    $redirect_url = $redirect_url ?? $this->buildListRedirectUrl();
    return $this->action_redirect_process('info', "{$this->getTitle()}에서 {$entity->getTitle()} 삭제가 완료되었습니다.", $redirect_url);
  }

  final public function delete($uid): RedirectResponse|ResponseInterface|string
  {
    $action = __FUNCTION__;

    return $this->runAction($action, function () use ($action, $uid) {
      $this->assertUid($uid, $action);

      $this->action_init_process($action);

      // 삭제 전 존재 확인(기존 로직 유지)
      $this->service->getEntity($uid);

      $entity = $this->delete_process($uid);
      $this->assertEntityClass($entity, $action);

      return $this->delete_result_process($entity);
    });
  }

  // =========================================================
  // View
  // =========================================================

  protected function view_process($uid): CommonEntity
  {
    return $this->service->getEntity($uid);
  }

  protected function view_result_process(string $action): string
  {
    return $this->action_render_process($action, $this->getViewDatas(), $this->request->getVar('ActionTemplate'));
  }

  final public function view($uid): string|RedirectResponse|ResponseInterface
  {
    $action = __FUNCTION__;

    return $this->runAction($action, function () use ($action, $uid) {
      $this->assertUid($uid, $action);

      $entity = $this->view_process($uid);
      $this->action_init_process($action, $entity->toArray());
      $this->addViewDatas('entity', $entity);

      return $this->view_result_process($action);
    });
  }
}
