// sort-imports-ignore
/**
 * @vitest-environment jsdom
 */

// IMPORTANT: Import ClipMenu-specific mocks FIRST before any other imports
// This ensures vi.mock() calls are hoisted properly
import './setup/clipMenuMocks';

import { render } from '@testing-library/react';
import React from 'react';
import { beforeEach, describe, expect, it, test, vi } from 'vitest';

import { ClipContextProvider } from '../ClipContext';
import {
  MoreMenuContents,
  MultiSelectMenuContents,
  SingleUntrashedMoreMenuContents,
  TrashedMenuContents,
  TrashedMultiSelectMenuContents,
} from '../ClipMenus';
import MultiSelectContext from '../MultiSelectContext';
import {
  CLIP_FIXTURES,
  SESSION_FIXTURES,
  TRASHED_SCENARIOS,
  UNTRASHED_SCENARIOS,
} from './fixtures';
import { extractMenuStructureFromRendered } from './utils/menuTestHelpers';
import { mockClipHelpers, mockStoresForClip } from './utils/mockHelpers';

describe('ClipMenu Rendering Tests', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('SingleUntrashedMoreMenuContents', () => {
    describe('Snapshot tests for all scenarios', () => {
      test.each(UNTRASHED_SCENARIOS)('$name', ({ clip, session }) => {
        // Use new mock system
        mockStoresForClip(clip, session);

        const { container } = render(
          <ClipContextProvider clip={clip as any}>
            <SingleUntrashedMoreMenuContents />
          </ClipContextProvider>
        );

        const menuStructure = extractMenuStructureFromRendered(container);

        // Snapshot the structure
        expect(menuStructure).toMatchSnapshot();
      });
    });

    describe('Specific scenario validations', () => {
      it('should show Remix/Edit for owner complete public clip', () => {
        const clip = CLIP_FIXTURES.COMPLETE_OWN_PUBLIC;
        const session = SESSION_FIXTURES.OWNER_PRO;

        mockStoresForClip(clip, session);
        mockClipHelpers({ isOwnClip: true, isStaff: false });

        const { container } = render(
          <ClipContextProvider clip={clip as any}>
            <SingleUntrashedMoreMenuContents />
          </ClipContextProvider>
        );

        // Find Remix/Edit button using semantic query
        const buttons = container.querySelectorAll(
          'button.context-menu-button'
        );
        const remixEditButton = Array.from(buttons).find((button) =>
          button.textContent?.includes('Remix/Edit')
        );

        expect(remixEditButton).toBeTruthy();
        expect(remixEditButton?.getAttribute('aria-disabled')).not.toBe('true');
      });

      it('should show Create menu for logged in users', () => {
        const clip = CLIP_FIXTURES.COMPLETE_OWN_PUBLIC;
        const session = SESSION_FIXTURES.OWNER_PRO;

        mockStoresForClip(clip, session);

        const { container } = render(
          <ClipContextProvider clip={clip as any}>
            <SingleUntrashedMoreMenuContents />
          </ClipContextProvider>
        );

        // Find Create button using semantic query
        const buttons = container.querySelectorAll(
          'button.context-menu-button'
        );
        const createButton = Array.from(buttons).find((button) =>
          button.textContent?.includes('Create')
        );

        expect(createButton).toBeTruthy();
      });

      it('should not show Create menu for logged out users', () => {
        const clip = CLIP_FIXTURES.COMPLETE_OTHER_REMIXABLE;
        const session = SESSION_FIXTURES.LOGGED_OUT;

        mockStoresForClip(clip, session);

        const { container } = render(
          <ClipContextProvider clip={clip as any}>
            <SingleUntrashedMoreMenuContents />
          </ClipContextProvider>
        );

        // Find Create button - should not exist for logged out users
        const buttons = container.querySelectorAll(
          'button.context-menu-button'
        );
        const createButton = Array.from(buttons).find((button) =>
          button.textContent?.includes('Create')
        );

        expect(createButton).toBeFalsy();
      });
    });
  });

  describe('TrashedMenuContents', () => {
    test.each(TRASHED_SCENARIOS)('$name', ({ clip, session }) => {
      mockStoresForClip(clip, session);
      mockClipHelpers({ isOwnClip: clip.user_id === session.userId });

      const { container } = render(
        <ClipContextProvider clip={clip as any}>
          <TrashedMenuContents />
        </ClipContextProvider>
      );

      const menuStructure = extractMenuStructureFromRendered(container);
      expect(menuStructure).toMatchSnapshot();
    });

    it('should show restore and delete options', () => {
      const clip = CLIP_FIXTURES.TRASHED_OWN;
      const session = SESSION_FIXTURES.OWNER_FREE;

      mockStoresForClip(clip, session);

      const { container } = render(
        <ClipContextProvider clip={clip as any}>
          <TrashedMenuContents />
        </ClipContextProvider>
      );

      // Find restore and delete buttons using semantic queries
      const buttons = container.querySelectorAll('button.context-menu-button');
      const restoreButton = Array.from(buttons).find((button) =>
        button.textContent?.includes('Restore')
      );
      const deleteButton = Array.from(buttons).find((button) =>
        button.textContent?.includes('Delete')
      );

      expect(restoreButton).toBeTruthy();
      expect(deleteButton).toBeTruthy();
    });
  });

  describe('MultiSelectMenuContents', () => {
    it('should show multi-select specific actions', () => {
      const clip = CLIP_FIXTURES.COMPLETE_OWN_PUBLIC;
      const session = SESSION_FIXTURES.OWNER_FREE;
      const multiSelectContext = {
        selectedClipIds: [clip.id!, 'clip-2', 'clip-3'],
        clear: vi.fn(),
        toggle: vi.fn(),
        isSelected: vi.fn(),
      };

      mockStoresForClip(clip, session);

      const { container } = render(
        <MultiSelectContext.Provider value={multiSelectContext as any}>
          <ClipContextProvider clip={clip as any}>
            <MultiSelectMenuContents />
          </ClipContextProvider>
        </MultiSelectContext.Provider>
      );

      const menuStructure = extractMenuStructureFromRendered(container);
      expect(menuStructure).toMatchSnapshot();
    });
  });

  describe('TrashedMultiSelectMenuContents', () => {
    it('should show multi-select options for trashed clips', () => {
      const clip = CLIP_FIXTURES.TRASHED_OWN;
      const session = SESSION_FIXTURES.OWNER_FREE;

      mockStoresForClip(clip, session);

      const { container } = render(
        <ClipContextProvider clip={clip as any}>
          <TrashedMultiSelectMenuContents />
        </ClipContextProvider>
      );

      const menuStructure = extractMenuStructureFromRendered(container);
      expect(menuStructure).toMatchSnapshot();
    });
  });

  describe('MoreMenuContents (wrapper)', () => {
    it('should render SingleUntrashedMoreMenuContents for untrashed clips', () => {
      const clip = CLIP_FIXTURES.COMPLETE_OWN_PUBLIC;
      const session = SESSION_FIXTURES.OWNER_PRO;
      const multiSelectContext = {
        selectedClipIds: [],
        clear: vi.fn(),
        toggle: vi.fn(),
        isSelected: vi.fn(),
      };

      mockStoresForClip(clip, session);
      // mockClipHelpers({
      //   isOwnClip: clip.user_id === session.userId,
      //   isStaff: false,
      // });

      const { container } = render(
        <MultiSelectContext.Provider value={multiSelectContext as any}>
          <ClipContextProvider clip={clip as any}>
            <MoreMenuContents />
          </ClipContextProvider>
        </MultiSelectContext.Provider>
      );

      expect(container).toBeTruthy();
    });

    it('should render TrashedMenuContents for trashed clips', () => {
      const clip = CLIP_FIXTURES.TRASHED_OWN;
      const session = SESSION_FIXTURES.OWNER_PRO;
      const multiSelectContext = {
        selectedClipIds: [],
        clear: vi.fn(),
        toggle: vi.fn(),
        isSelected: vi.fn(),
      };

      mockStoresForClip(clip, session);

      const { container } = render(
        <MultiSelectContext.Provider value={multiSelectContext as any}>
          <ClipContextProvider clip={clip as any}>
            <MoreMenuContents />
          </ClipContextProvider>
        </MultiSelectContext.Provider>
      );

      expect(container).toBeTruthy();
    });
  });
});
