import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import type { Draft } from '@/lib/db/draft-service';

// Mock clipboard API
const mockClipboard = {
  writeText: vi.fn(),
};

Object.assign(navigator, {
  clipboard: mockClipboard,
});

// Mock DraftService
vi.mock('@/lib/db/draft-service', () => ({
  DraftService: {
    updateDraftStatus: vi.fn().mockResolvedValue(true),
    getDraftById: vi.fn(),
    markAsCompleted: vi.fn(),
  },
}));

// Mock chat store
vi.mock('@/lib/store/chat-store', () => ({
  useChatStore: vi.fn(),
}));

import { DraftService } from '@/lib/db/draft-service';
import { DraftViewSheet } from './DraftViewSheet';
import { useChatStore } from '@/lib/store/chat-store';

describe('DraftViewSheet Integration', () => {
  const mockDraft: Draft = {
    id: 1,
    sessionId: 'session-1',
    title: 'Test Draft',
    content: '# Test Draft\n\nThis is test content.',
    tags: ['test'],
    createdAt: Date.now(),
    status: 'draft',
  };

  // Create a mock state system
  let mockState = {
    currentDraft: null as Draft | null,
    showDraftView: false,
    closeDraftView: vi.fn(),
    approveDraft: vi.fn(),
    completeDraft: vi.fn(),
    copyDraftToClipboard: vi.fn(),
    rejectDraft: vi.fn(),
    startRefinement: vi.fn().mockResolvedValue(undefined),
  };

  beforeEach(() => {
    vi.clearAllMocks();
    mockState = {
      currentDraft: null,
      showDraftView: false,
      closeDraftView: vi.fn(),
      approveDraft: vi.fn(),
      completeDraft: vi.fn().mockResolvedValue(undefined),
      copyDraftToClipboard: vi.fn().mockResolvedValue(undefined),
      rejectDraft: vi.fn(),
      startRefinement: vi.fn().mockResolvedValue(undefined),
    };

    // Setup mock store function
    (useChatStore as any).mockImplementation((selector?: Function) => {
      return selector ? selector(mockState) : mockState;
    });
  });

  it('does not render when no draft is available', () => {
    render(<DraftViewSheet />);
    expect(screen.queryByTestId('sheet-backdrop')).not.toBeInTheDocument();
  });

  it('opens sheet when draft is available and showDraftView is true', () => {
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    expect(screen.getByTestId('sheet-backdrop')).toBeInTheDocument();
    expect(screen.getByTestId('sheet-content')).toBeInTheDocument();
    // Check by class selector since title appears twice (h2 title and h1 markdown)
    expect(document.querySelector('.draft-title')?.textContent).toBe('Test Draft');
  });

  it('renders draft content with Markdown', () => {
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    expect(screen.getByText('This is test content.')).toBeInTheDocument();
  });

  it('renders tags', () => {
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    expect(screen.getByText('#test')).toBeInTheDocument();
  });

  it('calls completeDraft when Approve button is clicked', async () => {
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;
    mockState.completeDraft.mockResolvedValue(undefined);

    (DraftService.getDraftById as any).mockResolvedValue(mockDraft);
    (DraftService.markAsCompleted as any).mockResolvedValue(mockDraft);

    render(<DraftViewSheet />);

    const approveButton = screen.getByRole('button', { name: /approve, copy to clipboard, and mark as completed/i });
    fireEvent.click(approveButton);

    await waitFor(() => {
      expect(mockState.completeDraft).toHaveBeenCalledWith(1);
    });
  });

  it('calls startRefinement when Thumbs Down is clicked', () => {
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    const rejectButton = screen.getByRole('button', { name: /request changes/i });
    fireEvent.click(rejectButton);

    // Story 2.3: Thumbs Down now triggers refinement flow
    expect(mockState.startRefinement).toHaveBeenCalledWith(1);
    expect(mockState.rejectDraft).toHaveBeenCalledWith(1);
  });

  it('calls closeDraftView when backdrop is clicked', () => {
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    const backdrop = screen.getByTestId('sheet-backdrop');
    fireEvent.click(backdrop);

    expect(mockState.closeDraftView).toHaveBeenCalledTimes(1);
  });

  it('disables chat input when draft view is open', () => {
    // This test verifies the integration with ChatWindow
    // The ChatWindow should disable input when showDraftView is true
    mockState.currentDraft = mockDraft;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    // Verify sheet is open
    expect(screen.getByTestId('sheet-content')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /approve, copy to clipboard, and mark as completed/i })).toBeInTheDocument();
  });

  it('handles empty tags array gracefully', () => {
    const draftWithoutTags: Draft = {
      ...mockDraft,
      tags: [],
    };

    mockState.currentDraft = draftWithoutTags;
    mockState.showDraftView = true;

    render(<DraftViewSheet />);

    expect(screen.queryByText('#test')).not.toBeInTheDocument();
  });

  describe('Story 2.4: Copy Only Button and Toast', () => {
    it('renders Copy Only button when onCopyOnly is provided', () => {
      mockState.currentDraft = mockDraft;
      mockState.showDraftView = true;

      render(<DraftViewSheet />);

      expect(screen.getByRole('button', { name: /copy to clipboard without closing/i })).toBeInTheDocument();
    });

    it('calls copyDraftToClipboard when Copy Only button is clicked', async () => {
      mockState.currentDraft = mockDraft;
      mockState.showDraftView = true;
      mockState.copyDraftToClipboard.mockResolvedValue(undefined);

      render(<DraftViewSheet />);

      const copyOnlyButton = screen.getByRole('button', { name: /copy to clipboard without closing/i });
      fireEvent.click(copyOnlyButton);

      await waitFor(() => {
        expect(mockState.copyDraftToClipboard).toHaveBeenCalledWith(1);
      });
    });

    it('shows toast with correct message when Approve is clicked', async () => {
      mockState.currentDraft = mockDraft;
      mockState.showDraftView = true;
      mockState.completeDraft.mockResolvedValue(undefined);

      render(<DraftViewSheet />);

      const approveButton = screen.getByRole('button', { name: /approve, copy to clipboard, and mark as completed/i });
      fireEvent.click(approveButton);

      await waitFor(() => {
        expect(mockState.completeDraft).toHaveBeenCalledWith(1);
      });

      // Toast is rendered in a separate fragment, check for live region
      await waitFor(() => {
        expect(screen.getByRole('status')).toBeInTheDocument();
      });
    });

    it('shows toast with correct message when Copy Only is clicked', async () => {
      mockState.currentDraft = mockDraft;
      mockState.showDraftView = true;
      mockState.copyDraftToClipboard.mockResolvedValue(undefined);

      render(<DraftViewSheet />);

      const copyOnlyButton = screen.getByRole('button', { name: /copy to clipboard without closing/i });
      fireEvent.click(copyOnlyButton);

      await waitFor(() => {
        expect(mockState.copyDraftToClipboard).toHaveBeenCalledWith(1);
      });

      // Toast is rendered in a separate fragment, check for live region
      await waitFor(() => {
        expect(screen.getByRole('status')).toBeInTheDocument();
      });
    });

    it('renders all action buttons including delete button (Story 3.2)', () => {
      mockState.currentDraft = mockDraft;
      mockState.showDraftView = true;

      render(<DraftViewSheet />);

      // Story 3.2: Now has 4 buttons: Delete, Not Quite, Just Copy, Approve
      const buttons = screen.getAllByRole('button');
      expect(buttons).toHaveLength(4);
    });
  });
});
