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

import { SearchLaunchDialog } from '@/components/shared/SearchLaunchDialog';
import { fetchAccounts } from '@/services/accountService';
import { triggerSearchBatch } from '@/services/automationService';
import type { ProcurementAccount1688 } from '@/types';
import { toast } from 'sonner';

const createdAccount: ProcurementAccount1688 = {
  id: 'account-new',
  user_id: 'user-1',
  account_name: '新配置账户',
  password: 'secret',
  remark: '主账号',
  login_status: 'success',
  login_error: null,
  login_checked_at: '2026-04-21T08:00:00.000Z',
  created_at: '2026-04-21T08:00:00.000Z',
  updated_at: '2026-04-21T08:00:00.000Z',
};

vi.mock('@/hooks/useAuth', () => ({
  useAuth: () => ({
    user: {
      id: 'user-1',
    },
  }),
}));

vi.mock('@/services/accountService', async () => {
  const actual = await vi.importActual<typeof import('@/services/accountService')>('@/services/accountService');
  return {
    ...actual,
    fetchAccounts: vi.fn(),
  };
});

vi.mock('@/services/automationService', async () => {
  const actual = await vi.importActual<typeof import('@/services/automationService')>('@/services/automationService');
  return {
    ...actual,
    triggerSearchBatch: vi.fn(),
  };
});

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

vi.mock('@/components/auth/ProcurementAccountDialog', () => ({
  ProcurementAccountDialog: ({
    open,
    onOpenChange,
    onAccountCreated,
  }: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    onAccountCreated?: (account: typeof createdAccount) => void;
  }) => {
    if (!open) {
      return null;
    }

    return (
      <button
        type="button"
        onClick={() => {
          onAccountCreated?.(createdAccount);
          onOpenChange(false);
        }}
      >
        完成账户配置
      </button>
    );
  },
}));

describe('SearchLaunchDialog', () => {
  const fetchAccountsMock = vi.mocked(fetchAccounts);
  const triggerSearchBatchMock = vi.mocked(triggerSearchBatch);
  const toastSuccessMock = vi.mocked(toast.success);
  const toastErrorMock = vi.mocked(toast.error);

  beforeEach(() => {
    fetchAccountsMock.mockResolvedValue([]);
    triggerSearchBatchMock.mockReset();
    vi.clearAllMocks();
    fetchAccountsMock.mockResolvedValue([]);
  });

  it('auto-selects a newly created account from the configuration entry', async () => {
    fetchAccountsMock.mockResolvedValueOnce([]).mockResolvedValue([createdAccount]);

    render(
      <SearchLaunchDialog
        open
        onOpenChange={vi.fn()}
        mode="selected"
        batchId="CG-TEST-001"
        selectedItems={[
          {
            id: 'row-1',
            batch_id: 'CG-TEST-001',
            material_id: 'mat-1',
            invoice_type: '专票',
            original_name: '测试物料',
            original_spec: '规格',
            standardized_name: '测试物料',
            category: '分类',
            brand: '品牌',
            notes: '',
            delivery_address: '杭州',
            primary_search_term: '测试物料',
            alt_search_terms: [],
            standardized_spec: '规格',
            standardized_unit: '个',
            quantity: 1,
            product_type: '标准品',
            llm_model: 'gpt',
            ai_reasoning: '',
            created_at: '2026-04-21T08:00:00.000Z',
          },
        ]}
        onStarted={vi.fn()}
      />,
    );

    await waitFor(() => expect(fetchAccountsMock).toHaveBeenCalledWith('user-1'));

    fireEvent.click(screen.getByRole('button', { name: '配置账户' }));
    fireEvent.click(screen.getByText('完成账户配置'));

    await waitFor(() => expect(screen.getByText('新配置账户')).toBeInTheDocument());
  });

  it('submits the search request and returns created task ids to the caller', async () => {
    const onOpenChange = vi.fn();
    const onStarted = vi.fn();

    fetchAccountsMock.mockResolvedValueOnce([]).mockResolvedValue([createdAccount]);
    triggerSearchBatchMock.mockResolvedValue({
      message: '搜索任务已启动',
      totalRows: 2,
      createdCount: 1,
      taskId: 'task-001',
      taskIds: ['task-001'],
    });

    render(
      <SearchLaunchDialog
        open
        onOpenChange={onOpenChange}
        mode="selected"
        batchId="all"
        selectedItems={[
          {
            id: 'row-1',
            batch_id: 'CG-TEST-001',
            material_id: 'mat-1',
            invoice_type: '专票',
            original_name: '测试物料A',
            original_spec: '规格A',
            standardized_name: '测试物料A',
            category: '分类',
            brand: '品牌',
            notes: '',
            delivery_address: '杭州',
            primary_search_term: '测试物料A',
            alt_search_terms: [],
            standardized_spec: '规格A',
            standardized_unit: '个',
            quantity: 1,
            product_type: '标准品',
            llm_model: 'gpt',
            ai_reasoning: '',
            created_at: '2026-04-21T08:00:00.000Z',
          },
          {
            id: 'row-2',
            batch_id: 'CG-TEST-001',
            material_id: 'mat-2',
            invoice_type: '专票',
            original_name: '测试物料B',
            original_spec: '规格B',
            standardized_name: '测试物料B',
            category: '分类',
            brand: '品牌',
            notes: '',
            delivery_address: '杭州',
            primary_search_term: '测试物料B',
            alt_search_terms: [],
            standardized_spec: '规格B',
            standardized_unit: '个',
            quantity: 1,
            product_type: '标准品',
            llm_model: 'gpt',
            ai_reasoning: '',
            created_at: '2026-04-21T08:00:00.000Z',
          },
        ]}
        onStarted={onStarted}
      />,
    );

    await waitFor(() => expect(fetchAccountsMock).toHaveBeenCalledWith('user-1'));

    fireEvent.click(screen.getByRole('button', { name: '配置账户' }));
    fireEvent.click(screen.getByText('完成账户配置'));

    await waitFor(() => expect(screen.getByText('新配置账户')).toBeInTheDocument());
    fireEvent.click(screen.getByRole('button', { name: '启动搜索' }));

    await waitFor(() => {
      expect(triggerSearchBatchMock).toHaveBeenCalledWith(expect.objectContaining({
        batch_id: 'CG-TEST-001',
        material_ids: ['mat-1', 'mat-2'],
        account_id: 'account-new',
        contact_limit: 5,
        headless: true,
        resource_profile: 'low_cpu',
      }));
    });

    expect(onOpenChange).toHaveBeenCalledWith(false);
    expect(onStarted).toHaveBeenCalledWith({
      taskIds: ['task-001'],
      createdCount: 1,
      totalRows: 2,
      batchId: 'CG-TEST-001',
    });
    expect(toastSuccessMock).toHaveBeenCalledWith('已创建搜索任务，包含 2 条物料');
  });

  it('shows an error toast when the search request fails', async () => {
    fetchAccountsMock.mockResolvedValueOnce([]).mockResolvedValue([createdAccount]);
    triggerSearchBatchMock.mockRejectedValue(new Error('network failed'));

    const onStarted = vi.fn();

    render(
      <SearchLaunchDialog
        open
        onOpenChange={vi.fn()}
        mode="selected"
        batchId="CG-TEST-001"
        selectedItems={[
          {
            id: 'row-1',
            batch_id: 'CG-TEST-001',
            material_id: 'mat-1',
            invoice_type: '专票',
            original_name: '测试物料',
            original_spec: '规格',
            standardized_name: '测试物料',
            category: '分类',
            brand: '品牌',
            notes: '',
            delivery_address: '杭州',
            primary_search_term: '测试物料',
            alt_search_terms: [],
            standardized_spec: '规格',
            standardized_unit: '个',
            quantity: 1,
            product_type: '标准品',
            llm_model: 'gpt',
            ai_reasoning: '',
            created_at: '2026-04-21T08:00:00.000Z',
          },
        ]}
        onStarted={onStarted}
      />,
    );

    await waitFor(() => expect(fetchAccountsMock).toHaveBeenCalledWith('user-1'));

    fireEvent.click(screen.getByRole('button', { name: '配置账户' }));
    fireEvent.click(screen.getByText('完成账户配置'));

    await waitFor(() => expect(screen.getByText('新配置账户')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: '启动搜索' }));

    await waitFor(() => {
      expect(toastErrorMock).toHaveBeenCalledWith('启动失败: network failed');
    });
    expect(onStarted).not.toHaveBeenCalled();
  });
});
