/*
 * SonarQube
 * Copyright (C) 2009-2024 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
import { waitFor } from '@testing-library/react';
import React from 'react';
import { Outlet, Route } from 'react-router-dom';
import BranchesServiceMock from '../../api/mocks/BranchesServiceMock';
import ComponentsServiceMock from '../../api/mocks/ComponentsServiceMock';
import IssuesServiceMock from '../../api/mocks/IssuesServiceMock';
import UsersServiceMock from '../../api/mocks/UsersServiceMock';
import { mockComponent } from '../../helpers/mocks/component';
import { mockCurrentUser } from '../../helpers/testMocks';
import { renderApp, renderAppWithComponentContext } from '../../helpers/testReactTestingUtils';
import { byPlaceholderText, byRole, byTestId, byText } from '../../helpers/testSelector';
import {
  CleanCodeAttributeCategory,
  SoftwareImpactSeverity,
  SoftwareQuality,
} from '../../types/clean-code-taxonomy';
import { Feature } from '../../types/features';
import { Component } from '../../types/types';
import { NoticeType } from '../../types/users';
import IssuesApp from './components/IssuesApp';
import { projectIssuesRoutes } from './routes';

export const usersHandler = new UsersServiceMock();
export const issuesHandler = new IssuesServiceMock(usersHandler);
export const componentsHandler = new ComponentsServiceMock();
export const branchHandler = new BranchesServiceMock();

export const ui = {
  loading: byText('loading'),
  issuePageHeadering: byRole('heading', { level: 1, name: 'issues.page' }),
  issueItemAction1: byRole('link', { name: 'Issue with no location message' }),
  issueItemAction2: byRole('link', { name: 'FlowIssue' }),
  issueItemAction3: byRole('link', { name: 'Issue on file' }),
  issueItemAction4: byRole('link', { name: 'Fix this' }),
  issueItemAction5: byRole('link', { name: 'Fix that' }),
  issueItemAction6: byRole('link', { name: 'Second issue' }),
  issueItemAction7: byRole('link', { name: 'Issue with tags' }),
  issueItemAction8: byRole('link', { name: 'Issue on page 2' }),

  issueItems: byRole('region'),

  fixedIssuesHeading: byRole('heading', { level: 2, name: 'issues.fixed_issues' }),

  issueItem1: byRole('region', { name: 'Issue with no location message' }),
  issueItem2: byRole('region', { name: 'FlowIssue' }),
  issueItem3: byRole('region', { name: 'Issue on file' }),
  issueItem4: byRole('region', { name: 'Fix this' }),
  issueItem5: byRole('region', { name: 'Fix that' }),
  issueItem6: byRole('region', { name: 'Second issue' }),
  issueItem7: byRole('region', { name: 'Issue with tags' }),
  issueItem8: byRole('region', { name: 'Issue on page 2' }),
  issueItem9: byRole('region', { name: 'Issue inside folderA' }),
  projectIssueItem6: byRole('button', { name: 'Second issue' }),

  conciseIssueTotal: byTestId('page-counter-total'),
  conciseIssueItem2: byTestId('issues-nav-bar').byRole('button', { name: 'Fix that' }),
  conciseIssueItem4: byTestId('issues-nav-bar').byRole('button', { name: 'Issue with tags' }),

  assigneeFacet: byRole('button', { name: 'issues.facet.assignees' }),
  authorFacet: byRole('button', { name: 'issues.facet.authors' }),
  codeVariantsFacet: byRole('button', { name: 'issues.facet.codeVariants' }),
  creationDateFacet: byRole('button', { name: 'issues.facet.createdAt' }),
  languageFacet: byRole('button', { name: 'issues.facet.languages' }),
  projectFacet: byRole('button', { name: 'issues.facet.projects' }),
  resolutionFacet: byRole('button', { name: 'issues.facet.resolutions' }),
  ruleFacet: byRole('button', { name: 'issues.facet.rules' }),
  scopeFacet: byRole('button', { name: 'issues.facet.scopes' }),
  issueStatusFacet: byRole('button', { name: 'issues.facet.issueStatuses' }),
  tagFacet: byRole('button', { name: 'issues.facet.tags' }),
  typeFacet: byRole('button', { name: 'issues.facet.types' }),
  cleanCodeAttributeCategoryFacet: byRole('button', {
    name: 'issues.facet.cleanCodeAttributeCategories',
  }),
  softwareQualityFacet: byRole('button', {
    name: 'issues.facet.impactSoftwareQualities',
  }),
  severityFacet: byRole('button', { name: 'issues.facet.impactSeverities' }),

  clearCodeCategoryFacet: byTestId('clear-issues.facet.cleanCodeAttributeCategories'),
  clearSoftwareQualityFacet: byTestId('clear-issues.facet.impactSoftwareQualities'),
  clearAssigneeFacet: byTestId('clear-issues.facet.assignees'),
  clearAuthorFacet: byTestId('clear-issues.facet.authors'),
  clearCodeVariantsFacet: byTestId('clear-issues.facet.codeVariants'),
  clearCreationDateFacet: byTestId('clear-issues.facet.createdAt'),
  clearIssueTypeFacet: byTestId('clear-issues.facet.types'),
  clearProjectFacet: byTestId('clear-issues.facet.projects'),
  clearResolutionFacet: byTestId('clear-issues.facet.resolutions'),
  clearRuleFacet: byTestId('clear-issues.facet.rules'),
  clearScopeFacet: byTestId('clear-issues.facet.scopes'),
  clearSeverityFacet: byTestId('clear-issues.facet.impactSeverities'),
  clearIssueStatusFacet: byTestId('clear-issues.facet.issueStatuses'),
  clearTagFacet: byTestId('clear-issues.facet.tags'),

  responsibleCategoryFilter: byRole('checkbox', {
    name: `issue.clean_code_attribute_category.${CleanCodeAttributeCategory.Responsible}`,
  }),
  consistentCategoryFilter: byRole('checkbox', {
    name: `issue.clean_code_attribute_category.${CleanCodeAttributeCategory.Consistent}`,
  }),
  softwareQualityMaintainabilityFilter: byRole('checkbox', {
    name: `software_quality.${SoftwareQuality.Maintainability}`,
  }),
  codeSmellIssueTypeFilter: byRole('checkbox', { name: 'issue.type.CODE_SMELL' }),
  confirmedStatusFilter: byRole('checkbox', { name: 'issue.issue_status.CONFIRMED' }),
  fixedResolutionFilter: byRole('checkbox', { name: 'issue.resolution.FIXED' }),
  mainScopeFilter: byRole('checkbox', { name: 'issue.scope.MAIN' }),
  mediumSeverityFilter: byRole('checkbox', { name: `severity.${SoftwareImpactSeverity.Medium}` }),
  openStatusFilter: byRole('checkbox', { name: 'issue.issue_status.OPEN' }),
  vulnerabilityIssueTypeFilter: byRole('checkbox', { name: 'issue.type.VULNERABILITY' }),

  bulkChangeComment: byRole('textbox', { name: /issue_bulk_change.resolution_comment/ }),

  clearAllFilters: byRole('button', { name: 'clear_all_filters' }),

  dateInputMonthSelect: byTestId('month-select'),
  dateInputYearSelect: byTestId('year-select'),

  authorFacetSearch: byPlaceholderText('search.search_for_authors'),
  inNewCodeFilter: byRole('checkbox', { name: 'issues.new_code' }),
  languageFacetList: byRole('group', { name: 'issues.facet.languages' }),
  ruleFacetList: byRole('group', { name: 'issues.facet.rules' }),
  ruleFacetSearch: byPlaceholderText('search.search_for_rules'),
  tagFacetSearch: byPlaceholderText('search.search_for_tags'),

  issueActivityTab: byRole('tab', { name: 'coding_rules.description_section.title.activity' }),
  issueActivityAddComment: byRole('button', {
    name: `issue.activity.add_comment`,
  }),
  issueAcitivityEditComment: byRole('button', { name: 'issue.comment.edit' }),
  issueActivityDeleteComment: byRole('button', { name: 'issue.comment.delete' }),

  guidePopup: byRole('alertdialog'),
};

export async function waitOnDataLoaded() {
  await waitFor(() => {
    expect(ui.loading.query()).not.toBeInTheDocument();
  });
}

export function renderIssueApp(
  currentUser = mockCurrentUser({
    dismissedNotices: {
      [NoticeType.ISSUE_GUIDE]: true,
      [NoticeType.ISSUE_NEW_STATUS_AND_TRANSITION_GUIDE]: true,
    },
  }),
) {
  renderApp('issues', <IssuesApp />, { currentUser });
}

export function renderProjectIssuesApp(
  navigateTo?: string,
  overrides?: Partial<Component>,
  currentUser = mockCurrentUser({
    dismissedNotices: {
      [NoticeType.ISSUE_GUIDE]: true,
      [NoticeType.ISSUE_NEW_STATUS_AND_TRANSITION_GUIDE]: true,
    },
  }),
) {
  renderAppWithComponentContext(
    'project/issues',
    () => (
      <Route
        element={
          <div data-guiding-id="issue-5">
            <Outlet />
          </div>
        }
      >
        {projectIssuesRoutes()}
      </Route>
    ),
    { navigateTo, currentUser, featureList: [Feature.BranchSupport] },
    { component: mockComponent(overrides) },
  );
}