import React from 'react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { act, cleanup, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import StudioUploadQueue from '../StudioUploadQueue'

let pageMock = { props: {} }

vi.mock('@inertiajs/react', () => ({
  usePage: () => pageMock,
}))

vi.mock('../../../Layouts/StudioLayout', () => ({
  default: ({ children }) => <div>{children}</div>,
}))

function makeQueueProps(overrides = {}) {
  return {
    title: 'Upload Queue',
    description: 'Queue drafts',
    chunkSize: 5242880,
    chunkRequestTimeoutMs: 45000,
    contentTypes: [
      {
        name: 'Photography',
        categories: [
          { id: 10, name: 'Portraits', children: [] },
        ],
      },
    ],
    queue: {
      filters: { batch_id: 1, status: 'all', sort: 'newest' },
      batches: [{ id: 1, name: 'Spring Set' }],
      current_batch: {
        id: 1,
        name: 'Spring Set',
        status: 'completed_with_errors',
        total_items: 2,
        ready_items: 1,
        processing_items: 0,
        needs_review_items: 1,
        failed_items: 0,
        updated_at: '2026-04-18T10:00:00Z',
      },
      status_options: [
        { value: 'all', label: 'All' },
        { value: 'ready', label: 'Ready' },
        { value: 'needs_review', label: 'Needs review' },
      ],
      sort_options: [
        { value: 'newest', label: 'Newest first' },
        { value: 'filename', label: 'Filename' },
      ],
      items: [
        {
          id: 101,
          title: 'Ready draft',
          original_filename: 'ready.webp',
          status: 'ready',
          processing_stage: 'finalized',
          metadata_label: '100% complete',
          is_ready_to_publish: true,
          missing: [],
          error_message: null,
          updated_at: '2026-04-18T10:00:00Z',
          edit_url: '/studio/artworks/1/edit',
          actions: {
            can_edit: true,
            can_publish: true,
            can_delete: true,
            can_retry_processing: false,
            can_generate_ai: true,
          },
        },
        {
          id: 102,
          title: 'Needs review draft',
          original_filename: 'review.webp',
          status: 'needs_review',
          processing_stage: 'finalized',
          metadata_label: '75% complete',
          is_ready_to_publish: false,
          missing: ['Needs maturity review'],
          error_message: null,
          updated_at: '2026-04-18T11:00:00Z',
          edit_url: '/studio/artworks/2/edit',
          actions: {
            can_edit: true,
            can_publish: false,
            can_delete: true,
            can_retry_processing: false,
            can_generate_ai: true,
          },
        },
      ],
      ...overrides.queue,
    },
    ...overrides,
  }
}

describe('StudioUploadQueue', () => {
  beforeEach(() => {
    pageMock = { props: makeQueueProps() }
    window.axios = {
      get: vi.fn().mockResolvedValue({ data: pageMock.props.queue }),
      post: vi.fn().mockResolvedValue({ data: { success: 1, failed: 0, errors: [] } }),
    }
    window.confirm = vi.fn(() => true)
    window.prompt = vi.fn(() => 'DELETE')
  })

  afterEach(() => {
    cleanup()
    vi.useRealTimers()
    vi.restoreAllMocks()
  })

  it('renders mixed queue states and item actions', () => {
    render(<StudioUploadQueue />)

    expect(screen.getByText('Ready draft')).not.toBeNull()
    expect(screen.getByText('Needs review draft')).not.toBeNull()
    expect(screen.getAllByText('Ready to publish')[0]).not.toBeNull()
    expect(screen.getByText('Needs maturity review')).not.toBeNull()
    expect(screen.getAllByRole('link', { name: /edit in studio/i })).toHaveLength(2)
    expect(screen.getAllByRole('button', { name: /^generate ai$/i })).toHaveLength(3)
  })

  it('reloads the queue when filters change', async () => {
    const user = userEvent.setup()

    render(<StudioUploadQueue />)

    await user.selectOptions(screen.getByRole('combobox', { name: /filter/i }), 'ready')

    await waitFor(() => {
      expect(window.axios.get).toHaveBeenCalledWith('/api/studio/upload-queue', {
        params: expect.objectContaining({
          batch_id: 1,
          status: 'ready',
          sort: 'newest',
        }),
      })
    })
  })

  it('shows a publish confirmation summary before bulk publish', async () => {
    const user = userEvent.setup()

    render(<StudioUploadQueue />)

    const checkboxes = screen.getAllByRole('checkbox')
    const itemCheckboxes = checkboxes.slice(-2)
    await user.click(itemCheckboxes[0])
    await user.click(itemCheckboxes[1])
    await user.click(screen.getByRole('button', { name: /publish selected/i }))

    expect(window.confirm).toHaveBeenCalledWith([
      'Publish 1 ready draft(s)?',
      'Selected: 2',
      'Ready now: 1',
      'Blocked and skipped: 1',
      'Needs review: 1',
      'Blocked drafts will not be published.',
    ].join('\n'))

    await waitFor(() => {
      expect(window.axios.post).toHaveBeenCalledWith('/api/studio/upload-queue/bulk', expect.objectContaining({
        action: 'publish',
        item_ids: [101, 102],
      }))
    })
  })

  it('does not attempt bulk publish when no selected drafts are ready', async () => {
    const user = userEvent.setup()
    pageMock = {
      props: makeQueueProps({
        queue: {
          items: [
            {
              id: 202,
              title: 'Blocked draft',
              original_filename: 'blocked.webp',
              status: 'needs_metadata',
              processing_stage: 'finalized',
              metadata_label: '50% complete',
              is_ready_to_publish: false,
              missing: ['Missing title'],
              error_message: null,
              updated_at: '2026-04-18T10:00:00Z',
              edit_url: '/studio/artworks/3/edit',
              actions: {
                can_edit: true,
                can_publish: false,
                can_delete: true,
                can_retry_processing: false,
                can_generate_ai: true,
              },
            },
          ],
        },
      }),
    }

    render(<StudioUploadQueue />)

    const checkboxes = screen.getAllByRole('checkbox')
    await user.click(checkboxes.at(-1))
    await user.click(screen.getByRole('button', { name: /publish selected/i }))

    expect(window.confirm).not.toHaveBeenCalled()
    expect(window.axios.post).not.toHaveBeenCalledWith('/api/studio/upload-queue/bulk', expect.objectContaining({
      action: 'publish',
    }))
    expect(screen.getByText('None of the selected drafts are ready to publish yet.')).not.toBeNull()
  })

  it('shows the correct Studio links and publish readiness state per item', () => {
    render(<StudioUploadQueue />)

    const studioLinks = screen.getAllByRole('link', { name: /edit in studio/i })
    expect(studioLinks).toHaveLength(2)
    expect(studioLinks[0].getAttribute('href')).toBe('/studio/artworks/1/edit')
    expect(studioLinks[1].getAttribute('href')).toBe('/studio/artworks/2/edit')
    expect(screen.getAllByRole('button', { name: /^publish$/i })).toHaveLength(1)
  })

  it('bulk actions apply only to selected queue items', async () => {
    const user = userEvent.setup()

    render(<StudioUploadQueue />)

    const checkboxes = screen.getAllByRole('checkbox')
    const itemCheckboxes = checkboxes.slice(-2)
    await user.click(itemCheckboxes[0])
    await user.click(screen.getAllByRole('button', { name: /^generate ai$/i })[0])

    await waitFor(() => {
      expect(window.axios.post).toHaveBeenCalledWith('/api/studio/upload-queue/bulk', expect.objectContaining({
        action: 'generate_ai',
        item_ids: [101],
      }))
    })
  })

  it('shows failed items clearly and lets creators retry them', async () => {
    const user = userEvent.setup()
    pageMock = {
      props: makeQueueProps({
        queue: {
          current_batch: {
            id: 1,
            name: 'Spring Set',
            status: 'completed_with_errors',
            total_items: 1,
            ready_items: 0,
            processing_items: 0,
            needs_review_items: 0,
            failed_items: 1,
            updated_at: '2026-04-18T12:00:00Z',
          },
          items: [
            {
              id: 303,
              title: 'Broken draft',
              original_filename: 'broken.webp',
              status: 'failed',
              processing_stage: 'finalized',
              metadata_label: '25% complete',
              is_ready_to_publish: false,
              missing: ['Processing incomplete'],
              error_message: 'Derivative generation failed.',
              updated_at: '2026-04-18T12:00:00Z',
              edit_url: '/studio/artworks/4/edit',
              actions: {
                can_edit: true,
                can_publish: false,
                can_delete: true,
                can_retry_processing: true,
                can_generate_ai: true,
              },
            },
          ],
        },
      }),
    }

    render(<StudioUploadQueue />)

    expect(screen.getByText('Derivative generation failed.')).not.toBeNull()
    expect(screen.getByText('Processing incomplete')).not.toBeNull()

    await user.click(screen.getByRole('button', { name: /retry/i }))

    await waitFor(() => {
      expect(window.axios.post).toHaveBeenCalledWith('/api/studio/upload-queue/items/303/retry')
    })
  })

  it('polls the queue while processing items are still running', async () => {
    vi.useFakeTimers()
    pageMock = {
      props: makeQueueProps({
        queue: {
          current_batch: {
            id: 1,
            name: 'Spring Set',
            status: 'processing',
            total_items: 1,
            ready_items: 0,
            processing_items: 1,
            needs_review_items: 0,
            failed_items: 0,
            updated_at: '2026-04-18T12:15:00Z',
          },
          items: [
            {
              id: 404,
              title: 'Processing draft',
              original_filename: 'processing.webp',
              status: 'processing',
              processing_stage: 'maturity_check',
              metadata_label: '50% complete',
              is_ready_to_publish: false,
              missing: ['Maturity analysis pending'],
              error_message: null,
              updated_at: '2026-04-18T12:15:00Z',
              edit_url: '/studio/artworks/5/edit',
              actions: {
                can_edit: true,
                can_publish: false,
                can_delete: true,
                can_retry_processing: false,
                can_generate_ai: true,
              },
            },
          ],
        },
      }),
    }

    render(<StudioUploadQueue />)

    expect(screen.getByText('Maturity analysis pending')).not.toBeNull()
    expect(screen.queryByRole('button', { name: /^publish$/i })).toBeNull()

    await act(async () => {
      vi.advanceTimersByTime(3000)
      await Promise.resolve()
    })

    expect(window.axios.get).toHaveBeenCalledWith('/api/studio/upload-queue', {
      params: expect.objectContaining({
        batch_id: 1,
        status: 'all',
        sort: 'newest',
      }),
    })
  })
})