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

import {
  FailureResolutionDialog,
  type FailureResolutionSubmission,
} from '@/components/shared/FailureResolutionDialog';
import type { StandardizationFailureItem } from '@/services/standardizedService';

function createFailureItem(overrides: Partial<StandardizationFailureItem> = {}): StandardizationFailureItem {
  return {
    id: 'failure-001',
    task_id: 'task-001',
    batch_id: 'BATCH-001',
    source_material_id: 'mat-001',
    original_name: '球墨铸铁井盖',
    original_spec: 'DN700',
    quantity: 12,
    unit: '套',
    invoice_type: '专票',
    standardized_name: '球墨铸铁井盖',
    can_search_1688: false,
    missing_required_fields: ['规格型号', '材质'],
    failure_reason: '缺少规格型号和材质，无法准确搜索',
    human_fix_hint: '请补充规格型号、材质',
    llm_model: 'glm-5.1',
    resolved_by_task_id: null,
    resolved_at: null,
    created_at: '2026-04-20T10:00:00.000Z',
    updated_at: '2026-04-20T10:00:00.000Z',
    source_snapshot: {
      id: 'mat-001',
      batch_id: 'BATCH-001',
      material_name: '球墨铸铁井盖',
      specification: 'DN700',
      quantity: 12,
      unit: '套',
      invoice_type: '专票',
      brand: '源品牌',
      remarks: '道路工程使用',
      delivery_address: '济南仓',
      technical_standard: 'GB/T 23858',
      material_requirement: '球墨铸铁',
      technical_requirement: '',
      applicable_conditions: '市政道路',
      test_requirement: '',
      acceptance_note: '',
      warranty_period: '',
      deadline: '',
      source_file: 'source.xlsx',
      created_at: '2026-04-20T09:00:00.000Z',
      created_by: 'user-001',
    },
    ...overrides,
  };
}

function installLocalStorageMock() {
  const store = new Map<string, string>();
  Object.defineProperty(window, 'localStorage', {
    configurable: true,
    value: {
      getItem: vi.fn((key: string) => store.get(key) ?? null),
      setItem: vi.fn((key: string, value: string) => {
        store.set(key, value);
      }),
      removeItem: vi.fn((key: string) => {
        store.delete(key);
      }),
      clear: vi.fn(() => {
        store.clear();
      }),
    },
  });
}

describe('FailureResolutionDialog', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    installLocalStorageMock();
    window.localStorage.clear();
  });

  afterEach(() => {
    vi.useRealTimers();
    window.localStorage.clear();
  });

  it('keeps independent drafts while switching queue items', () => {
    render(
      <FailureResolutionDialog
        open
        items={[
          createFailureItem({ id: 'failure-001', original_name: '球墨铸铁井盖' }),
          createFailureItem({
            id: 'failure-002',
            source_material_id: 'mat-002',
            original_name: '莱卡全站仪电池',
            missing_required_fields: ['品牌'],
            failure_reason: '缺少品牌',
            human_fix_hint: '请补充品牌',
          }),
        ]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'D400 DN700' } });
    fireEvent.click(screen.getByRole('button', { name: /莱卡全站仪电池/ }));
    fireEvent.change(screen.getByLabelText('品牌 *'), { target: { value: 'Leica' } });
    fireEvent.click(screen.getByRole('button', { name: /球墨铸铁井盖/ }));

    expect(screen.getByLabelText('规格型号 *')).toHaveValue('D400 DN700');
    fireEvent.click(screen.getByRole('button', { name: /莱卡全站仪电池/ }));
    expect(screen.getByLabelText('品牌 *')).toHaveValue('Leica');
  });

  it('auto-saves drafts locally and restores them when the dialog reopens', async () => {
    vi.useFakeTimers();
    const onOpenChange = vi.fn();
    const item = createFailureItem();
    const { rerender } = render(
      <FailureResolutionDialog
        open
        items={[item]}
        onOpenChange={onOpenChange}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'D400 DN700' } });
    expect(screen.getByText('保存中')).toBeInTheDocument();

    await act(async () => {
      vi.advanceTimersByTime(500);
    });

    expect(screen.getByText('已自动保存')).toBeInTheDocument();

    fireEvent.click(screen.getByRole('button', { name: '取消' }));
    expect(onOpenChange).toHaveBeenCalledWith(false);

    rerender(
      <FailureResolutionDialog
        open={false}
        items={[item]}
        onOpenChange={onOpenChange}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );
    rerender(
      <FailureResolutionDialog
        open
        items={[item]}
        onOpenChange={onOpenChange}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    expect(screen.getByLabelText('规格型号 *')).toHaveValue('D400 DN700');
    expect(screen.getByText('有草稿')).toBeInTheDocument();
  });

  it('keeps restored drafts isolated by batch and failure item', async () => {
    vi.useFakeTimers();
    const firstBatchItem = createFailureItem({ id: 'failure-001', batch_id: 'BATCH-001' });
    const secondBatchItem = createFailureItem({ id: 'failure-001', batch_id: 'BATCH-002' });
    const { rerender } = render(
      <FailureResolutionDialog
        open
        items={[firstBatchItem]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'BATCH-001 DN700' } });
    await act(async () => {
      vi.advanceTimersByTime(500);
    });

    rerender(
      <FailureResolutionDialog
        open
        items={[secondBatchItem]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    expect(screen.getByLabelText('规格型号 *')).toHaveValue('');
  });

  it('clears the submitted record draft after a successful success-pool action', async () => {
    vi.useFakeTimers();
    const onConfirmSuccessPool = vi.fn(async () => undefined);
    const item = createFailureItem({ missing_required_fields: ['规格型号'], failure_reason: '缺少规格型号', human_fix_hint: '请补充规格型号' });
    const { rerender } = render(
      <FailureResolutionDialog
        open
        items={[item]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={onConfirmSuccessPool}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'DN700' } });
    await act(async () => {
      vi.advanceTimersByTime(500);
    });
    vi.useRealTimers();

    fireEvent.click(screen.getByRole('button', { name: '确认入成功池' }));
    await waitFor(() => {
      expect(onConfirmSuccessPool).toHaveBeenCalledTimes(1);
    });

    rerender(
      <FailureResolutionDialog
        open={false}
        items={[item]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={onConfirmSuccessPool}
        onRetryAiStandardization={vi.fn()}
      />,
    );
    rerender(
      <FailureResolutionDialog
        open
        items={[item]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={onConfirmSuccessPool}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    expect(screen.getByLabelText('规格型号 *')).toHaveValue('');
    expect(screen.queryByText('有草稿')).not.toBeInTheDocument();
  });

  it('clears the submitted record draft after a successful retry action', async () => {
    vi.useFakeTimers();
    const onRetryAiStandardization = vi.fn(async () => undefined);
    const item = createFailureItem({ missing_required_fields: ['规格型号'], failure_reason: '缺少规格型号', human_fix_hint: '请补充规格型号' });
    const { rerender } = render(
      <FailureResolutionDialog
        open
        items={[item]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={onRetryAiStandardization}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'DN700' } });
    await act(async () => {
      vi.advanceTimersByTime(500);
    });
    vi.useRealTimers();

    fireEvent.click(screen.getByRole('button', { name: '重新 AI 标准化' }));
    await waitFor(() => {
      expect(onRetryAiStandardization).toHaveBeenCalledTimes(1);
    });

    rerender(
      <FailureResolutionDialog
        open={false}
        items={[item]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={onRetryAiStandardization}
      />,
    );
    rerender(
      <FailureResolutionDialog
        open
        items={[item]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={onRetryAiStandardization}
      />,
    );

    expect(screen.getByLabelText('规格型号 *')).toHaveValue('');
    expect(screen.queryByText('有草稿')).not.toBeInTheDocument();
  });

  it('submits only valid records and leaves invalid records in the queue with missing field errors', async () => {
    const onConfirmSuccessPool = vi.fn();
    render(
      <FailureResolutionDialog
        open
        items={[
          createFailureItem({
            id: 'failure-001',
            original_name: '已补充物料',
            missing_required_fields: ['规格型号'],
            failure_reason: '缺少规格型号',
            human_fix_hint: '请补充规格型号',
          }),
          createFailureItem({
            id: 'failure-002',
            source_material_id: 'mat-002',
            original_name: '待补充物料',
            missing_required_fields: ['品牌'],
            failure_reason: '缺少品牌',
            human_fix_hint: '请补充品牌',
          }),
        ]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={onConfirmSuccessPool}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'DN700' } });
    fireEvent.click(screen.getByRole('button', { name: '确认入成功池' }));

    expect(onConfirmSuccessPool).toHaveBeenCalledTimes(1);
    expect(onConfirmSuccessPool.mock.calls[0][0]).toEqual([
      expect.objectContaining<Partial<FailureResolutionSubmission>>({
        failureId: 'failure-001',
        supplement: expect.objectContaining({ spec_model: 'DN700' }),
      }),
    ]);

    await waitFor(() => {
      expect(screen.queryByRole('button', { name: /已补充物料/ })).not.toBeInTheDocument();
    });
    expect(screen.getByRole('button', { name: /待补充物料/ })).toBeInTheDocument();
    expect(screen.getAllByText('缺少：品牌').length).toBeGreaterThan(0);
  });

  it('keeps callback failures in the queue after valid records are submitted', async () => {
    const onConfirmSuccessPool = vi.fn<(submissions: FailureResolutionSubmission[]) => Promise<{ failedIds: string[] }>>(async () => ({
      failedIds: ['failure-002'],
    }));
    render(
      <FailureResolutionDialog
        open
        items={[
          createFailureItem({
            id: 'failure-001',
            original_name: '写入成功物料',
            missing_required_fields: ['规格型号'],
            failure_reason: '缺少规格型号',
            human_fix_hint: '请补充规格型号',
          }),
          createFailureItem({
            id: 'failure-002',
            source_material_id: 'mat-002',
            original_name: '写入失败物料',
            missing_required_fields: ['品牌'],
            failure_reason: '缺少品牌',
            human_fix_hint: '请补充品牌',
          }),
        ]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={onConfirmSuccessPool}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    fireEvent.change(screen.getByLabelText('规格型号 *'), { target: { value: 'DN700' } });
    fireEvent.click(screen.getByRole('button', { name: /写入失败物料/ }));
    fireEvent.change(screen.getByLabelText('品牌 *'), { target: { value: 'Leica' } });
    fireEvent.click(screen.getByRole('button', { name: '确认入成功池' }));

    await waitFor(() => {
      expect(onConfirmSuccessPool).toHaveBeenCalledTimes(1);
    });

    const submitted = onConfirmSuccessPool.mock.calls[0]?.[0] as FailureResolutionSubmission[];
    expect(submitted).toHaveLength(2);
    await waitFor(() => {
      expect(screen.queryByRole('button', { name: /写入成功物料/ })).not.toBeInTheDocument();
    });
    expect(screen.getByRole('button', { name: /写入失败物料/ })).toBeInTheDocument();
    expect(screen.getAllByText('缺少：提交失败').length).toBeGreaterThan(0);
  });

  it('renders AI suggestion prominently and auxiliary source details in a collapsible section', () => {
    render(
      <FailureResolutionDialog
        open
        items={[createFailureItem()]}
        onOpenChange={vi.fn()}
        onConfirmSuccessPool={vi.fn()}
        onRetryAiStandardization={vi.fn()}
      />,
    );

    expect(screen.getByRole('heading', { name: '球墨铸铁井盖' })).toBeInTheDocument();
    expect(screen.getByText('请补充规格型号、材质')).toBeInTheDocument();

    const details = screen.getByText('原始信息').closest('button') ?? screen.getByText('原始信息');
    fireEvent.click(details);
    const sourcePanel = screen.getByTestId('failure-source-details');
    expect(within(sourcePanel).getByText('DN700')).toBeInTheDocument();
    expect(within(sourcePanel).getByText('12 套')).toBeInTheDocument();
    expect(within(sourcePanel).getByText('济南仓')).toBeInTheDocument();
  });
});
