/**
 * @ai-summary Unit tests for DocumentsMobileScreen component
 * @ai-context Tests mobile UI with mocked hooks and navigation
 */

import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { DocumentsMobileScreen } from './DocumentsMobileScreen';
import { useDocumentsList } from '../hooks/useDocuments';
import { useUploadWithProgress } from '../hooks/useUploadWithProgress';
import { useNavigate } from 'react-router-dom';
import type { DocumentRecord } from '../types/documents.types';

// Mock dependencies
jest.mock('../hooks/useDocuments');
jest.mock('../hooks/useUploadWithProgress');
jest.mock('react-router-dom');

const mockUseDocumentsList = jest.mocked(useDocumentsList);
const mockUseUploadWithProgress = jest.mocked(useUploadWithProgress);
const mockUseNavigate = jest.mocked(useNavigate);

describe('DocumentsMobileScreen', () => {
  const mockNavigate = jest.fn();
  const mockUploadMutate = jest.fn();

  const mockDocuments: DocumentRecord[] = [
    {
      id: 'doc-1',
      user_id: 'user-1',
      vehicle_id: 'vehicle-1',
      document_type: 'insurance',
      title: 'Car Insurance',
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-01T00:00:00Z',
    },
    {
      id: 'doc-2',
      user_id: 'user-1',
      vehicle_id: 'vehicle-2',
      document_type: 'registration',
      title: 'Vehicle Registration',
      created_at: '2024-01-02T00:00:00Z',
      updated_at: '2024-01-02T00:00:00Z',
    },
  ];

  beforeEach(() => {
    jest.clearAllMocks();

    mockUseNavigate.mockReturnValue(mockNavigate);

    mockUseUploadWithProgress.mockReturnValue({
      mutate: mockUploadMutate,
      isPending: false,
      progress: 0,
      isSuccess: false,
      isError: false,
      error: null,
      resetProgress: jest.fn(),
      data: undefined,
      variables: undefined,
      isIdle: true,
      status: 'idle',
      mutateAsync: jest.fn(),
      reset: jest.fn(),
    } as any);

    mockUseDocumentsList.mockReturnValue({
      data: mockDocuments,
      isLoading: false,
      error: null,
      refetch: jest.fn(),
      isError: false,
      isPending: false,
      isSuccess: true,
      status: 'success',
      dataUpdatedAt: 0,
      errorUpdatedAt: 0,
      failureCount: 0,
      failureReason: null,
      errorUpdateCount: 0,
      isFetched: true,
      isFetchedAfterMount: true,
      isFetching: false,
      isInitialLoading: false,
      isPlaceholderData: false,
      isPaused: false,
      isRefetching: false,
      isRefetchError: false,
      isLoadingError: false,
      isStale: false,
    } as any);
  });

  describe('Document List Display', () => {
    it('should render documents list', () => {
      render(<DocumentsMobileScreen />);

      expect(screen.getByText('Documents')).toBeInTheDocument();
      expect(screen.getByText('Car Insurance')).toBeInTheDocument();
      expect(screen.getByText('Vehicle Registration')).toBeInTheDocument();
    });

    it('should display document metadata', () => {
      render(<DocumentsMobileScreen />);

      // Check document types and vehicle IDs are displayed
      expect(screen.getByText(/insurance/)).toBeInTheDocument();
      expect(screen.getByText(/registration/)).toBeInTheDocument();
      expect(screen.getByText(/vehicle-1/)).toBeInTheDocument();
      expect(screen.getByText(/vehicle-2/)).toBeInTheDocument();
    });

    it('should truncate long vehicle IDs', () => {
      const longVehicleId = 'very-long-vehicle-id-that-should-be-truncated';
      const documentsWithLongId = [
        {
          ...mockDocuments[0],
          vehicle_id: longVehicleId,
        },
      ];

      mockUseDocumentsList.mockReturnValue({
        data: documentsWithLongId,
        isLoading: false,
        error: null,
        refetch: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      // Should show truncated version
      expect(screen.getByText(/very-lon\.\.\./)).toBeInTheDocument();
      expect(screen.queryByText(longVehicleId)).not.toBeInTheDocument();
    });
  });

  describe('Loading States', () => {
    it('should show loading message', () => {
      mockUseDocumentsList.mockReturnValue({
        data: undefined,
        isLoading: true,
        error: null,
        refetch: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      expect(screen.getByText('Loading...')).toBeInTheDocument();
    });

    it('should show error message', () => {
      mockUseDocumentsList.mockReturnValue({
        data: undefined,
        isLoading: false,
        error: new Error('Failed to load'),
        refetch: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      expect(screen.getByText('Failed to load documents')).toBeInTheDocument();
    });

    it('should handle empty documents list', () => {
      mockUseDocumentsList.mockReturnValue({
        data: [],
        isLoading: false,
        error: null,
        refetch: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      expect(screen.getByText('Documents')).toBeInTheDocument();
      // Should not crash with empty list
    });
  });

  describe('Navigation', () => {
    it('should navigate to document detail when Open is clicked', async () => {
      const user = userEvent.setup();
      render(<DocumentsMobileScreen />);

      const openButtons = screen.getAllByText('Open');
      await user.click(openButtons[0]);

      expect(mockNavigate).toHaveBeenCalledWith('/garage/documents/doc-1');
    });

    it('should navigate to correct document for each Open button', async () => {
      const user = userEvent.setup();
      render(<DocumentsMobileScreen />);

      const openButtons = screen.getAllByText('Open');

      await user.click(openButtons[0]);
      expect(mockNavigate).toHaveBeenCalledWith('/garage/documents/doc-1');

      await user.click(openButtons[1]);
      expect(mockNavigate).toHaveBeenCalledWith('/garage/documents/doc-2');
    });
  });

  describe('File Upload', () => {
    let mockFileInput: HTMLInputElement;

    beforeEach(() => {
      // Mock file input element
      mockFileInput = document.createElement('input');
      mockFileInput.type = 'file';
      mockFileInput.click = jest.fn();
      jest.spyOn(document, 'createElement').mockReturnValue(mockFileInput as any);
    });

    it('should trigger file upload when Upload button is clicked', async () => {
      const user = userEvent.setup();
      render(<DocumentsMobileScreen />);

      const uploadButtons = screen.getAllByText('Upload');
      await user.click(uploadButtons[0]);

      // Should clear and click the hidden file input
      expect(mockFileInput.value).toBe('');
      expect(mockFileInput.click).toHaveBeenCalled();
    });

    it('should set correct document ID when upload button is clicked', async () => {
      const user = userEvent.setup();
      render(<DocumentsMobileScreen />);

      const uploadButtons = screen.getAllByText('Upload');
      await user.click(uploadButtons[1]); // Click second document's upload

      // Verify the component tracks the current document ID
      // This is tested indirectly through the file change handler
    });

    it('should handle file selection and upload', async () => {
      render(<DocumentsMobileScreen />);

      const uploadButtons = screen.getAllByText('Upload');
      fireEvent.click(uploadButtons[0]);

      // Simulate file selection
      const file = new File(['test content'], 'test.pdf', { type: 'application/pdf' });
      const fileInput = screen.getByRole('textbox', { hidden: true }) ||
                       document.querySelector('input[type="file"]') as HTMLInputElement;

      if (fileInput) {
        Object.defineProperty(fileInput, 'files', {
          value: [file],
          writable: false,
        });

        fireEvent.change(fileInput);

        expect(mockUploadMutate).toHaveBeenCalledWith(file);
      }
    });

    it('should show upload progress during upload', () => {
      mockUseUploadWithProgress.mockReturnValue({
        mutate: mockUploadMutate,
        isPending: true,
        progress: 45,
        isSuccess: false,
        isError: false,
        error: null,
        resetProgress: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      expect(screen.getByText('45%')).toBeInTheDocument();
    });

    it('should show progress only for the uploading document', async () => {
      const user = userEvent.setup();

      // Mock upload in progress for first document
      mockUseUploadWithProgress.mockImplementation((docId: string) => ({
        mutate: mockUploadMutate,
        isPending: docId === 'doc-1',
        progress: docId === 'doc-1' ? 75 : 0,
        isSuccess: false,
        isError: false,
        error: null,
        resetProgress: jest.fn(),
      } as any));

      render(<DocumentsMobileScreen />);

      // Click upload for first document
      const uploadButtons = screen.getAllByText('Upload');
      await user.click(uploadButtons[0]);

      // Should show progress for first document only
      expect(screen.getByText('75%')).toBeInTheDocument();

      // Should not show progress for other documents
      const progressElements = screen.getAllByText(/\d+%/);
      expect(progressElements).toHaveLength(1);
    });
  });

  describe('File Input Configuration', () => {
    it('should configure file input with correct accept types', () => {
      render(<DocumentsMobileScreen />);

      const fileInput = document.querySelector('input[type="file"]');
      expect(fileInput).toBeTruthy();
      expect(fileInput!).toHaveAttribute('accept', 'image/*,application/pdf');
    });

    it('should hide file input from UI', () => {
      render(<DocumentsMobileScreen />);

      const fileInput = document.querySelector('input[type="file"]');
      expect(fileInput).toBeTruthy();
      expect(fileInput!).toHaveClass('hidden');
    });
  });

  describe('Document Cards Layout', () => {
    it('should render documents in individual cards', () => {
      render(<DocumentsMobileScreen />);

      // Each document should be in its own bordered container
      const documentCards = screen.getAllByRole('generic').filter(el =>
        el.className.includes('border') && el.className.includes('rounded-xl')
      );

      expect(documentCards.length).toBeGreaterThan(0);
    });

    it('should display action buttons for each document', () => {
      render(<DocumentsMobileScreen />);

      const openButtons = screen.getAllByText('Open');
      const uploadButtons = screen.getAllByText('Upload');

      expect(openButtons).toHaveLength(mockDocuments.length);
      expect(uploadButtons).toHaveLength(mockDocuments.length);
    });
  });

  describe('Error Handling', () => {
    it('should handle missing vehicle_id gracefully', () => {
      const documentsWithMissingVehicle = [
        {
          ...mockDocuments[0],
          vehicle_id: null as any,
        },
      ];

      mockUseDocumentsList.mockReturnValue({
        data: documentsWithMissingVehicle,
        isLoading: false,
        error: null,
        refetch: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      // Should show placeholder for missing vehicle ID
      expect(screen.getByText('—')).toBeInTheDocument();
    });

    it('should handle upload errors gracefully', () => {
      mockUseUploadWithProgress.mockReturnValue({
        mutate: mockUploadMutate,
        isPending: false,
        progress: 0,
        isSuccess: false,
        isError: true,
        error: new Error('Upload failed'),
        resetProgress: jest.fn(),
      } as any);

      render(<DocumentsMobileScreen />);

      // Component should still render without crashing
      expect(screen.getByText('Documents')).toBeInTheDocument();
    });
  });

  describe('Accessibility', () => {
    it('should have proper heading structure', () => {
      render(<DocumentsMobileScreen />);

      const heading = screen.getByRole('heading', { name: 'Documents' });
      expect(heading).toBeInTheDocument();
      expect(heading.tagName).toBe('H2');
    });

    it('should have accessible buttons', () => {
      render(<DocumentsMobileScreen />);

      const openButtons = screen.getAllByRole('button', { name: 'Open' });
      const uploadButtons = screen.getAllByRole('button', { name: 'Upload' });

      expect(openButtons).toHaveLength(mockDocuments.length);
      expect(uploadButtons).toHaveLength(mockDocuments.length);
    });
  });
});
