import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { useAuthStore } from '@/stores/auth';
import type { AuthUser } from '@alqove/types';
import { AdminMessagesPanel } from '../admin-messages-panel';

const listMock = vi.fn();
const postMock = vi.fn();
const bulkDeleteMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    messages: {
      list: (...a: unknown[]) => listMock(...a),
      post: (...a: unknown[]) => postMock(...a),
      delete: vi.fn(),
      uploadAttachment: vi.fn(),
    },
    admin: {
      bulkDeleteMessages: (...a: unknown[]) => bulkDeleteMock(...a),
    },
  },
}));

function wrap(node: React.ReactNode) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return <QueryClientProvider client={qc}>{node}</QueryClientProvider>;
}

const adminProps = {
  orderId: 'o1',
  adminUserId: 'admin-1',
  buyerLabel: 'Jane D.',
  storeLabel: 'Revive Boutique',
};

describe('AdminMessagesPanel', () => {
  beforeEach(() => {
    useAuthStore.getState().setAuth({ id: 'admin-1' } as AuthUser, 'token');
    listMock.mockReset();
    postMock.mockReset();
    bulkDeleteMock.mockReset();
  });

  it('renders messages read-only by default — no composer visible', async () => {
    listMock.mockResolvedValue({
      data: [
        {
          id: 'm1',
          thread_id: 't1',
          author_user_id: 'buyer-1',
          author_role: 'buyer',
          body: 'Where is my package?',
          attachments: [],
          created_at: '2026-05-06T10:00:00Z',
          deleted_at: null,
          deleted_by_user_id: null,
          deleted_by_admin: false,
        },
      ],
      meta: { total: 1, has_more: false },
    });

    render(wrap(<AdminMessagesPanel {...adminProps} />));
    await waitFor(() => expect(screen.getByText('Where is my package?')).toBeInTheDocument());

    expect(screen.queryByLabelText('Message')).not.toBeInTheDocument();
    expect(screen.getByRole('button', { name: /Intervene/i })).toBeInTheDocument();
  });

  it('Intervene toggle reveals the composer and a banner', async () => {
    listMock.mockResolvedValue({ data: [], meta: { total: 0, has_more: false } });
    render(wrap(<AdminMessagesPanel {...adminProps} />));
    await waitFor(() => expect(screen.getByRole('button', { name: /Intervene/i })).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: /Intervene/i }));

    expect(screen.getByLabelText('Message')).toBeInTheDocument();
    expect(screen.getByText(/visible to both buyer and seller/i)).toBeInTheDocument();
  });

  it('posting from intervene mode sends the message with admin role implied', async () => {
    listMock.mockResolvedValue({ data: [], meta: { total: 0, has_more: false } });
    postMock.mockResolvedValue({
      data: {
        id: 'm2',
        thread_id: 't1',
        author_user_id: 'admin-1',
        author_role: 'admin',
        body: 'Alqove Support: please share tracking ASAP.',
        attachments: [],
        created_at: '2026-05-06T11:00:00Z',
        deleted_at: null,
        deleted_by_user_id: null,
        deleted_by_admin: false,
      },
    });

    render(wrap(<AdminMessagesPanel {...adminProps} />));
    await waitFor(() => expect(screen.getByRole('button', { name: /Intervene/i })).toBeInTheDocument());
    fireEvent.click(screen.getByRole('button', { name: /Intervene/i }));

    fireEvent.change(screen.getByLabelText('Message'), {
      target: { value: 'Please share tracking ASAP.' },
    });
    fireEvent.click(screen.getByRole('button', { name: /^Send$/ }));

    await waitFor(() => expect(postMock).toHaveBeenCalled());
    const [, body] = postMock.mock.calls[0];
    expect(body.body).toBe('Please share tracking ASAP.');
  });

  it('select-to-delete mode shows checkboxes and bulk-deletes selected ids', async () => {
    const messages = [
      {
        id: 'm-bad-1',
        thread_id: 't1',
        author_user_id: 'buyer-1',
        author_role: 'buyer',
        body: 'spam one',
        attachments: [],
        created_at: '2026-05-06T10:00:00Z',
        deleted_at: null,
        deleted_by_user_id: null,
        deleted_by_admin: false,
      },
      {
        id: 'm-ok',
        thread_id: 't1',
        author_user_id: 'seller-1',
        author_role: 'seller',
        body: 'legit',
        attachments: [],
        created_at: '2026-05-06T10:01:00Z',
        deleted_at: null,
        deleted_by_user_id: null,
        deleted_by_admin: false,
      },
      {
        id: 'm-bad-2',
        thread_id: 't1',
        author_user_id: 'buyer-1',
        author_role: 'buyer',
        body: 'spam two',
        attachments: [],
        created_at: '2026-05-06T10:02:00Z',
        deleted_at: null,
        deleted_by_user_id: null,
        deleted_by_admin: false,
      },
    ];
    listMock.mockResolvedValue({ data: messages, meta: { total: 3, has_more: false } });
    bulkDeleteMock.mockResolvedValue({ data: { deleted_count: 2, requested_count: 2 } });

    const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true);

    render(wrap(<AdminMessagesPanel {...adminProps} />));
    await waitFor(() => expect(screen.getByText('spam one')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: /Select to delete/i }));

    fireEvent.click(screen.getByLabelText('Select message m-bad-1'));
    fireEvent.click(screen.getByLabelText('Select message m-bad-2'));

    fireEvent.click(screen.getByRole('button', { name: /^Delete 2$/ }));

    await waitFor(() => expect(bulkDeleteMock).toHaveBeenCalled());
    expect(bulkDeleteMock.mock.calls[0][0]).toEqual(['m-bad-1', 'm-bad-2']);

    confirmSpy.mockRestore();
  });
});
