<?php

namespace App\Helpers;

use App\Libraries\AuthContext;
use App\Traits\UtilTrait;
use RuntimeException;

abstract class CommonHelper
{
  use UtilTrait;
  private array $_attributes = [];
  protected function __construct()
  {
  }
  final public function setAttributes(array $attributes): void
  {
    $this->_attributes = $attributes;
  }
  final protected function getAuthContext(): AuthContext
  {
    return service('myauth')->getAuthContext();
  }
  final public function getAttribute(string $key): string
  {
    if (!array_key_exists($key, $this->_attributes)) {
      throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$key}에 해당하는 속성이 정의되지 않았습니다.");
    }
    return $this->_attributes[$key];
  }
  public function getFieldLabel(string $field, string $label, array $viewDatas, array $extras = []): string
  {
    switch ($field) {
      default:
        $extras = (strpos($viewDatas['formRules'][$field], 'required') !== false) ? ["class" => "text-danger", "required" => "", ...$extras] : $extras;
        $label = form_label($label, $field, ['class' => 'form-label-sm', ...$extras]);
        break;
    }
    return $label;
  }
  /**
   * CI4의 form_dropdown()을 확장하여 <option> 태그에 data-* 속성을 추가할 수 있도록 합니다.
   *
   * @param string $name 폼 필드 이름
   * @param array $options 드롭다운 옵션 배열. 
   * 값은 문자열/정수, 또는 추가 속성을 포함하는 배열일 수 있습니다.
   * 예: ['value' => 'test1', 'text' => 'Test 1', 'data-price' => 1000]
   * @param string|array|null $selected 현재 선택된 값
   * @param string $extra <select> 태그에 추가할 속성
   * @return string HTML <select> 태그
   */
  final public function form_dropdown_custom(string $name, array $options, mixed $selected, array $extras = []): string
  {
    //Extra처리
    $extra = "";
    foreach ($extras as $extras_key => $extras_value) {
      $extra .= " " . esc($extras_key) . '="' . esc($extras_value) . '"';
    }
    $select = '<select name="' . esc($name) . '"' . $extra . ">\n";
    foreach ($options as $key => $val) {
      // 💡$val이 배열인지 확인합니다.-->배열일경우 옵션 처리
      if (is_array($val)) {
        // $val이 배열인 경우: 복합 옵션 (value, text, data-* 속성 포함)
        $optionValue = $val['value'] ?? $key; // value가 없으면 키 사용
        $optionText = $val['text'] ?? $optionValue;
        $optionAttributes = '';
        // data-* 속성 추출 및 조합
        foreach ($val as $attrKey => $attrValue) {
          // 'value'와 'text'는 <option> 속성이 아니므로 제외
          if ($attrKey == 'value' || $attrKey == 'text') {
            continue;
          } else {
            $optionAttributes .= sprintf(" %s=\"%s\"", esc($attrKey), esc($attrValue));
          }
        }
        $optionSelected = $optionValue == $selected ? ' selected="selected"' : '';
        $select .= sprintf(
          "<option value=\"%s\" %s %s>%s</option>",
          $optionValue,
          $optionAttributes,
          $optionSelected,
          esc($optionText)
        );
      } else {
        // $val이 배열이 아닌 경우: 일반 옵션 (기존 form_dropdown() 방식)
        $optionSelected = $key == $selected ? ' selected="selected"' : '';
        $select .= sprintf(
          "<option value=\"%s\" %s></option>",
          $key,
          $optionSelected,
          esc($val)
        );
      }
    }
    $select .= "</select>\n";
    return $select;
  }
  protected function getFieldForm_process(string $field, array $viewDatas, string $form): string
  {
    switch ($field) {
      default:
        break;
    }
    return $form;
  }
  public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
  {
    switch ($field) {
      case 'email':
        $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' form-control' : 'form-control';
        $extras['placeholder'] = '예)test@example.co.kr';
        $form = form_input($field, $value ?? "", $extras);
        break;
      case 'mobile':
      case 'phone':
        $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' form-control' : 'form-control';
        $extras['placeholder'] = '예)010-0010-0010';
        $form = form_input($field, $value ?? "", $extras);
        break;
      case 'issue_at':
      case 'expired_at':
      case 'billing_at':
      case 'start_at':
      case 'end_at':
      case 'updated_at':
      case 'created_at':
      case 'deleted_at':
        $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' calender' : 'calender';
        $form = form_input($field, $value ?? "", $extras);
        break;
      case 'description':
      case 'content':
      case 'detail':
      case 'history':
        $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' form-control tinymce' : 'form-control tinymce';
        $form = form_textarea($field, html_entity_decode($value ?? "", ENT_QUOTES, 'UTF-8'), $extras);
        break;
      case 'status':
        $forms = [];
        // dd($viewDatas['formOptions']);
        array_shift($viewDatas['formOptions'][$field]['options']);
        foreach ($viewDatas['formOptions'][$field]['options'] as $key => $label)
          $forms[] = form_radio($field, $key, $key == $value, $extras) . $label;
        $form = implode(" ", $forms);
        break;
      default:
        $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' form-control' : 'form-control';
        if (in_array($field, $viewDatas['formFilters'])) {
          if (array_key_exists('extras', $viewDatas['formOptions'][$field])) {
            $extras = array_merge($extras, $viewDatas['formOptions'][$field]['extras']);
          }
          $form = form_dropdown($field, $viewDatas['formOptions'][$field]['options'], $value, $extras);
        } else {
          $form = form_input($field, $value ?? "", $extras);
        }
        break;
    }
    return $form;
  }
  public function getFieldView(string $field, mixed $value, array $viewDatas, array $extras = []): string|null
  {
    switch ($field) {
      case 'clientinfo_uid':
        if (array_key_exists($value, $viewDatas['formOptions'][$field]['options'])) {
          if (!array_key_exists($value, $viewDatas['formOptions'][$field]['options'])) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$field}에서 {$value}에 해당하는 값이 존재하지 않습니다.");
          }
          $value = !$value ? "" : "<a href=\"/admin/user/detail/{$value}\">{$viewDatas['formOptions'][$field]['options'][$value]}</a>";
        }
        break;
      case 'role':
        if (!is_array($value)) { //배열이 아니면
          $value = explode(DEFAULTS['DELIMITER_COMMA'], $value);
        }
        $roles = [];
        foreach ($value as $key) {
          $roles[] = $viewDatas['formOptions'][$field]['options'][$key];
        }
        $value = implode(" , ", $roles);
        break;
      case 'description':
      case 'content':
      case 'detail':
      case 'history':
        $value = $value != null ? html_entity_decode($value, ENT_QUOTES, 'UTF-8') : "";
        break;
      case 'updated_at':
      case 'created_at':
      case 'deleted_at':
        $value = $value ? date("Y-m-d", strtotime($value)) : "";
        break;
      default:
        if (in_array($field, $viewDatas['formFilters'])) {
          if ($value) {
            if (!array_key_exists($value, $viewDatas['formOptions'][$field]['options'])) {
              throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$field}에서 {$value}에 해당하는 값이 존재하지 않습니다.\n" . var_export($viewDatas['formOptions'][$field], true));
            }
            $value = $viewDatas['formOptions'][$field]['options'][$value];
          }
        }
        break;
    }
    if (is_array($value)) {
      throw new RuntimeException(static::class . "->" . __FUNCTION__ . "에서 오류발생:{$field}에 해당하는 Return 값이 배열형식입니다.\n" . var_export($value, true));
    }
    return $value;
  }
  public function getListFilter(string $field, mixed $value, array $viewDatas, array $extras = []): string
  {
    switch ($field) {
      case 'user_uid':
      case 'clientinfo_uid':
      case 'serverinfo_uid':
        $extras['class'] = array_key_exists('class', $extras) ? $extras['class'] . ' select-field' : 'select-field';
        $filter = form_dropdown($field, $viewDatas['formOptions'][$field]['options'], $value, $extras);
        break;
      default:
        $filter = "";
        if (in_array($field, $viewDatas['formFilters'])) {
          $filter = form_dropdown($field, $viewDatas['formOptions'][$field]['options'], $value, $extras);
        }
        break;
    }
    return $filter;
  }
  public function getListLabel(string $field, string $label, array $viewDatas, array $extras = []): string
  {
    switch ($field) {
      default:
        if (isset($viewDatas['order_field']) && $viewDatas['order_field'] == $field) {
          $label .= $viewDatas['order_value'] == 'ASC' ? ICONS["UP"] : ICONS["DOWN"];
        }
        $query = $viewDatas['uri']->getQuery(['except' => ['order_field', 'order_value']]);
        $query .= empty($query) ? "" : "&";
        $query .= "order_field={$field}&order_value=";
        $query .= isset($viewDatas['order_value']) && $viewDatas['order_value'] == 'DESC' ? "ASC" : "DESC";
        $label = anchor(current_url() . "?" . $query, $label);
        form_dropdown('perpage', $viewDatas['index_pagination_options'], $viewDatas['perpage'], ['onChange' => 'this.form.submit()']);
        break;
    }
    return $label;
  }

  public function getListButton(string $action, string $label, array $viewDatas, array $extras = []): string
  {
    switch ($action) {
      case 'create':
        $action = form_label(
          $label,
          $action,
          [
            "data-src" => sprintf("%s/%s?%s", current_url(), $action, service('request')->getUri()->getQuery()),
            "data-bs-toggle" => "modal",
            "data-bs-target" => "#modal_action_form",
            "class" => "btn btn-sm btn-primary form-label-sm",
            ...$extras
          ]
        );
        break;
      case 'modify':
        $oldBatchJobUids = old("batchjob_uids", null);
        $oldBatchJobUids = is_array($oldBatchJobUids) ? $oldBatchJobUids : [$oldBatchJobUids];
        $checkbox = form_checkbox([
          "id" => "checkbox_uid_{$viewDatas['entity']->getPK()}",
          "name" => "batchjob_uids[]",
          "value" => $viewDatas['entity']->getPK(),
          "class" => "batchjobuids_checkboxs",
          "checked" => in_array($viewDatas['entity']->getPK(), $oldBatchJobUids)
        ]);
        $action = $checkbox . form_label(
          $label,
          $action,
          [
            "data-src" => sprintf("%s/%s/%s?%s", current_url(), $action, $viewDatas['entity']->getPK(), service('request')->getUri()->getQuery()),
            "data-bs-toggle" => "modal",
            "data-bs-target" => "#modal_action_form",
            'class' => 'form-label-sm',
            ...$extras
          ]
        );
        break;
      case 'view':
        $action = form_label(
          $label,
          $action,
          [
            "data-src" => sprintf("%s/%s/%s?%s", current_url(), $action, $viewDatas['entity']->getPK(), service('request')->getUri()->getQuery()),
            "data-bs-toggle" => "modal",
            "data-bs-target" => "#modal_action_form",
            "class" => "btn btn-sm btn-primary form-label-sm",
            ...$extras
          ]
        );
        break;
      case 'delete':
        $action = anchor(
          current_url() . '/' . $action . '/' . $viewDatas['entity']->getPK(),
          $label,
          [
            "class" => "btn btn-sm btn-danger form-label-sm",
            ...$extras
          ]
        );
        break;
      case 'batchjob':
        $action = form_submit("batchjob_submit", $label, [
          "formaction" => current_url() . '/batchjob',
          "class" => "btn btn-sm btn-warning form-label-sm",
          ...$extras,
          // "onclick" => "return submitBatchJob()"
        ]);
        break;
      case 'batchjob_delete':
        $action = form_submit("batchjob_submit", $label, [
          "formaction" => current_url() . '/batchjob_delete',
          "class" => "btn btn-sm btn-danger form-label-sm",
          ...$extras,
          // "onclick" => "return submitBatchJobDelete()"
        ]);
        break;
      default:
        $action = "";
        break;
    }
    return $action;
  }
}
