///////////////////////////////////////////////////////////////////////////////
// Portfolio filters
///////////////////////////////////////////////////////////////////////////////

function initPortfolioFilters(domainColumns) {
    const expirySelect          = document.getElementById("pf-filter-expiry");
    const registrarExpirySelect = document.getElementById("pf-filter-registrar-expiry");

    if (expirySelect)
        expirySelect.addEventListener("change", applyFilters);

    if (registrarExpirySelect)
        registrarExpirySelect.addEventListener("change", applyFilters);

    (window.PF_FILTERS || []).forEach(function(f) {
        // Validate columns — flag any that don't exist in domainColumns
        f.missingColumns = _getMissingColumns(f.columns, domainColumns);

        if (f.missingColumns.length > 0) {
            _markFilterInvalid(f);
            // Still wire up events — filter will just produce no clause
        }

        if (f.type === 'text') {
            const el = document.getElementById(f.id);
            if (!el) return;
            let _timer = null;
            el.addEventListener("input", function() {
                clearTimeout(_timer);
                _timer = setTimeout(applyFilters, 400);
            });

        } else if (f.type === 'float' || f.type === 'int') {
            const minEl = document.getElementById(f.id + "-min");
            const maxEl = document.getElementById(f.id + "-max");
            let _timer  = null;
            const handler = function() {
                clearTimeout(_timer);
                _timer = setTimeout(applyFilters, 400);
            };
            if (minEl) minEl.addEventListener("input", handler);
            if (maxEl) maxEl.addEventListener("input", handler);

        } else if (f.type === 'boolean') {
            const el = document.getElementById(f.id);
            if (el) el.addEventListener("change", applyFilters);
        }
    });
}

///////////////////////////////////////////////////////////////////////////////
// Column validation
///////////////////////////////////////////////////////////////////////////////

function _getMissingColumns(columns, domainColumns) {
    if (!domainColumns || Object.keys(domainColumns).length === 0) return [];
    return columns.filter(function(col) {
        // Strip d. prefix before checking against domainColumns keys
        const key = col.startsWith("d.") ? col.substring(2) : col;
        return !(key in domainColumns);
    });
}

function _markFilterInvalid(f) {
    // Find the filter field container — for range inputs use the -min element
    const el = document.getElementById(f.id)
            || document.getElementById(f.id + "-min");
    if (!el) return;

    const field = el.closest(".pf-filter-field");
    if (!field) return;

    // Find or create the label — insert pill after it
    let label = field.querySelector(".pf-filter-label");
    if (!label) {
        // Single-field group with suppressed label — create one
        label = document.createElement("span");
        label.className = "pf-filter-label";
        field.insertBefore(label, field.firstChild);
    }

    const pill = document.createElement("span");
    pill.className   = "pf-error-pill";
    pill.textContent = "!";
    pill.title       = "Column not found: " + f.missingColumns.join(", ");

    label.appendChild(pill);

    // Disable the input(s) so the filter cannot be accidentally used
    [f.id, f.id + "-min", f.id + "-max"].forEach(function(id) {
        const input = document.getElementById(id);
        if (input) input.disabled = true;
    });
}

///////////////////////////////////////////////////////////////////////////////
// Build and apply all active filters
///////////////////////////////////////////////////////////////////////////////

function applyFilters() {
    const dt = DataTableView.getTable("dp-table");
    if (!dt) return;

    const today  = dayjs().format("YYYY-MM-DD");
    const parts  = [];
    const params = [];

    const expiryVal          = document.getElementById("pf-filter-expiry")?.value          || "";
    const registrarExpiryVal = document.getElementById("pf-filter-registrar-expiry")?.value || "";

    _buildExpiryClause("d.registry_expiry",  expiryVal,          today, parts, params);
    _buildExpiryClause("d.registrar_expiry", registrarExpiryVal, today, parts, params);

    (window.PF_FILTERS || []).forEach(function(f) {
        // Skip filters with missing columns
        if (f.missingColumns && f.missingColumns.length > 0) return;

        if (f.type === 'text') {
            const val = (document.getElementById(f.id)?.value || "").trim();
            _buildSearchClause(f.columns, val, parts, params);

        } else if (f.type === 'float' || f.type === 'int') {
            const min = (document.getElementById(f.id + "-min")?.value || "").trim();
            const max = (document.getElementById(f.id + "-max")?.value || "").trim();
            _buildRangeClause(f.columns[0], min, max, parts, params);

        } else if (f.type === 'boolean') {
            const val = document.getElementById(f.id)?.value || "";
            _buildBooleanClause(f.columns[0], val, parts, params);
        }
    });

    dt.setQuery(parts.join(" AND "), params.join("\n"));
    dt.reload();
}

///////////////////////////////////////////////////////////////////////////////
// Clause builders
///////////////////////////////////////////////////////////////////////////////

function _buildExpiryClause(column, value, today, parts, params) {
    switch (value) {
        case "30":
        case "60":
        case "90":
        case "120":
        case "365":
            parts.push(`${column} GE ? AND ${column} LE ?`);
            params.push(today);
            params.push(dayjs().add(parseInt(value), "day").format("YYYY-MM-DD"));
            break;
        case "expired":
            parts.push(`${column} LT ?`);
            params.push(today);
            break;
        case "expired_unknown":
            parts.push(`(${column} LT ? OR ${column} IS NULL)`);
            params.push(today);
            break;
        case "unknown":
            parts.push(`${column} IS NULL`);
            break;
        default:
            break;
    }
}

function _buildSearchClause(columns, value, parts, params) {
    if (!value) return;
    const cols   = Array.isArray(columns) ? columns : [columns];
    const clause = cols.map(col => `${col} LIKE ?`).join(" OR ");
    cols.forEach(() => params.push("%" + value + "%"));
    if (cols.length > 1)
        parts.push(`(${clause})`);
    else
        parts.push(clause);
}

function _buildRangeClause(column, min, max, parts, params) {
    if (min !== "" && max !== "") {
        parts.push(`${column} GE ? AND ${column} LE ?`);
        params.push(min);
        params.push(max);
    } else if (min !== "") {
        parts.push(`${column} GE ?`);
        params.push(min);
    } else if (max !== "") {
        parts.push(`${column} LE ?`);
        params.push(max);
    }
}

function _buildBooleanClause(column, value, parts, params) {
    if (value === "") return;
    parts.push(`${column} EQ ?`);
    params.push(value);
}