<?php

namespace MintyPHP\Repository\CustomField;

use MintyPHP\DB;
use MintyPHP\Repository\Support\RepoQuery;

class TenantCustomFieldDefinitionRepository
{
    private static function unwrap(?array $row): ?array
    {
        if (!$row) {
            return null;
        }
        return $row['tenant_custom_field_definitions'] ?? null;
    }

    private static function unwrapList($rows): array
    {
        if (!is_array($rows)) {
            return [];
        }
        $list = [];
        foreach ($rows as $row) {
            $item = $row['tenant_custom_field_definitions'] ?? null;
            if (is_array($item)) {
                $list[] = $item;
            }
        }
        return $list;
    }

    public static function listByTenantId(int $tenantId, bool $onlyActive = true): array
    {
        if ($tenantId <= 0) {
            return [];
        }
        $query = 'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
            'from tenant_custom_field_definitions where tenant_id = ?';
        $params = [(string) $tenantId];
        if ($onlyActive) {
            $query .= ' and active = 1';
        }
        $query .= ' order by sort_order asc, label asc, id asc';
        return self::unwrapList(DB::select($query, ...$params));
    }

    public static function listByTenantIds(array $tenantIds, bool $onlyActive = true): array
    {
        $tenantIds = array_values(array_unique(array_map('intval', $tenantIds)));
        $tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0));
        if (!$tenantIds) {
            return [];
        }
        $query = 'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
            'from tenant_custom_field_definitions where tenant_id in (???)';
        $params = [$tenantIds];
        if ($onlyActive) {
            $query .= ' and active = 1';
        }
        $query .= ' order by tenant_id asc, sort_order asc, label asc, id asc';
        return self::unwrapList(call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $params)));
    }

    public static function listFilterableByTenantIds(array $tenantIds): array
    {
        $tenantIds = array_values(array_unique(array_map('intval', $tenantIds)));
        $tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0));
        if (!$tenantIds) {
            return [];
        }
        $query = 'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
            'from tenant_custom_field_definitions ' .
            'where tenant_id in (???) and active = 1 and is_filterable = 1 ' .
            "and type in ('select', 'multiselect', 'boolean', 'date') " .
            'order by tenant_id asc, sort_order asc, label asc, id asc';
        return self::unwrapList(call_user_func_array(['MintyPHP\\DB', 'select'], [$query, $tenantIds]));
    }

    public static function findByUuid(string $uuid): ?array
    {
        $row = DB::selectOne(
            'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
            'from tenant_custom_field_definitions where uuid = ? limit 1',
            $uuid
        );
        return self::unwrap($row);
    }

    public static function findById(int $id): ?array
    {
        $row = DB::selectOne(
            'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
            'from tenant_custom_field_definitions where id = ? limit 1',
            (string) $id
        );
        return self::unwrap($row);
    }

    public static function findByTenantIdAndKey(int $tenantId, string $fieldKey): ?array
    {
        if ($tenantId <= 0 || $fieldKey === '') {
            return null;
        }
        $row = DB::selectOne(
            'select id, uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, modified_by, created, modified ' .
            'from tenant_custom_field_definitions where tenant_id = ? and field_key = ? limit 1',
            (string) $tenantId,
            $fieldKey
        );
        return self::unwrap($row);
    }

    public static function create(array $data): int|false
    {
        return DB::insert(
            'insert into tenant_custom_field_definitions ' .
            '(uuid, tenant_id, field_key, label, type, is_required, is_filterable, active, sort_order, created_by, created) ' .
            'values (?,?,?,?,?,?,?,?,?,?,NOW())',
            $data['uuid'] ?? RepoQuery::uuidV4(),
            (string) ($data['tenant_id'] ?? 0),
            (string) ($data['field_key'] ?? ''),
            (string) ($data['label'] ?? ''),
            (string) ($data['type'] ?? ''),
            (string) ((int) ($data['is_required'] ?? 0)),
            (string) ((int) ($data['is_filterable'] ?? 0)),
            (string) ((int) ($data['active'] ?? 1)),
            (string) ((int) ($data['sort_order'] ?? 100)),
            $data['created_by'] ?? null
        );
    }

    public static function update(int $id, array $data): bool
    {
        if ($id <= 0) {
            return false;
        }
        $fields = [
            'field_key' => (string) ($data['field_key'] ?? ''),
            'label' => (string) ($data['label'] ?? ''),
            'type' => (string) ($data['type'] ?? ''),
            'is_required' => (int) ($data['is_required'] ?? 0),
            'is_filterable' => (int) ($data['is_filterable'] ?? 0),
            'active' => (int) ($data['active'] ?? 1),
            'sort_order' => (int) ($data['sort_order'] ?? 100),
        ];
        if (array_key_exists('modified_by', $data)) {
            $fields['modified_by'] = $data['modified_by'];
        }

        $set = [];
        $params = [];
        foreach ($fields as $field => $value) {
            $set[] = sprintf('`%s` = ?', $field);
            $params[] = (string) $value;
        }
        $params[] = (string) $id;

        $result = DB::update(
            'update tenant_custom_field_definitions set ' . implode(', ', $set) . ' where id = ?',
            ...$params
        );
        return $result !== false;
    }

    public static function delete(int $id): bool
    {
        if ($id <= 0) {
            return false;
        }
        $result = DB::delete('delete from tenant_custom_field_definitions where id = ?', (string) $id);
        return $result !== false;
    }
}
