import React from 'react'
import { render, fireEvent, waitFor } from '@testing-library/react-native'
import { View, Text } from 'react-native'
import TemplateDetailScreen from './templateDetail'

// Mock expo-router
jest.mock('expo-router', () => ({
  useRouter: jest.fn(() => ({
    back: jest.fn(),
    push: jest.fn(),
  })),
  useLocalSearchParams: jest.fn(() => ({ id: 'test-template-id' })),
}))

// Mock react-i18next
jest.mock('react-i18next', () => ({
  useTranslation: jest.fn(() => ({
    t: (key: string) => key,
  })),
}))

// Mock expo-status-bar
jest.mock('expo-status-bar', () => ({
  StatusBar: 'StatusBar',
}))

// Mock react-native-safe-area-context
jest.mock('react-native-safe-area-context', () => ({
  SafeAreaView: ({ children }: { children: React.ReactNode }) => (
    <View>{children}</View>
  ),
}))

// Mock components
jest.mock('@/components/icon', () => ({
  LeftArrowIcon: () => null,
}))

jest.mock('@/components/SearchResultsGrid', () => ({
  __esModule: true,
  default: () => null,
}))

jest.mock('@/components/DynamicForm', () => {
  const { View, Text } = require('react-native')
  return {
    __esModule: true,
    DynamicForm: React.forwardRef(({ formSchema, onSubmit, onOpenDrawer }: any, ref: any) => (
      <View testID="dynamic-form">
        <Text onPress={() => onSubmit({})}>Submit Form</Text>
      </View>
    )),
  }
})

jest.mock('@/components/ui/Toast', () => ({
  __esModule: true,
  default: {
    show: jest.fn(),
    showLoading: jest.fn(),
    hideLoading: jest.fn(),
  },
}))

jest.mock('@/components/drawer/UploadReferenceImageDrawer', () => ({
  __esModule: true,
  default: () => null,
}))

jest.mock('@/components/blocks/ui/SocialActionBar', () => ({
  __esModule: true,
  SocialActionBar: jest.fn(() => null),
}))

// Mock hooks
jest.mock('@/hooks', () => ({
  useTemplateActions: jest.fn(() => ({
    runTemplate: jest.fn().mockResolvedValue({ generationId: 'gen-123' }),
  })),
  useTemplateDetail: jest.fn(() => ({
    data: {
      id: 'test-template-id',
      title: 'Test Template',
      titleEn: 'Test Template',
      formSchema: {
        startNodes: [
          {
            id: 'node_1',
            type: 'text',
            data: { label: '文本节点', text: '默认文本' },
          },
        ],
      },
    },
    loading: false,
    error: null,
    execute: jest.fn(),
  })),
  useTemplateGenerations: jest.fn(() => ({
    generations: [],
    loading: false,
    execute: jest.fn(),
  })),
  useTemplateLike: jest.fn(() => ({
    liked: false,
    loading: false,
    error: null,
    like: jest.fn().mockResolvedValue({}),
    unlike: jest.fn().mockResolvedValue({}),
    checkLiked: jest.fn().mockResolvedValue({}),
  })),
  useTemplateFavorite: jest.fn(() => ({
    favorited: false,
    loading: false,
    error: null,
    favorite: jest.fn().mockResolvedValue({ data: null, error: null }),
    unfavorite: jest.fn().mockResolvedValue({ data: null, error: null }),
    checkFavorited: jest.fn().mockResolvedValue({ data: null, error: null }),
  })),
}))

import { useTemplateActions, useTemplateDetail, useTemplateGenerations, useTemplateLike, useTemplateFavorite } from '@/hooks'
import Toast from '@/components/ui/Toast'

const mockUseTemplateActions = useTemplateActions as jest.MockedFunction<typeof useTemplateActions>
const mockUseTemplateDetail = useTemplateDetail as jest.MockedFunction<typeof useTemplateDetail>
const mockUseTemplateGenerations = useTemplateGenerations as jest.MockedFunction<typeof useTemplateGenerations>
const mockUseTemplateLike = useTemplateLike as jest.MockedFunction<typeof useTemplateLike>
const mockUseTemplateFavorite = useTemplateFavorite as jest.MockedFunction<typeof useTemplateFavorite>

describe('TemplateDetail Screen', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })

  describe('Loading State', () => {
    it('should show loading indicator when template is loading', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: undefined,
        loading: true,
        error: null,
        execute: jest.fn(),
      } as any)

      const { getByTestId } = render(<TemplateDetailScreen />)

      // Should show loading state
      expect(mockUseTemplateDetail).toHaveBeenCalled()
    })

    it('should not show loading when template data is loaded', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
          titleEn: 'Test Template',
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { queryByText } = render(<TemplateDetailScreen />)

      expect(queryByText('加载中...')).toBeNull()
    })
  })

  describe('Error State', () => {
    it('should show error message when template loading fails', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: undefined,
        loading: false,
        error: { message: 'Failed to load' },
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      expect(getByText('加载失败，请返回重试')).toBeTruthy()
    })

    it('should show retry button on error', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: undefined,
        loading: false,
        error: { message: 'Failed to load' },
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      expect(getByText('返回')).toBeTruthy()
    })
  })

  describe('Template Display', () => {
    it('should display template title', () => {
      const mockData = {
        id: 'test-id',
        title: 'Test Template',
        titleEn: 'Test Template',
      }

      mockUseTemplateDetail.mockReturnValue({
        data: mockData,
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getAllByText } = render(<TemplateDetailScreen />)

      // Title appears in both header and main title section
      const titles = getAllByText('Test Template')
      expect(titles.length).toBeGreaterThan(0)
    })

    it('should display start creating button when no formSchema', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
          formSchema: {
            startNodes: [],
          },
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      expect(getByText('templateDetail.startCreating')).toBeTruthy()
    })

    it('should display generations section', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      expect(getByText('templateDetail.generations')).toBeTruthy()
    })
  })

  describe('DynamicForm Integration', () => {
    it('should show form inline when formSchema exists', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
          formSchema: {
            startNodes: [
              {
                id: 'node_1',
                type: 'text',
                data: { label: '文本' },
              },
            ],
          },
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByTestId } = render(<TemplateDetailScreen />)

      // Form should be displayed inline
      expect(getByTestId('dynamic-form')).toBeTruthy()
    })

    it('should navigate to generateVideo when start creating is pressed with no formSchema', () => {
      const mockPush = jest.fn()
      const mockRouter = { push: mockPush, back: jest.fn() }

      // Update the router mock
      jest.spyOn(require('expo-router'), 'useRouter').mockReturnValue(mockRouter)

      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
          formSchema: {
            startNodes: [],
          },
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      const startButton = getByText('templateDetail.startCreating')
      fireEvent.press(startButton)

      // Should have pushed to generateVideo route
      expect(mockPush).toHaveBeenCalled()
    })

    it('should handle form submission correctly', async () => {
      const mockRunTemplate = jest.fn().mockResolvedValue({
        generationId: 'gen-123',
      })

      mockUseTemplateActions.mockReturnValue({
        runTemplate: mockRunTemplate,
        loading: false,
        error: null,
      } as any)

      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
          formSchema: {
            startNodes: [
              {
                id: 'node_1',
                type: 'text',
                data: { label: '文本' },
              },
            ],
          },
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByTestId, getByText } = render(<TemplateDetailScreen />)

      // Form is shown inline
      const form = getByTestId('dynamic-form')
      expect(form).toBeTruthy()

      // Submit form via the mocked submit button
      const submitButton = getByText('Submit Form')
      fireEvent.press(submitButton)

      await waitFor(() => {
        expect(mockRunTemplate).toHaveBeenCalledWith({
          templateId: 'test-template-id',
          data: {},
        })
        expect(Toast.show).toHaveBeenCalledWith({
          title: 'templateDetail.generationStarted',
        })
      })
    })

    it('should handle form submission errors', async () => {
      const mockRunTemplate = jest.fn().mockResolvedValue({
        error: { message: 'Submission failed' },
      })

      mockUseTemplateActions.mockReturnValue({
        runTemplate: mockRunTemplate,
        loading: false,
        error: null,
      } as any)

      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
          formSchema: {
            startNodes: [
              {
                id: 'node_1',
                type: 'text',
                data: { label: '文本' },
              },
            ],
          },
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByTestId, getByText } = render(<TemplateDetailScreen />)

      // Form is shown inline
      expect(getByTestId('dynamic-form')).toBeTruthy()

      const submitButton = getByText('Submit Form')
      fireEvent.press(submitButton)

      await waitFor(() => {
        expect(mockRunTemplate).toHaveBeenCalled()
      })
    })
  })

  describe('Generations Display', () => {
    it('should display generations when available', () => {
      const mockGenerations = [
        {
          id: 'gen-1',
          template: { title: 'Template 1' },
          resultUrl: ['http://example.com/image1.jpg'],
          originalUrl: 'http://example.com/thumb1.jpg',
        },
        {
          id: 'gen-2',
          template: { titleEn: 'Template 2' },
          resultUrl: ['http://example.com/image2.jpg'],
          originalUrl: 'http://example.com/thumb2.jpg',
        },
      ]

      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: mockGenerations as any,
        loading: false,
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      expect(getByText('templateDetail.generations')).toBeTruthy()
    })

    it('should show loading indicator when loading generations', () => {
      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
        },
        loading: false,
        error: null,
        execute: jest.fn(),
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [{ id: 'gen-1' }] as any,
        loading: true,
        execute: jest.fn(),
      } as any)

      const { getByText } = render(<TemplateDetailScreen />)

      expect(getByText('加载中...')).toBeTruthy()
    })
  })

  describe('Data Fetching', () => {
    it('should fetch template detail and generations on mount', () => {
      const mockExecuteDetail = jest.fn()
      const mockExecuteGenerations = jest.fn()

      mockUseTemplateDetail.mockReturnValue({
        data: {
          id: 'test-id',
          title: 'Test Template',
        },
        loading: false,
        error: null,
        execute: mockExecuteDetail,
      } as any)

      mockUseTemplateGenerations.mockReturnValue({
        generations: [],
        loading: false,
        execute: mockExecuteGenerations,
      } as any)

      render(<TemplateDetailScreen />)

      expect(mockExecuteDetail).toHaveBeenCalledWith({ id: 'test-template-id' })
      expect(mockExecuteGenerations).toHaveBeenCalledWith({
        templateId: 'test-template-id',
        page: 1,
        limit: 20,
      })
    })
  })
})
