<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class FilterFacade {

  /** @var CI_Controller */
  protected $CI;

  public function __construct()
  {
    $this->CI =& get_instance();
    $this->CI->load->library('FilterBuilder');
    $this->CI->load->model('CommonModel');
  }

  public function fetchLegacy($module, array $filterOption, array $staticJoined, array $other)
  {
    $columns = $this->mapLegacyColumns($module, $staticJoined);
    $sort    = $this->mapLegacySort($module, $other);
    $filters = $this->mapLegacyFilters($module, $filterOption);

    $limit  = isset($other['limit']) ? (int)$other['limit'] : 20;
    $page   = isset($other['page']) ? max(1, (int)$other['page']) : 1;
    $offset = ($page - 1) * $limit;

    return $this->CI->CommonModel->fetchWithFilters($module, $filters, $columns, $sort, $limit, $offset);
  }

  protected function mapLegacyColumns($module, array $staticJoined)
  {
    $cols = [];
    if (isset($staticJoined['columns']) && is_array($staticJoined['columns'])) {
      foreach ($staticJoined['columns'] as $col) {
        if (strpos($col, '.') !== false) $col = substr($col, strpos($col, '.') + 1);
        $cols[] = $col;
      }
    }
    if (!$cols) $cols = ['customer_id','name','email','status','created_date'];
    return array_values(array_unique($cols));
  }

  protected function mapLegacySort($module, array $other)
  {
    $sortBy  = isset($other['orderBy']) ? $other['orderBy'] : null;
    $sortDir = isset($other['order'])  ? $other['order']  : 'ASC';
    return ['by' => $sortBy, 'dir' => $sortDir];
  }

  protected function mapLegacyFilters($module, array $filterOption)
  {
    $result = [];
    foreach (($filterOption['rules'] ?? []) as $r) {
      $field = isset($r['field']) ? $r['field'] : '';
      $op    = isset($r['operator']) ? $r['operator'] : '';
      $val   = isset($r['value']) ? $r['value'] : null;

      if (strpos($field, '.') !== false) $field = substr($field, strpos($field, '.') + 1);

      $norm = $this->normalizeOperator($op, $val, $r);
      if (!$norm) continue;
      $norm['field'] = $field;
      $result[] = $norm;
    }
    return $result;
  }

  protected function normalizeOperator($legacyOp, $val, $rule)
  {
    $lop = strtolower($legacyOp);
    switch ($lop) {
      case '=': case 'eq': return ['op' => 'equal_to', 'value' => $val];
      case '!=': case '<>': return ['op' => 'not_equal_to', 'value' => $val];
      case 'in': return ['op' => 'in', 'value' => (is_array($val) ? $val : explode(',', (string)$val))];
      case 'not in': return ['op' => 'not_in', 'value' => (is_array($val) ? $val : explode(',', (string)$val))];
      case 'like': return ['op' => 'like', 'value' => $val];
      case 'ilike': return ['op' => 'ilike', 'value' => $val];
      case '>=': return ['op' => 'gte', 'value' => $val];
      case '<=': return ['op' => 'lte', 'value' => $val];
      case 'between': return ['op' => 'between', 'from' => ($rule['from'] ?? null), 'to' => ($rule['to'] ?? null)];
      case 'start_with': return ['op' => 'start_with', 'value' => $val];
      case 'end_with': return ['op' => 'end_with', 'value' => $val];
      case 'is_empty': return ['op' => 'is_empty'];
      case 'is_not_empty': return ['op' => 'is_not_empty'];
      case 'greater_than': return ['op' => 'greater_than', 'value' => $val];
      case 'less_than': return ['op' => 'less_than', 'value' => $val];
      case 'range': return ['op' => 'range', 'from' => ($rule['from'] ?? null), 'to' => ($rule['to'] ?? null)];
      case 'today': case 'yesterday': case 'tomorrow': case 'this_week': case 'this_month': case 'exact_date':
        return ['op' => $lop, 'value' => $val];
      default: return null;
    }
  }
}
