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

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    usePage: vi.fn(() => ({
      url: '/admin/blog-posts',
      props: {
        auth: { user: { id: 1, name: 'Admin', email: 'admin@test.com', is_admin: true } },
        features: {
          billing: false,
          socialAuth: false,
          emailVerification: true,
          apiTokens: true,
          userSettings: true,
          notifications: false,
          onboarding: false,
          apiDocs: false,
          twoFactor: false,
          webhooks: false,
          admin: true,
        },
      },
    })),
    Link: ({
      children,
      href,
      ...rest
    }: {
      children: React.ReactNode;
      href: string;
      className?: string;
    }) => (
      <a href={href} {...rest}>
        {children}
      </a>
    ),
    router: {
      patch: vi.fn(),
      delete: vi.fn(),
      post: vi.fn(),
      get: vi.fn(),
      visit: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
  };
});

vi.mock('@/Components/theme/use-theme', () => ({
  useTheme: vi.fn(() => ({ theme: 'system', setTheme: vi.fn(), resolvedTheme: 'light' })),
}));

vi.mock('sonner', () => ({
  toast: { success: vi.fn(), error: vi.fn() },
}));

import BlogPostsIndex from './Index';

const makePagination = <T,>(data: T[]) => ({
  data,
  current_page: 1,
  last_page: 1,
  from: data.length > 0 ? 1 : null,
  to: data.length > 0 ? data.length : null,
  total: data.length,
});

const makePost = (overrides = {}) => ({
  id: 1,
  title: 'My First Blog Post',
  slug: 'my-first-blog-post',
  author: 'Alice',
  published_at: '2026-03-01T10:00:00Z',
  deleted_at: null,
  created_at: '2026-02-28T08:00:00Z',
  ...overrides,
});

const defaultFilters = { trashed: 'without', search: '' };

describe('BlogPostsIndex', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders the Blog Posts heading', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    expect(screen.getByRole('heading', { name: 'Blog Posts', level: 1 })).toBeInTheDocument();
  });

  it('renders a post row with title, slug, and author', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost()])}
        filters={defaultFilters}
      />,
    );
    expect(screen.getByText('My First Blog Post')).toBeInTheDocument();
    expect(screen.getByText('my-first-blog-post')).toBeInTheDocument();
    expect(screen.getByText('Alice')).toBeInTheDocument();
  });

  it('shows em dash for posts with no author', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ author: null })])}
        filters={defaultFilters}
      />,
    );
    expect(screen.getByText('—')).toBeInTheDocument();
  });

  it('shows Deleted badge for soft-deleted posts', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'with', search: '' }}
      />,
    );
    // "Deleted" appears as both a table header column and a badge on the post row
    expect(screen.getAllByText('Deleted').length).toBeGreaterThanOrEqual(1);
  });

  it('shows empty state when no posts exist', () => {
    render(<BlogPostsIndex posts={makePagination([])} filters={defaultFilters} />);
    expect(screen.getByText('No blog posts found')).toBeInTheDocument();
  });

  it('shows deleted-specific empty state when trashed filter is active', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([])}
        filters={{ trashed: 'only', search: '' }}
      />,
    );
    expect(screen.getByText('No deleted blog posts.')).toBeInTheDocument();
  });

  it('renders Edit button for active posts', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    expect(screen.getByRole('link', { name: 'Edit' })).toBeInTheDocument();
  });

  it('does not render Edit button for deleted posts', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'only', search: '' }}
      />,
    );
    expect(screen.queryByRole('link', { name: 'Edit' })).not.toBeInTheDocument();
  });

  it('renders Restore button for deleted posts', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'only', search: '' }}
      />,
    );
    expect(screen.getByRole('button', { name: 'Restore' })).toBeInTheDocument();
  });

  it('renders multiple posts', () => {
    const posts = [
      makePost({ id: 1, title: 'Post One', slug: 'post-one' }),
      makePost({ id: 2, title: 'Post Two', slug: 'post-two' }),
    ];
    render(<BlogPostsIndex posts={makePagination(posts)} filters={defaultFilters} />);
    expect(screen.getByText('Post One')).toBeInTheDocument();
    expect(screen.getByText('Post Two')).toBeInTheDocument();
  });

  it('shows selection toolbar when a row checkbox is checked', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    const checkbox = screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ });
    fireEvent.click(checkbox);
    expect(screen.getByText('1 selected')).toBeInTheDocument();
  });

  it('shows Delete Selected button in toolbar for active filter', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    const checkbox = screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ });
    fireEvent.click(checkbox);
    expect(screen.getByRole('button', { name: /Delete Selected/ })).toBeInTheDocument();
  });

  it('shows Restore Selected button in toolbar for deleted-only filter', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'only', search: '' }}
      />,
    );
    const checkbox = screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ });
    fireEvent.click(checkbox);
    expect(screen.getByRole('button', { name: /Restore Selected/ })).toBeInTheDocument();
  });

  it('clears selection when Clear selection is clicked', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    const checkbox = screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ });
    fireEvent.click(checkbox);
    expect(screen.getByText('1 selected')).toBeInTheDocument();
    fireEvent.click(screen.getByRole('button', { name: /Clear selection/ }));
    expect(screen.queryByText('1 selected')).not.toBeInTheDocument();
  });

  it('renders New Post link', () => {
    render(<BlogPostsIndex posts={makePagination([])} filters={defaultFilters} />);
    expect(screen.getByRole('link', { name: /New Post/ })).toBeInTheDocument();
  });

  it('does not show Delete Selected button when trashed filter is "only"', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'only', search: '' }}
      />,
    );
    const checkbox = screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ });
    fireEvent.click(checkbox);
    expect(screen.queryByRole('button', { name: /Delete Selected/ })).not.toBeInTheDocument();
  });

  it('renders Delete button for active posts', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument();
  });

  it('renders search input with correct placeholder', () => {
    render(<BlogPostsIndex posts={makePagination([])} filters={defaultFilters} />);
    expect(
      screen.getByRole('textbox', { name: /Search blog posts by title, slug, or author/ }),
    ).toBeInTheDocument();
  });

  it('renders Export button', () => {
    render(<BlogPostsIndex posts={makePagination([])} filters={defaultFilters} />);
    expect(screen.getByRole('link', { name: /Export/ })).toBeInTheDocument();
  });

  it('shows Deleted column header when trashed filter is "with"', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'with', search: '' }}
      />,
    );
    // The "Deleted" header cell should be visible for non-"without" filters
    const headers = screen.getAllByRole('columnheader');
    const deletedHeader = headers.find((h) => h.textContent?.trim() === 'Deleted');
    expect(deletedHeader).toBeInTheDocument();
  });

  it('shows both Delete Selected and Restore Selected in toolbar when filter is "with"', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'with', search: '' }}
      />,
    );
    const checkbox = screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ });
    fireEvent.click(checkbox);
    expect(screen.getByRole('button', { name: /Delete Selected/ })).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /Restore Selected/ })).toBeInTheDocument();
  });

  it('opens bulk delete confirm dialog when Delete Selected is clicked', () => {
    render(<BlogPostsIndex posts={makePagination([makePost()])} filters={defaultFilters} />);
    fireEvent.click(screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ }));
    fireEvent.click(screen.getByRole('button', { name: /Delete Selected/ }));
    expect(screen.getByText('Delete selected blog posts?')).toBeInTheDocument();
  });

  it('opens bulk restore confirm dialog when Restore Selected is clicked', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([makePost({ deleted_at: '2026-03-10T12:00:00Z' })])}
        filters={{ trashed: 'only', search: '' }}
      />,
    );
    fireEvent.click(screen.getByRole('checkbox', { name: /Select "My First Blog Post"/ }));
    fireEvent.click(screen.getByRole('button', { name: /Restore Selected/ }));
    expect(screen.getByText('Restore selected blog posts?')).toBeInTheDocument();
  });

  it('shows correct count in bulk delete confirmation dialog', () => {
    render(
      <BlogPostsIndex
        posts={makePagination([
          makePost({ id: 1, title: 'Post A', slug: 'post-a' }),
          makePost({ id: 2, title: 'Post B', slug: 'post-b' }),
        ])}
        filters={defaultFilters}
      />,
    );
    fireEvent.click(screen.getByRole('checkbox', { name: /Select "Post A"/ }));
    fireEvent.click(screen.getByRole('checkbox', { name: /Select "Post B"/ }));
    // 2 selected independently computed
    expect(screen.getByText('2 selected')).toBeInTheDocument();
    fireEvent.click(screen.getByRole('button', { name: /Delete Selected/ }));
    expect(screen.getByText(/2 post\(s\) will be soft-deleted/)).toBeInTheDocument();
  });
});
