import { fromJS } from 'immutable';

import { makeSelectDemoVideoAndLink, setInjectedTags } from 'v2Containers/Cap/selectors';

describe('CapSelectors', () => {
  const mockState = fromJS({
    cap: {
      demoVideoAndLinkJSON: 'Test data',
      demoVideoAndLinkJSONError: null,
      demoVideoAndLinkJSONStatus: 'SUCCESS',
    },
  });

  //not need now :Temp
  // describe('makeSelectLocationState', () => {
  //   it.concurrent('should select the route as a plain JS object', () => {
  //     const route = fromJS({
  //       locationBeforeTransitions: null,
  //     });
  //     const mockedState = fromJS({
  //       route,
  //     });
  //     expect(makeSelectLocationState()(mockedState)).toEqual(route.toJS());
  //   });

  //   it.concurrent('should return cached js routeState for same concurrent calls', () => {
  //     const route = fromJS({
  //       locationBeforeTransitions: null,
  //     });
  //     const mockedState = fromJS({
  //       route,
  //     });
  //     const selectLocationState = makeSelectLocationState();

  //     const firstRouteStateJS = selectLocationState(mockedState);
  //     expect(selectLocationState(mockedState)).toBe(firstRouteStateJS);
  //   });
  // });

  describe('makeSelectDemoVideoAndLink selector', () => {
    it.concurrent('should return the correct substate', () => {
      const selected = makeSelectDemoVideoAndLink().resultFunc(
        mockState.get('cap'),
      );
      expect(selected).toEqual({
        demoVideoAndLinkJSON: 'Test data',
        demoVideoAndLinkJSONError: null,
        demoVideoAndLinkJSONStatus: 'SUCCESS',
      });
    });
  });

  describe('setInjectedTags selector', () => {
    // Helper function to safely convert result to plain object
    const toPlainObject = (result) => {
      return result && typeof result.toJS === 'function' ? result.toJS() : result;
    };
    it('should merge all tag types when all are present', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {
            tags: {
              custom: { customTag: 'customValue' },
              extended: { extendedTag: 'extendedValue' },
              loyaltyTags: { loyaltyTag: 'loyaltyValue' },
            },
          },
        },
      });
      // Due to destructuring bug in selector: const { tags } = metaEntities; fails with Immutable Maps
      // So tags becomes undefined and only injectedTags is returned
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle empty globalState with default parameter', () => {
      // Arrange
      const state = fromJS({ cap: {} });
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle undefined injectedTags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          metaEntities: {
            tags: {
              custom: { customTag: 'customValue' },
            },
          },
        },
      });
      // Since metaEntities is an Immutable Map, destructuring { tags } = metaEntities returns undefined
      // So tags will be undefined, and customTags will be undefined
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle null injectedTags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: null,
          metaEntities: {
            tags: {
              custom: { customTag: 'customValue' },
            },
          },
        },
      });
      // Same issue - destructuring doesn't work with Immutable Maps
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle undefined metaEntities', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
        },
      });
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle null metaEntities', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: null,
        },
      });
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle undefined tags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {},
        },
      });
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle null tags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {
            tags: null,
          },
        },
      });
      // Destructuring { tags } = metaEntities will return undefined because metaEntities is Immutable Map
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle undefined custom tags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {
            tags: {
              extended: { extendedTag: 'extendedValue' },
              loyaltyTags: { loyaltyTag: 'loyaltyValue' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle undefined extended tags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {
            tags: {
              custom: { customTag: 'customValue' },
              loyaltyTags: { loyaltyTag: 'loyaltyValue' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle undefined loyalty tags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {
            tags: {
              custom: { customTag: 'customValue' },
              extended: { extendedTag: 'extendedValue' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle empty tag objects', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { existing: 'tag1' },
          metaEntities: {
            tags: {
              custom: {},
              extended: {},
              loyaltyTags: {},
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {
        existing: 'tag1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle merge with overlapping keys (later values override)', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { shared: 'injected', unique1: 'value1' },
          metaEntities: {
            tags: {
              custom: { shared: 'custom', unique2: 'value2' },
              extended: { shared: 'extended', unique3: 'value3' },
              loyaltyTags: { shared: 'loyalty', unique4: 'value4' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined, so only injectedTags will be returned
      const expected = {
        shared: 'injected',
        unique1: 'value1',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle only injectedTags with no metaEntities', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: { onlyInjected: 'value' },
        },
      });
      const expected = {
        onlyInjected: 'value',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle only custom tags with no injectedTags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          metaEntities: {
            tags: {
              custom: { onlyCustom: 'value' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle only extended tags with no injectedTags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          metaEntities: {
            tags: {
              extended: { onlyExtended: 'value' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle only loyalty tags with no injectedTags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          metaEntities: {
            tags: {
              loyaltyTags: { onlyLoyalty: 'value' },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle completely empty state', () => {
      // Arrange
      const state = fromJS({ cap: {} });
      const expected = {};
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });

    it('should handle nested object values in tags', () => {
      // Arrange
      const state = fromJS({
        cap: {
          injectedTags: {
            nested: { level1: { level2: 'deep' } },
            simple: 'value',
          },
          metaEntities: {
            tags: {
              custom: {
                customNested: { customLevel1: 'customDeep' },
                customSimple: 'customValue',
              },
            },
          },
        },
      });
      // Destructuring issue - tags will be undefined
      const expected = {
        nested: { level1: { level2: 'deep' } },
        simple: 'value',
      };
      const selector = setInjectedTags();

      // Act
      const result = selector(state);

      // Assert
      expect(toPlainObject(result)).toEqual(expected);
    });
  });
});

