import { render, screen, fireEvent, within } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { RecordListHeader } from '../src/platform/features/record/components/RecordListHeader';
import type { ListView, SObjectDescribe, SObjectField } from '../src/platform/types';

// #363 P2 — the filter chips row rendered under the toolbar: one removable chip
// per condition, a real count badge, Clear-all relocated here, read-only chips
// for OR/custom logic, and no resident row when no filter is active.

function field(name: string, label: string): SObjectField {
    return {
        name,
        label,
        type: 'string',
        custom: false,
        readable: true,
        createable: true,
        updateable: true,
        nillable: true,
        nameField: name === 'Name',
    } as SObjectField;
}

const accountMetadata: SObjectDescribe = {
    name: 'Account',
    label: 'Account',
    labelPlural: 'Accounts',
    custom: false,
    keyPrefix: '001',
    createable: true,
    updateable: true,
    deletable: true,
    retrieveable: true,
    searchable: true,
    triggerable: true,
    undeletable: false,
    mergeable: true,
    deprecatedAndHidden: false,
    layoutable: true,
    queryable: true,
    replicateable: true,
    feedEnabled: true,
    fields: [field('Name', 'Account Name'), field('Industry', 'Industry')],
};

function renderHeader(overrides: {
    activeFilterExpr?: string;
    activeFilterLogic?: string;
    selectedView?: ListView | null;
    hasReadOnlyFilter?: boolean;
    setActiveFilterExpr?: (expr: string) => void;
    setActiveFilterLogic?: (logic: string) => void;
    setSelectedView?: (view: ListView | null) => void;
} = {}) {
    return render(
        <RecordListHeader
            objectMetadata={accountMetadata}
            localSearch=""
            setLocalSearch={vi.fn()}
            onRefresh={vi.fn()}
            activeFilterExpr={overrides.activeFilterExpr ?? ''}
            activeFilterLogic={overrides.activeFilterLogic}
            hasReadOnlyFilter={overrides.hasReadOnlyFilter}
            setActiveFilterExpr={overrides.setActiveFilterExpr ?? vi.fn()}
            setActiveFilterLogic={overrides.setActiveFilterLogic ?? vi.fn()}
            customActions={[]}
            selectedRecordsCount={0}
            onCustomActionClick={vi.fn()}
            onCreateNew={vi.fn()}
            selectedView={overrides.selectedView ?? null}
            setSelectedView={overrides.setSelectedView ?? vi.fn()}
            listViews={[]}
            onSaveViewClick={vi.fn()}
            onCloneViewClick={vi.fn()}
            onNewViewClick={vi.fn()}
            onDeleteViewClick={vi.fn()}
            onSelectFields={vi.fn()}
            onResetColumnWidths={vi.fn()}
            viewMode="list"
            setViewMode={vi.fn()}
        />,
    );
}

describe('list toolbar P2 filter chips (#363)', () => {
    it('renders no chips row and no Clear all when no filter is active', () => {
        renderHeader();
        expect(screen.queryByText('Clear all')).not.toBeInTheDocument();
        expect(screen.queryByRole('button', { name: /Remove filter/ })).not.toBeInTheDocument();
    });

    it('renders one labeled removable chip per condition, with a real count badge', () => {
        renderHeader({ activeFilterExpr: "Name = 'Acme' AND Industry = 'Tech'" });

        // Count badge reflects the actual number of conditions (was hardcoded 1).
        expect(screen.getByRole('button', { name: /Filters/ })).toHaveTextContent('2');

        // Labels, not API names.
        expect(screen.getByText('Account Name')).toBeInTheDocument();
        expect(screen.getByText('Industry')).toBeInTheDocument();

        expect(screen.getByRole('button', { name: 'Remove filter: Account Name' })).toBeInTheDocument();
        expect(screen.getByRole('button', { name: 'Remove filter: Industry' })).toBeInTheDocument();
        expect(screen.getByText('Clear all')).toBeInTheDocument();
    });

    it('removes a single condition, rebuilding the expression and resetting the view', () => {
        const setActiveFilterExpr = vi.fn();
        const setSelectedView = vi.fn();
        renderHeader({
            activeFilterExpr: "Name = 'Acme' AND Industry = 'Tech'",
            setActiveFilterExpr,
            setSelectedView,
        });

        fireEvent.click(screen.getByRole('button', { name: 'Remove filter: Account Name' }));
        expect(setActiveFilterExpr).toHaveBeenCalledWith("Industry = 'Tech'");
        expect(setSelectedView).toHaveBeenCalledWith(null);
    });

    it('clears every filter from the relocated Clear all', () => {
        const setActiveFilterExpr = vi.fn();
        const setSelectedView = vi.fn();
        renderHeader({ activeFilterExpr: "Name = 'Acme'", setActiveFilterExpr, setSelectedView });

        fireEvent.click(screen.getByText('Clear all'));
        expect(setActiveFilterExpr).toHaveBeenCalledWith('');
        expect(setSelectedView).toHaveBeenCalledWith(null);
    });

    it('renders chips read-only (no ✕) when the filter uses custom OR logic', () => {
        renderHeader({
            activeFilterExpr: "Name = 'Acme' OR Industry = 'Tech'",
            activeFilterLogic: '1 OR 2',
        });

        // Chips still show so the user sees the conditions…
        expect(screen.getByText('Account Name')).toBeInTheDocument();
        expect(screen.getByText('Industry')).toBeInTheDocument();
        // …the OR is rendered so it is not mistaken for an AND filter…
        expect(screen.getByText('or')).toBeInTheDocument();
        // …but individual removal is disabled (would rewrite boolean intent).
        expect(screen.queryByRole('button', { name: /Remove filter/ })).not.toBeInTheDocument();
        // Clear all remains available.
        expect(screen.getByText('Clear all')).toBeInTheDocument();
    });

    it('opens the Filter panel from the chips row "Add filter" affordance', () => {
        renderHeader({ activeFilterExpr: "Name = 'Acme'" });

        expect(screen.queryByRole('heading', { name: 'Filter Records' })).not.toBeInTheDocument();
        fireEvent.click(screen.getByRole('button', { name: /Add filter/ }));
        expect(screen.getByRole('heading', { name: 'Filter Records' })).toBeInTheDocument();
    });

    it('shows a non-removable "Filtered by link" chip and an active badge for a URL-only filter', () => {
        renderHeader({ hasReadOnlyFilter: true });
        // The list is filtered by the page URL even with no editable conditions:
        // the badge stays active (count 1) and a read-only chip makes it visible.
        expect(screen.getByRole('button', { name: /Filters/ })).toHaveTextContent('1');
        expect(screen.getByText('Filtered by link')).toBeInTheDocument();
        // …but it cannot be removed individually (it is not user-editable here).
        expect(screen.queryByRole('button', { name: 'Remove filter: Filtered by link' })).not.toBeInTheDocument();
    });

    it('counts URL + editable filters together and keeps only editable chips removable', () => {
        renderHeader({ hasReadOnlyFilter: true, activeFilterExpr: "Name = 'Acme'" });
        // badge = 1 editable + 1 URL = 2
        expect(screen.getByRole('button', { name: /Filters/ })).toHaveTextContent('2');
        // URL chip (read-only) + editable chip (removable ✕)
        expect(screen.getByText('Filtered by link')).toBeInTheDocument();
        expect(screen.getByRole('button', { name: 'Remove filter: Account Name' })).toBeInTheDocument();
        expect(screen.queryByRole('button', { name: 'Remove filter: Filtered by link' })).not.toBeInTheDocument();
    });

    it('does not surface a saved list view’s own filter as chips', () => {
        // A saved view carries its filter intrinsically (the view name conveys
        // it); the chips row is only for ad-hoc filters (#363 P2 follow-up).
        renderHeader({
            activeFilterExpr: "Name = 'Acme'",
            selectedView: { id: 'view-1', label: "Kevin Lu's list" } as ListView,
        });
        expect(screen.queryByText('Account Name')).not.toBeInTheDocument();
        expect(screen.queryByRole('button', { name: /Remove filter/ })).not.toBeInTheDocument();
        expect(screen.queryByText('Clear all')).not.toBeInTheDocument();
    });

    it('still shows ad-hoc filter chips for All Records (no saved view)', () => {
        renderHeader({ activeFilterExpr: "Name = 'Acme'", selectedView: null });
        expect(screen.getByText('Account Name')).toBeInTheDocument();
    });

    it('hides the chips row for Recently Viewed lists', () => {
        renderHeader({
            activeFilterExpr: "Name = 'Acme'",
            selectedView: { id: 'account-recent-view', label: 'Recently Viewed' } as ListView,
        });
        expect(screen.queryByRole('button', { name: /Remove filter/ })).not.toBeInTheDocument();
        expect(screen.queryByText('Clear all')).not.toBeInTheDocument();
    });
});
