import { fireEvent, render, screen, waitFor } from '@testing-library/react'

const mockListBackups = jest.fn()
const mockUpdateBackupSetting = jest.fn()
const mockUseListBackupPolicies = jest.fn()

jest.mock('mobx-react', () => ({
  observer: (component: unknown) => component
}))

// Jest maps UIKit subpaths to the package root; include subpath exports in this shared mock.
jest.doMock(require.resolve('@tidbcloud/uikit'), () => ({
  ActionIcon: ({ children }: React.PropsWithChildren) => <button>{children}</button>,
  Alert: ({ children }: React.PropsWithChildren) => <div role="alert">{children}</div>,
  Anchor: ({ children, ...props }: React.ComponentPropsWithoutRef<'a'>) => <a {...props}>{children}</a>,
  Box: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
  Button: ({
    children,
    type,
    disabled,
    onClick,
    ...props
  }: React.PropsWithChildren<{
    type?: 'button' | 'submit' | 'reset'
    disabled?: boolean
    onClick?: React.MouseEventHandler<HTMLButtonElement>
    'data-testid'?: string
  }>) => (
    <button type={type} disabled={disabled} onClick={onClick} data-testid={props['data-testid']}>
      {children}
    </button>
  ),
  Code: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
  Divider: () => <hr />,
  Group: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
  HoverCard: Object.assign(({ children }: React.PropsWithChildren) => <div>{children}</div>, {
    Target: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
    Dropdown: ({ children }: React.PropsWithChildren) => <div>{children}</div>
  }),
  LoadingOverlay: () => null,
  Modal: ({ children, opened }: React.PropsWithChildren<{ opened?: boolean }>) =>
    opened ? <div>{children}</div> : null,
  notifier: { error: jest.fn(), success: jest.fn() },
  Form: ({
    children,
    form,
    onSubmit
  }: React.PropsWithChildren<{
    form: {
      handleSubmit: (handler: (values: Record<string, string>) => unknown) => React.FormEventHandler<HTMLFormElement>
      setValue: (name: string, value: string, options?: { shouldDirty?: boolean }) => void
    }
    onSubmit: (values: Record<string, string>) => unknown
  }>) => (
    <form onSubmit={form.handleSubmit(onSubmit)}>
      <button
        type="button"
        data-testid="change-retention"
        onClick={() => form.setValue('retentionDays', '3', { shouldDirty: true })}
      >
        Change retention
      </button>
      {children}
    </form>
  ),
  FormSelect: () => null,
  ProTable: () => <div />,
  Radio: {
    Card: ({ children, ...props }: React.PropsWithChildren<{ 'data-testid'?: string }>) => (
      <div data-testid={props['data-testid']}>{children}</div>
    ),
    Indicator: () => null
  },
  ScrollArea: {
    Autosize: ({ children }: React.PropsWithChildren) => <div>{children}</div>
  },
  SimpleGrid: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
  Skeleton: () => <div />,
  Stack: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
  TextInput: () => <input />,
  Tooltip: ({ children }: React.PropsWithChildren) => <div>{children}</div>,
  Typography: ({ children }: React.PropsWithChildren) => <div>{children}</div>
}))

jest.mock('@tidbcloud/uikit/icons', () => ({
  IconAlertTriangle: () => null,
  IconClock: () => null,
  IconEdit05: () => null,
  IconInfoCircle: () => null
}))

jest.mock('dbaas/features/Common', () => ({
  useOrgProjectClusterIds: () => ({ orgId: 'org-1', projectId: 'project-1' })
}))

jest.mock('dbaas/services/errorCodes', () => ({
  getErrorMessage: jest.fn()
}))

jest.mock('dbaas/utils/tracking', () => ({
  MixpanelEvents: {
    PremiumBackup: {
      Update: { ButtonClicked: 'update' },
      View: { ButtonClicked: 'view' }
    }
  }
}))

jest.mock('dbaas/services/api-clients/v2025/tidb-management/v1beta2', () => ({
  getTidbServiceGetBackupSettingQueryKey: jest.fn(),
  tidbServiceListTidbBackups: mockListBackups,
  useTidbServiceGetBackupSetting: () => ({
    data: {
      mode: 'STANDARD_BUNDLE',
      backupPolicy: 'TIER1'
    },
    isFetching: false
  }),
  useTidbServiceListBackupPolicies: mockUseListBackupPolicies,
  useTidbServiceUpdateBackupSetting: () => ({ isLoading: false, mutateAsync: mockUpdateBackupSetting })
}))

jest.mock('dbaas/stores/useStores', () => ({
  __esModule: true,
  default: () => ({
    store: {
      tenantData: { name: 'Test Org', timezone: 'UTC' },
      activeProject: { name: 'Test Project' }
    }
  })
}))

jest.mock('react-query', () => ({
  useQueryClient: () => ({ invalidateQueries: jest.fn() })
}))

const { BackupSettingPremium } = jest.requireActual<typeof import('./Settings')>('./Settings')
const { BackupSettingSummary } = jest.requireActual<typeof import('./SettingsSummary')>('./SettingsSummary')

beforeEach(() => {
  jest.clearAllMocks()
  mockListBackups.mockResolvedValue({ backups: [] })
  mockUpdateBackupSetting.mockResolvedValue({})
  mockUseListBackupPolicies.mockReturnValue({ data: undefined, isLoading: false })
})

test('hides backup pricing guidance for BYOC instances', () => {
  render(
    <BackupSettingPremium tidbId="tidb-1" instanceName="Test TiDB" servicePlan="BYOC" closeModal={jest.fn()} isBYOC />
  )

  expect(screen.queryByText(/Backup price for/)).toBeNull()
})

test('shows backup pricing guidance for TiDB Cloud managed instances', () => {
  render(
    <BackupSettingPremium
      tidbId="tidb-1"
      instanceName="Test TiDB"
      servicePlan="Premium"
      closeModal={jest.fn()}
      isBYOC={false}
    />
  )

  expect(screen.getByText(/Backup price for Standard Bundle Mode/)).toBeTruthy()
  expect(screen.getByRole('link', { name: 'View Pricing' }).getAttribute('href')).toBe(
    'https://www.pingcap.com/tidb-cloud-premium-pricing-details/'
  )
})

test('uses Custom Retention Mode without Standard policy requests for Essential V2', async () => {
  render(
    <BackupSettingPremium
      tidbId="tidb-1"
      instanceName="Test TiDB"
      servicePlan="Essential_V2"
      closeModal={jest.fn()}
      isBYOC={false}
    />
  )

  expect(screen.queryByTestId('premium-backup-settings-standard-mode')).toBeNull()
  expect(screen.queryByTestId('premium-backup-settings-flexible-mode')).toBeNull()
  expect(screen.getByText(/Backup price for Custom Retention Mode/)).toBeTruthy()
  expect(screen.getByRole('link', { name: 'View Pricing' }).getAttribute('href')).toBe(
    'https://www.pingcap.com/tidb-cloud-essential-pricing-details/'
  )
  expect(mockUseListBackupPolicies).toHaveBeenCalledWith(
    'tidb-1',
    { orgId: 'org-1', projectId: 'project-1' },
    expect.objectContaining({ query: expect.objectContaining({ enabled: false }) })
  )

  fireEvent.click(screen.getByTestId('change-retention'))
  fireEvent.click(screen.getByTestId('premium-backup-settings-save'))

  await waitFor(() => {
    expect(mockUpdateBackupSetting).toHaveBeenCalledWith({
      tidbId: 'tidb-1',
      data: {
        mode: 'FLEXIBLE_RETENTION',
        retentionDays: 3,
        dailyBackupTimeUtc: expect.any(String)
      },
      params: { orgId: 'org-1', projectId: 'project-1' }
    })
  })
})

test('shows only Custom backup rules in the Essential V2 summary', () => {
  render(
    <BackupSettingSummary tidbId="tidb-1" servicePlan="Essential_V2" canChangeSettings onChangeSettings={jest.fn()} />
  )

  expect(screen.getByText('Custom')).toBeTruthy()
  expect(screen.getByText('PITR')).toBeTruthy()
  expect(screen.getByText('Daily Backup')).toBeTruthy()
  expect(screen.queryByText('Hourly Backup')).toBeNull()
  expect(mockUseListBackupPolicies).toHaveBeenCalledWith(
    'tidb-1',
    { orgId: 'org-1', projectId: 'project-1' },
    expect.objectContaining({ query: expect.objectContaining({ enabled: false }) })
  )
})
