/**
 * use-template-generation-actions.test.ts
 *
 * TDD 测试文件 - 测试模板生成记录的删除功能
 *
 * 测试覆盖：
 * 1. 单个删除成功场景
 * 2. 单个删除失败场景
 * 3. 批量删除成功场景（可选）
 * 4. 批量删除失败场景（可选）
 */

import { renderHook, act, waitFor } from '@testing-library/react-native'
import { root } from '@repo/core'
import { TemplateGenerationController } from '@repo/sdk'
import { useDeleteGeneration, useBatchDeleteGenerations } from '@/hooks/use-template-generation-actions'

// Mock SDK
jest.mock('@repo/core', () => ({
  root: {
    get: jest.fn(),
  },
}))

describe('use-template-generation-actions', () => {
  // 在每个测试前重置所有 mocks
  beforeEach(() => {
    jest.clearAllMocks()
  })

  describe('useDeleteGeneration', () => {
    it('应该成功删除单个生成记录', async () => {
      // Arrange: 准备测试数据
      const mockDelete = jest.fn().mockResolvedValue({ message: '删除成功' })
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act: 渲染 hook 并执行删除
      const { result } = renderHook(() => useDeleteGeneration())

      await act(async () => {
        const response = await result.current.deleteGeneration('test-id-123')
        // Assert: 验证返回值
        expect(response).toEqual({
          data: { message: '删除成功' },
          error: null,
        })
      })

      // Assert: 验证控制器被正确调用
      expect(root.get).toHaveBeenCalledWith(TemplateGenerationController)
      expect(mockDelete).toHaveBeenCalledWith({ id: 'test-id-123' })
      expect(mockDelete).toHaveBeenCalledTimes(1)
    })

    it('删除失败时应该返回错误信息', async () => {
      // Arrange: 准备测试数据和模拟错误
      const mockError = {
        message: '删除失败：记录不存在',
        code: 'NOT_FOUND',
      }
      const mockDelete = jest.fn().mockRejectedValue(mockError)
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act: 渲染 hook 并执行删除
      const { result } = renderHook(() => useDeleteGeneration())

      await act(async () => {
        const response = await result.current.deleteGeneration('non-existent-id')
        // Assert: 验证返回的错误信息
        expect(response).toEqual({
          data: null,
          error: mockError,
        })
      })

      // Assert: 验证控制器被调用
      expect(mockDelete).toHaveBeenCalledWith({ id: 'non-existent-id' })
    })

    it('删除过程中应该设置正确的加载状态', async () => {
      // Arrange: 准备异步测试
      const mockDelete = jest.fn().mockImplementation(
        () =>
          new Promise((resolve) => {
            setTimeout(() => resolve({ message: '删除成功' }), 100)
          }),
      )
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act: 渲染 hook
      const { result } = renderHook(() => useDeleteGeneration())

      // Assert: 初始状态应该是未加载
      expect(result.current.loading).toBe(false)

      // Act: 开始删除
      const deletePromise = act(async () => {
        await result.current.deleteGeneration('test-id')
      })

      // Assert: 删除过程中应该是加载状态
      await waitFor(() => {
        expect(result.current.loading).toBe(true)
      })

      await deletePromise

      // Assert: 删除完成后应该重置加载状态
      await waitFor(() => {
        expect(result.current.loading).toBe(false)
      })
    })

    it('删除失败后应该更新错误状态', async () => {
      // Arrange
      const mockError = {
        message: '网络错误',
        code: 'NETWORK_ERROR',
      }
      const mockDelete = jest.fn().mockRejectedValue(mockError)
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useDeleteGeneration())

      await act(async () => {
        await result.current.deleteGeneration('test-id')
      })

      // Assert: 验证错误状态
      expect(result.current.error).toEqual(mockError)
    })

    it('连续调用多次删除应该正确处理', async () => {
      // Arrange
      const mockDelete = jest.fn()
        .mockResolvedValueOnce({ message: '第一次删除成功' })
        .mockResolvedValueOnce({ message: '第二次删除成功' })
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useDeleteGeneration())

      await act(async () => {
        const response1 = await result.current.deleteGeneration('id-1')
        const response2 = await result.current.deleteGeneration('id-2')

        // Assert
        expect(response1.data?.message).toBe('第一次删除成功')
        expect(response2.data?.message).toBe('第二次删除成功')
      })

      // Assert: 验证调用次数
      expect(mockDelete).toHaveBeenCalledTimes(2)
      expect(mockDelete).toHaveBeenNthCalledWith(1, { id: 'id-1' })
      expect(mockDelete).toHaveBeenNthCalledWith(2, { id: 'id-2' })
    })
  })

  describe('useBatchDeleteGenerations', () => {
    it('应该成功批量删除生成记录', async () => {
      // Arrange
      const mockBatchDelete = jest.fn().mockResolvedValue({
        message: '批量删除成功',
        deletedCount: 3,
      })
      const mockController = {
        batchDelete: mockBatchDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useBatchDeleteGenerations())

      await act(async () => {
        const response = await result.current.batchDeleteGenerations([
          'id-1',
          'id-2',
          'id-3',
        ])

        // Assert
        expect(response).toEqual({
          data: {
            message: '批量删除成功',
            deletedCount: 3,
          },
          error: null,
        })
      })

      // Assert: 验证控制器被正确调用
      expect(root.get).toHaveBeenCalledWith(TemplateGenerationController)
      expect(mockBatchDelete).toHaveBeenCalledWith({
        ids: ['id-1', 'id-2', 'id-3'],
      })
    })

    it('批量删除失败时应该返回错误信息', async () => {
      // Arrange
      const mockError = {
        message: '批量删除失败：部分记录不存在',
        code: 'PARTIAL_FAILURE',
      }
      const mockBatchDelete = jest.fn().mockRejectedValue(mockError)
      const mockController = {
        batchDelete: mockBatchDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useBatchDeleteGenerations())

      await act(async () => {
        const response = await result.current.batchDeleteGenerations([
          'id-1',
          'id-2',
        ])

        // Assert
        expect(response).toEqual({
          data: null,
          error: mockError,
        })
      })

      expect(mockBatchDelete).toHaveBeenCalledWith({
        ids: ['id-1', 'id-2'],
      })
    })

    it('批量删除时应该设置正确的加载状态', async () => {
      // Arrange
      const mockBatchDelete = jest.fn().mockImplementation(
        () =>
          new Promise((resolve) => {
            setTimeout(() => resolve({ message: '批量删除成功' }), 100)
          }),
      )
      const mockController = {
        batchDelete: mockBatchDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useBatchDeleteGenerations())

      expect(result.current.loading).toBe(false)

      // Act
      const deletePromise = act(async () => {
        await result.current.batchDeleteGenerations(['id-1', 'id-2'])
      })

      // Assert: 删除过程中
      await waitFor(() => {
        expect(result.current.loading).toBe(true)
      })

      await deletePromise

      // Assert: 删除完成后
      await waitFor(() => {
        expect(result.current.loading).toBe(false)
      })
    })

    it('传入空数组时应该正常处理', async () => {
      // Arrange
      const mockBatchDelete = jest.fn().mockResolvedValue({
        message: '批量删除成功',
        deletedCount: 0,
      })
      const mockController = {
        batchDelete: mockBatchDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useBatchDeleteGenerations())

      await act(async () => {
        const response = await result.current.batchDeleteGenerations([])

        // Assert
        expect(response.data?.deletedCount).toBe(0)
      })

      expect(mockBatchDelete).toHaveBeenCalledWith({ ids: [] })
    })
  })

  describe('边界情况', () => {
    it('应该处理 ID 为空字符串的情况', async () => {
      // Arrange
      const mockDelete = jest.fn().mockResolvedValue({ message: '删除成功' })
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useDeleteGeneration())

      await act(async () => {
        await result.current.deleteGeneration('')
      })

      // Assert: 即使是空字符串，也应该调用 API
      expect(mockDelete).toHaveBeenCalledWith({ id: '' })
    })

    it('应该处理超长 ID 的情况', async () => {
      // Arrange
      const longId = 'a'.repeat(1000)
      const mockDelete = jest.fn().mockResolvedValue({ message: '删除成功' })
      const mockController = {
        delete: mockDelete,
      } as unknown as TemplateGenerationController

      ;(root.get as jest.Mock).mockReturnValue(mockController)

      // Act
      const { result } = renderHook(() => useDeleteGeneration())

      await act(async () => {
        await result.current.deleteGeneration(longId)
      })

      // Assert
      expect(mockDelete).toHaveBeenCalledWith({ id: longId })
    })
  })
})
