// Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/

import { getNode } from '@formkit/core'
import { within } from '@testing-library/vue'
import { expect } from 'vitest'

import { visitView } from '#tests/support/components/visitView.ts'
import { mockApplicationConfig } from '#tests/support/mock-applicationConfig.ts'
import { mockPermissions } from '#tests/support/mock-permissions.ts'

import { mockFormUpdaterQuery } from '#shared/components/Form/graphql/queries/formUpdater.mocks.ts'
import {
  mockTicketUpdateMutation,
  waitForTicketUpdateMutationCalls,
} from '#shared/entities/ticket/graphql/mutations/update.mocks.ts'
import { mockTicketQuery } from '#shared/entities/ticket/graphql/queries/ticket.mocks.ts'
import { createDummyTicket } from '#shared/entities/ticket-article/__tests__/mocks/ticket.ts'
import { EnumUserErrorException } from '#shared/graphql/types.ts'
import { convertToGraphQLId } from '#shared/graphql/utils.ts'

describe('Ticket detail view', () => {
  beforeEach(() => {
    mockPermissions(['ticket.agent'])
  })

  describe('Time accounting', () => {
    it('opens time accounting flyout when the condition is met', async () => {
      mockApplicationConfig({
        ui_ticket_zoom_article_note_new_internal: true,
        time_accounting: true,
        time_accounting_unit: '',
        time_accounting_types: false,
      })

      const ticket = createDummyTicket({
        state: {
          id: convertToGraphQLId('Ticket::State', 2),
          name: 'open',
          stateType: {
            id: convertToGraphQLId('TicketStateType', 2),
            name: 'open',
          },
        },
        articleType: 'email',
        defaultPolicy: {
          update: true,
          agentReadAccess: true,
        },
      })

      mockTicketQuery({
        ticket,
      })

      mockFormUpdaterQuery({
        formUpdater: {
          fields: {
            group_id: {
              options: [
                {
                  value: 1,
                  label: 'Users',
                },
                {
                  value: 2,
                  label: 'test group',
                },
              ],
            },
            owner_id: {
              options: [
                {
                  value: 3,
                  label: 'Test Admin Agent',
                },
              ],
            },
            state_id: {
              options: [
                {
                  value: 4,
                  label: 'closed',
                },
                {
                  value: 2,
                  label: 'open',
                },
                {
                  value: 6,
                  label: 'pending close',
                },
                {
                  value: 3,
                  label: 'pending reminder',
                },
              ],
            },
            pending_time: {
              show: false,
            },
            priority_id: {
              options: [
                {
                  value: 1,
                  label: '1 low',
                },
                {
                  value: 2,
                  label: '2 normal',
                },
                {
                  value: 3,
                  label: '3 high',
                },
              ],
            },
          },
          flags: {
            newArticlePresent: false,
          },
        },
      })

      const view = await visitView('/tickets/1')

      await view.events.click(
        await view.findByRole('button', { name: 'Add internal note' }),
      )

      await view.events.type(
        await view.findByRole('textbox', { name: 'Text' }),
        'Foo note',
      )

      mockTicketUpdateMutation({
        ticketUpdate: {
          ticket: null,
          errors: [
            {
              message: 'The ticket time accounting condition is met.',
              exception:
                EnumUserErrorException.ServiceTicketUpdateValidatorTimeAccountingError,
            },
          ],
        },
      })

      mockFormUpdaterQuery({
        formUpdater: {
          fields: {},
        },
      })

      await view.events.click(
        await view.findByRole('button', { name: 'Update' }),
      )

      await waitForTicketUpdateMutationCalls()

      const flyout = await view.findByRole('complementary', {
        name: 'Time Accounting',
      })

      expect(
        within(flyout).getByRole('heading', {
          level: 2,
        }),
      ).toHaveTextContent('Time Accounting')

      await view.events.type(
        await within(flyout).findByLabelText('Accounted Time'),
        '1',
      )

      await getNode('form-ticket-time-accounting')?.settled

      mockTicketUpdateMutation({
        ticketUpdate: {
          ticket,
          errors: null,
        },
      })

      await view.events.click(
        within(flyout).getByRole('button', {
          name: 'Account Time',
        }),
      )

      const calls = await waitForTicketUpdateMutationCalls()

      expect(calls.at(-1)?.variables).toEqual(
        expect.objectContaining({
          input: expect.objectContaining({
            article: expect.objectContaining({
              timeUnit: 1,
            }),
          }),
        }),
      )

      expect(
        view.queryByRole('complementary', {
          name: 'Time Accounting',
        }),
      ).not.toBeInTheDocument()
    })
  })
})