import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import type { components } from './generated/schema'
import { apiClient } from './client'
import { throwApiProblem } from './contracts'
import { queryKeys } from './queryClient'
import { reportOperationResult } from '../services/operationResults'

export type NotificationDto = components['schemas']['NotificationDto']
export type NotificationSnapshotDto = components['schemas']['NotificationSnapshotDto']

export interface NotificationQueryOptions {
  forUser?: string
  limit?: number
  unreadOnly?: boolean
}

function normalizeOptions(options: NotificationQueryOptions = {}) {
  return {
    forUser: options.forUser?.trim().toLowerCase() || 'bao',
    limit: Math.min(Math.max(options.limit ?? 50, 1), 200),
    unreadOnly: options.unreadOnly ?? false,
  }
}

export async function fetchNotificationSnapshot(
  options: NotificationQueryOptions = {},
  signal?: AbortSignal,
): Promise<NotificationSnapshotDto> {
  const normalized = normalizeOptions(options)
  const { data, error, response } = await apiClient.GET(
    '/api/dashboard/notifications/snapshot',
    {
      params: { query: normalized },
      signal,
    },
  )
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Benachrichtigungen konnten nicht geladen werden')
  }
  return data as NotificationSnapshotDto
}

async function markNotificationRead(id: string): Promise<NotificationDto> {
  const { data, error, response } = await apiClient.PATCH(
    '/api/dashboard/notifications/{id}/read',
    { params: { path: { id } } },
  )
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Benachrichtigung konnte nicht als gelesen markiert werden')
  }
  const notification = data as NotificationDto
  reportOperationResult(notification.operation, 'Benachrichtigung gelesen')
  return notification
}

async function markAllNotificationsRead(forUser: string): Promise<components['schemas']['NotificationReadAllResultDto']> {
  const { data, error, response } = await apiClient.PATCH(
    '/api/dashboard/notifications/read-all',
    { params: { query: { forUser } } },
  )
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Benachrichtigungen konnten nicht aktualisiert werden')
  }
  const result = data as components['schemas']['NotificationReadAllResultDto']
  reportOperationResult(result.operation, 'Benachrichtigungen gelesen')
  return result
}

export function useNotificationSnapshot(options: NotificationQueryOptions = {}) {
  const normalized = normalizeOptions(options)
  const client = useQueryClient()
  const query = useQuery({
    queryKey: queryKeys.notifications(
      normalized.forUser,
      normalized.limit,
      normalized.unreadOnly,
    ),
    queryFn: ({ signal }) => fetchNotificationSnapshot(normalized, signal),
  })

  const refreshNotificationQueries = () =>
    client.invalidateQueries({ queryKey: ['notifications'] })

  const markReadMutation = useMutation({
    mutationFn: markNotificationRead,
    onSuccess: refreshNotificationQueries,
  })
  const markAllReadMutation = useMutation({
    mutationFn: () => markAllNotificationsRead(normalized.forUser),
    onSuccess: refreshNotificationQueries,
  })

  return {
    query,
    markAsRead: (id: string) => markReadMutation.mutateAsync(id),
    markAllAsRead: () => markAllReadMutation.mutateAsync(),
    markingRead: markReadMutation.isPending,
    markingAllRead: markAllReadMutation.isPending,
  }
}
