<?php
namespace Components\Models;

// Ensure legacy constants are defined
if (defined('MH_DIR_FS_CATALOG') && defined('MH_ROOT_PATH')) {
    $legacyFile = MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'mailbeez/mb_newsletter/classes/mb_newsletter_categories.php';
    if (is_file($legacyFile)) {
        require_once $legacyFile;
    }
}

/**
 * Newsletter Topics (Categories) model.
 */
class Topic extends BaseModel
{
    protected static string $table = 'TABLE_MAILBEEZ_NEWSLETTER_CATEGORIES';
    protected static string $primaryKey = 'newsletter_categories_id';
    protected static string $blueprint = 'topic.yaml';

    public function augmentFormValues(array $values): array
    {
        $id = (int)($values[static::$primaryKey] ?? $this->{static::$primaryKey} ?? 0);
        if ($id > 0) {
            try {
                $all = TopicDescription::forTopic($id);
                $names = [];
                $descs = [];
                foreach ($all as $lid => $row) {
                    $names[$lid] = (string)($row['newsletter_categories_name'] ?? '');
                    $descs[$lid] = (string)($row['newsletter_categories_description'] ?? '');
                }
                $values['newsletter_category_name'] = $names;
                $values['newsletter_category_description'] = $descs;
            } catch (\Throwable $e) { /* ignore */ }
        }
        return $values;
    }

    protected function filterAttributesForSave(array $data): array
    {
        // These fields are virtual (i18n) and handled in afterSave
        unset($data['newsletter_category_name']);
        unset($data['newsletter_category_description']);
        return parent::filterAttributesForSave($data);
    }

    public function afterSave(array $post): void
    {
        $id = (int)($this->{static::$primaryKey} ?? 0);
        if ($id <= 0) return;

        $names = isset($post['newsletter_category_name']) && is_array($post['newsletter_category_name']) ? $post['newsletter_category_name'] : [];
        $descs = isset($post['newsletter_category_description']) && is_array($post['newsletter_category_description']) ? $post['newsletter_category_description'] : [];

        $map = [];
        $langIds = array_unique(array_map('intval', array_merge(array_keys($names), array_keys($descs))));

        foreach ($langIds as $lid) {
            $lid = (int)$lid; if ($lid <= 0) continue;
            $nm = isset($names[$lid]) ? trim((string)$names[$lid]) : '';
            $dc = isset($descs[$lid]) ? (string)$descs[$lid] : '';
            if ($nm === '' && $dc === '') continue;
            $map[$lid] = [ 'newsletter_categories_name' => $nm, 'newsletter_categories_description' => $dc ];
        }

        if (!empty($map)) {
            try { TopicDescription::syncForTopic($id, $map); } catch (\Throwable $e) { /* ignore */ }
        }
    }

    /**
     * Default values for new topic records.
     */
    public static function getNewDefaults(): array
    {
        $defaults = [];
        try {
            $val = (string) (\mh_get('is_public', '', 'string') ?: \mh_get('topics_tab', '', 'string'));
            if ($val !== '') {
                $s = strtolower(trim($val));
                if ($s === 'public' || $s === 'true') $defaults['is_public'] = 'True';
                elseif ($s === 'private' || $s === 'false') $defaults['is_public'] = 'False';
            }
        } catch (\Throwable $e) { /* ignore */ }
        return $defaults;
    }

    public static function paginate(int $perPage = 10, int $page = 1, string $search = '', array $searchCols = [], array $filters = []): array
    {
        if (self::isDev()) return ['items' => [], 'total' => 0];

        $where = "1=1";
        $table = static::table();
        $descTable = TopicDescription::table();

        // Join with description to search in names
        $langId = (int)($_SESSION['languages_id'] ?? 1);
        $join = " LEFT JOIN " . $descTable . " td ON " . $table . ".newsletter_categories_id = td.newsletter_categories_id AND td.language_id = " . $langId;

        // Apply filters
        if (!empty($filters)) {
            // Support 'is_public' filter: accepts boolean, 'True'/'False', or 'public'/'private'
            if (array_key_exists('is_public', $filters)) {
                $val = $filters['is_public'];
                if (is_bool($val)) {
                    $val = $val ? 'True' : 'False';
                } else {
                    $s = strtolower((string)$val);
                    if ($s === 'public') $val = 'True';
                    elseif ($s === 'private') $val = 'False';
                    elseif ($s !== 'True' && $s !== 'False') {
                        // normalize any truthy/falsy string
                        $val = in_array($s, ['1','true','yes','y'], true) ? 'True' : 'False';
                    }
                }
                $where .= " AND " . $table . ".is_public = '" . \mh_db_input($val) . "'";
            }
        }

        if ($search !== '' && !empty($searchCols)) {
            $clauses = [];
            foreach ($searchCols as $col) {
                if (in_array($col, ['newsletter_categories_name', 'newsletter_categories_description'])) {
                    $clauses[] = "td." . $col . " LIKE '%" . \mh_db_input($search) . "%'";
                } else {
                    $clauses[] = $table . "." . $col . " LIKE '%" . \mh_db_input($search) . "%'";
                }
            }
            $where .= " AND (" . implode(" OR ", $clauses) . ")";
        }

        $countSql = "SELECT COUNT(DISTINCT " . $table . ".newsletter_categories_id) as total FROM " . $table . $join . " WHERE " . $where;
        $cq = \mh_db_query($countSql);
        $res = \mh_db_fetch_array($cq);
        $total = (int)($res['total'] ?? 0);
        \mh_db_free_result($cq);

        $offset = max(0, ($page - 1) * $perPage);

        $sql = "SELECT " . $table . ".*, td.newsletter_categories_name, td.newsletter_categories_description FROM " . $table . $join . " WHERE " . $where . " ORDER BY " . $table . ".sort_order ASC, " . $table . "." . static::pk() . " DESC LIMIT " . (int)$offset . ", " . (int)$perPage;
        $q = \mh_db_query($sql);

        $items = [];
        while ($row = \mh_db_fetch_array($q)) {
            $items[] = new static($row);
        }
        \mh_db_free_result($q);

        return [
            'items' => $items,
            'total' => $total,
        ];
    }

    public static function paginatePublic(int $perPage = 10, int $page = 1, string $search = '', array $searchCols = []): array
    {
        return static::paginate($perPage, $page, $search, $searchCols, ['is_public' => 'True']);
    }

    public static function paginatePrivate(int $perPage = 10, int $page = 1, string $search = '', array $searchCols = []): array
    {
        return static::paginate($perPage, $page, $search, $searchCols, ['is_public' => 'False']);
    }
}
