import type { FeatureToggles } from '@grafana/data';
import { reportInteraction, config } from '@grafana/runtime';
import { contextSrv } from 'app/core/services/context_srv';
import { getExternalUserMngLinkUrl } from 'app/features/users/utils';
import { AccessControlAction } from 'app/types/accessControl';

import {
  performInviteUserClick,
  performUpgradeUserClick,
  shouldRenderInviteUserButton,
  shouldRenderUpgradeUserButton,
} from './InviteUserButtonUtils';

// Mock dependencies
jest.mock('@grafana/runtime', () => ({
  ...jest.requireActual('@grafana/runtime'),
  reportInteraction: jest.fn(),
  config: {
    featureToggles: {} as Partial<FeatureToggles>,
    externalUserMngLinkUrl: '',
    externalUserUpgradeLinkUrl: '',
    namespace: 'org-1',
  },
}));

jest.mock('app/features/provisioning/utils/isOnPrem', () => ({
  isOnPrem: jest.fn(() => true),
}));

jest.mock('app/core/services/context_srv', () => ({
  contextSrv: {
    hasPermission: jest.fn(),
  },
}));

jest.mock('app/features/users/utils', () => ({
  getExternalUserMngLinkUrl: jest.fn(),
}));

const mockReportInteraction = jest.mocked(reportInteraction);
const mockConfig = jest.mocked(config);
const mockContextSrv = jest.mocked(contextSrv);
const mockGetExternalUserMngLinkUrl = jest.mocked(getExternalUserMngLinkUrl);

// Mock window.open
const mockWindowOpen = jest.fn();
Object.defineProperty(window, 'open', {
  value: mockWindowOpen,
  writable: true,
});

describe('InviteUserButtonUtils', () => {
  beforeEach(() => {
    jest.clearAllMocks();

    // Set up default mocks
    mockConfig.externalUserMngLinkUrl = 'https://example.com/invite';
    mockContextSrv.hasPermission.mockReturnValue(true);

    // Dynamic mock that returns URL with the actual cnt parameter
    mockGetExternalUserMngLinkUrl.mockImplementation((cnt: string) => `https://example.com/invite?cnt=${cnt}`);
  });

  describe('shouldRenderInviteUserButton', () => {
    it('should return true when all conditions are met', () => {
      expect(shouldRenderInviteUserButton()).toBe(true);
      expect(mockContextSrv.hasPermission).toHaveBeenCalledWith(AccessControlAction.OrgUsersAdd);
    });

    it('should return false when neither URL is configured', () => {
      mockConfig.externalUserMngLinkUrl = '';
      mockConfig.externalUserUpgradeLinkUrl = '';

      expect(shouldRenderInviteUserButton()).toBeFalsy();
    });

    it('should return true when upgrade URL is configured even without invite URL', () => {
      mockConfig.externalUserMngLinkUrl = '';
      mockConfig.externalUserUpgradeLinkUrl = 'https://example.com/upgrade';

      expect(shouldRenderInviteUserButton()).toBe(true);
    });

    it('should return false when user lacks permission', () => {
      mockContextSrv.hasPermission.mockReturnValue(false);

      expect(shouldRenderInviteUserButton()).toBe(false);
    });
  });

  describe('performInviteUserClick', () => {
    it('should report interaction, get URL, and open window with correct cnt parameter', () => {
      const placement = 'top_bar_right';
      const cnt = 'invite-user-test';

      performInviteUserClick(placement, cnt);

      expect(mockReportInteraction).toHaveBeenCalledWith('invite_user_button_clicked', {
        placement,
      });
      expect(mockGetExternalUserMngLinkUrl).toHaveBeenCalledWith(cnt);
      expect(mockWindowOpen).toHaveBeenCalledWith(`https://example.com/invite?cnt=${cnt}`, '_blank');
    });

    it('should work with different cnt values', () => {
      const placement = 'top_bar_right';
      const cnt = 'dashboard-header';

      performInviteUserClick(placement, cnt);

      expect(mockReportInteraction).toHaveBeenCalledWith('invite_user_button_clicked', {
        placement,
      });
      expect(mockGetExternalUserMngLinkUrl).toHaveBeenCalledWith(cnt);
      expect(mockWindowOpen).toHaveBeenCalledWith(`https://example.com/invite?cnt=${cnt}`, '_blank');
    });

    it('should handle special characters in cnt parameter', () => {
      const placement = 'menu-item';
      const cnt = 'admin-panel_users-section';

      performInviteUserClick(placement, cnt);

      expect(mockReportInteraction).toHaveBeenCalledWith('invite_user_button_clicked', {
        placement,
      });
      expect(mockGetExternalUserMngLinkUrl).toHaveBeenCalledWith(cnt);
      expect(mockWindowOpen).toHaveBeenCalledWith(`https://example.com/invite?cnt=${cnt}`, '_blank');
    });
  });

  describe('shouldRenderUpgradeUserButton', () => {
    it('should return false on on-prem instances', () => {
      const { isOnPrem } = require('app/features/provisioning/utils/isOnPrem');
      isOnPrem.mockReturnValue(true);
      mockConfig.externalUserUpgradeLinkUrl = 'https://example.com/upgrade';
      mockContextSrv.hasPermission.mockReturnValue(true);

      expect(shouldRenderUpgradeUserButton()).toBeFalsy();
    });

    it('should return false without upgrade URL even on cloud', () => {
      const { isOnPrem } = require('app/features/provisioning/utils/isOnPrem');
      isOnPrem.mockReturnValue(false);
      mockConfig.externalUserUpgradeLinkUrl = '';
      mockContextSrv.hasPermission.mockReturnValue(true);

      expect(shouldRenderUpgradeUserButton()).toBeFalsy();
    });

    it('should return false without permission even with URL on cloud', () => {
      const { isOnPrem } = require('app/features/provisioning/utils/isOnPrem');
      isOnPrem.mockReturnValue(false);
      mockConfig.externalUserUpgradeLinkUrl = 'https://example.com/upgrade';
      mockContextSrv.hasPermission.mockReturnValue(false);

      expect(shouldRenderUpgradeUserButton()).toBeFalsy();
    });

    it('should return true when all conditions met (cloud + URL + permission)', () => {
      const { isOnPrem } = require('app/features/provisioning/utils/isOnPrem');
      isOnPrem.mockReturnValue(false);
      mockConfig.externalUserUpgradeLinkUrl = 'https://example.com/upgrade';
      mockContextSrv.hasPermission.mockReturnValue(true);

      expect(shouldRenderUpgradeUserButton()).toBe(true);
      expect(mockContextSrv.hasPermission).toHaveBeenCalledWith(AccessControlAction.OrgUsersAdd);
    });
  });

  describe('performUpgradeUserClick', () => {
    beforeEach(() => {
      mockConfig.externalUserUpgradeLinkUrl = 'https://example.com/upgrade';
    });

    it('should report interaction and open upgrade URL', () => {
      const placement = 'top_bar_right';

      performUpgradeUserClick(placement);

      expect(mockReportInteraction).toHaveBeenCalledWith('upgrade_user_button_clicked', {
        placement,
      });
      expect(mockWindowOpen).toHaveBeenCalledWith('https://example.com/upgrade', '_blank');
    });

    it('should work with different placements', () => {
      const placement = 'settings_page';

      performUpgradeUserClick(placement);

      expect(mockReportInteraction).toHaveBeenCalledWith('upgrade_user_button_clicked', {
        placement,
      });
      expect(mockWindowOpen).toHaveBeenCalledWith('https://example.com/upgrade', '_blank');
    });
  });
});
