import { computed, toValue, type MaybeRefOrGetter } from 'vue'
import { useQuery } from '@tanstack/vue-query'
import type { components } from './generated/schema'
import { apiClient } from './client'
import { queryKeys } from './queryClient'
import { throwApiProblem } from './contracts'

export type DashboardTaskDto = components['schemas']['DashboardTaskDto']
export type TaskActivityDto = components['schemas']['ActivityEvent']
export type TaskRunDto = components['schemas']['OpenClawRunDto']

async function fetchTask(id: string, signal: AbortSignal): Promise<DashboardTaskDto> {
  const { data, error, response } = await apiClient.GET('/api/dashboard/tasks/{id}', {
    params: { path: { id } },
    signal,
  })
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Aufgabe konnte nicht geladen werden')
  }
  return data as DashboardTaskDto
}

async function fetchTaskChildren(id: string, signal: AbortSignal): Promise<DashboardTaskDto[]> {
  const { data, error, response } = await apiClient.GET('/api/dashboard/tasks/{id}/children', {
    params: { path: { id } },
    signal,
  })
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Child-Tasks konnten nicht geladen werden')
  }
  return data as DashboardTaskDto[]
}

async function fetchTaskActivity(id: string, signal: AbortSignal): Promise<TaskActivityDto[]> {
  const { data, error, response } = await apiClient.GET('/api/dashboard/tasks/{id}/activity', {
    params: { path: { id } },
    signal,
  })
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Task-Aktivität konnte nicht geladen werden')
  }
  return data as TaskActivityDto[]
}

async function fetchTaskRuns(id: string, signal: AbortSignal): Promise<TaskRunDto[]> {
  const { data, error, response } = await apiClient.GET('/api/v1/openclaw/runs', {
    params: {
      query: {
        limit: 20,
        taskId: id,
      },
    },
    signal,
  })
  if (!response.ok || error || !data) {
    await throwApiProblem(response, 'Zugehörige Runs konnten nicht geladen werden')
  }
  return (data as components['schemas']['OpenClawRunCollectionDto']).items
}

function resolvedQueryInput(
  id: MaybeRefOrGetter<string>,
  enabled: MaybeRefOrGetter<boolean>,
) {
  const resolvedId = computed(() => toValue(id))
  const queryEnabled = computed(() => Boolean(resolvedId.value) && toValue(enabled))
  return { resolvedId, queryEnabled }
}

export function useTaskQuery(
  id: MaybeRefOrGetter<string>,
  enabled: MaybeRefOrGetter<boolean> = true,
) {
  const { resolvedId, queryEnabled } = resolvedQueryInput(id, enabled)
  return useQuery({
    queryKey: computed(() => queryKeys.task(resolvedId.value)),
    queryFn: ({ signal }) => fetchTask(resolvedId.value, signal),
    enabled: queryEnabled,
  })
}

export function useTaskChildren(
  id: MaybeRefOrGetter<string>,
  enabled: MaybeRefOrGetter<boolean> = true,
) {
  const { resolvedId, queryEnabled } = resolvedQueryInput(id, enabled)
  return useQuery({
    queryKey: computed(() => queryKeys.taskChildren(resolvedId.value)),
    queryFn: ({ signal }) => fetchTaskChildren(resolvedId.value, signal),
    enabled: queryEnabled,
  })
}

export function useTaskActivity(
  id: MaybeRefOrGetter<string>,
  enabled: MaybeRefOrGetter<boolean> = true,
) {
  const { resolvedId, queryEnabled } = resolvedQueryInput(id, enabled)
  return useQuery({
    queryKey: computed(() => queryKeys.taskActivity(resolvedId.value)),
    queryFn: ({ signal }) => fetchTaskActivity(resolvedId.value, signal),
    enabled: queryEnabled,
  })
}

export function useTaskRuns(
  id: MaybeRefOrGetter<string>,
  enabled: MaybeRefOrGetter<boolean> = true,
) {
  const { resolvedId, queryEnabled } = resolvedQueryInput(id, enabled)
  return useQuery({
    queryKey: computed(() => queryKeys.taskRuns(resolvedId.value)),
    queryFn: ({ signal }) => fetchTaskRuns(resolvedId.value, signal),
    enabled: queryEnabled,
  })
}

export function useTaskDetail(id: MaybeRefOrGetter<string>) {
  const taskQuery = useTaskQuery(id)
  const childrenQuery = useTaskChildren(id)
  const activityQuery = useTaskActivity(id)
  const runsQuery = useTaskRuns(id)

  return {
    taskQuery,
    childrenQuery,
    activityQuery,
    runsQuery,
    task: computed(() => taskQuery.data.value ?? null),
    children: computed(() => childrenQuery.data.value ?? []),
    activity: computed(() => activityQuery.data.value ?? []),
    relatedRuns: computed(() => runsQuery.data.value ?? []),
    detailsLoading: computed(() =>
      childrenQuery.isPending.value
      || activityQuery.isPending.value
      || runsQuery.isPending.value,
    ),
  }
}
