import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { z } from 'zod'
import { api } from '../client'
import type { PullRequest } from '../../types/api'

const prReviewerSchema = z.object({
  userId: z.number(),
  username: z.string(),
  avatarUrl: z.string(),
})

const prSchema = z.object({
  id: z.number(),
  repoId: z.number(),
  authorId: z.number(),
  title: z.string(),
  body: z.string(),
  sourceBranch: z.string(),
  targetBranch: z.string(),
  status: z.enum(['open', 'merged', 'closed']),
  createdAt: z.string(),
  updatedAt: z.string(),
  reviewers: z.array(prReviewerSchema).default([]),
})

const prsSchema = z.array(prSchema)

const mergeResponseSchema = z.object({ status: z.string() })

export function usePRs(owner: string, repo: string) {
  return useQuery({
    queryKey: ['repos', owner, repo, 'pulls'],
    queryFn: () =>
      api.get<PullRequest[]>(`/api/v1/repos/${owner}/${repo}/pulls`, prsSchema),
    enabled: Boolean(owner && repo),
  })
}

export function usePR(owner: string, repo: string, prId: number) {
  return useQuery({
    queryKey: ['repos', owner, repo, 'pulls', prId],
    queryFn: () =>
      api.get<PullRequest>(`/api/v1/repos/${owner}/${repo}/pulls/${prId}`, prSchema),
    enabled: Boolean(owner && repo && prId),
  })
}

export function useUpdatePR(owner: string, repo: string, prId: number) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (data: { title?: string; body?: string }) =>
      api.patch<PullRequest>(`/api/v1/repos/${owner}/${repo}/pulls/${prId}`, prSchema, data),
    onSuccess: (updated) => {
      queryClient.setQueryData(['repos', owner, repo, 'pulls', prId], updated)
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'pulls'] })
    },
  })
}

export function useReopenPR(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (prId: number) =>
      api.post<PullRequest>(`/api/v1/repos/${owner}/${repo}/pulls/${prId}/reopen`, prSchema, {}),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'pulls'] })
      queryClient.invalidateQueries({ queryKey: ['dashboard'] })
    },
  })
}

export function useCreatePR(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (data: { title: string; body: string; sourceBranch: string; targetBranch: string }) =>
      api.post<PullRequest>(`/api/v1/repos/${owner}/${repo}/pulls`, prSchema, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'pulls'] })
      queryClient.invalidateQueries({ queryKey: ['dashboard'] })
    },
  })
}

export function useMergePR(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: ({ prId, strategy }: { prId: number; strategy: string }) =>
      api.post(`/api/v1/repos/${owner}/${repo}/pulls/${prId}/merge`, mergeResponseSchema, { strategy }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'pulls'] })
      queryClient.invalidateQueries({ queryKey: ['dashboard'] })
    },
  })
}

export function useClosePR(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (prId: number) =>
      api.post<PullRequest>(`/api/v1/repos/${owner}/${repo}/pulls/${prId}/close`, prSchema, {}),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'pulls'] })
      queryClient.invalidateQueries({ queryKey: ['dashboard'] })
    },
  })
}

// ─── PR settings ──────────────────────────────────────────────────────────────

export interface DefaultReviewer {
  userId: number
  username: string
  avatarUrl: string
}

const reviewerSchema = z.object({
  userId: z.number(),
  username: z.string(),
  avatarUrl: z.string(),
})
const reviewersSchema = z.array(reviewerSchema)

const descriptionSchema = z.object({ template: z.string() })
const excludedFilesSchema = z.object({ patterns: z.string() })

export function useDefaultReviewers(owner: string, repo: string) {
  return useQuery({
    queryKey: ['repos', owner, repo, 'default-reviewers'],
    queryFn: () =>
      api.get<DefaultReviewer[]>(`/api/v1/repos/${owner}/${repo}/default-reviewers`, reviewersSchema),
    enabled: Boolean(owner && repo),
  })
}

export function useAddDefaultReviewer(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (username: string) =>
      api.post<DefaultReviewer>(`/api/v1/repos/${owner}/${repo}/default-reviewers`, reviewerSchema, { username }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'default-reviewers'] })
    },
  })
}

export function useRemoveDefaultReviewer(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (username: string) =>
      api.delete(`/api/v1/repos/${owner}/${repo}/default-reviewers/${encodeURIComponent(username)}`, z.any()),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'default-reviewers'] })
    },
  })
}

export function useDefaultDescription(owner: string, repo: string) {
  return useQuery({
    queryKey: ['repos', owner, repo, 'default-description'],
    queryFn: () =>
      api.get<{ template: string }>(`/api/v1/repos/${owner}/${repo}/default-description`, descriptionSchema),
    enabled: Boolean(owner && repo),
  })
}

export function useUpdateDefaultDescription(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (template: string) =>
      api.put<{ template: string }>(`/api/v1/repos/${owner}/${repo}/default-description`, descriptionSchema, { template }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'default-description'] })
    },
  })
}

export function useExcludedFiles(owner: string, repo: string) {
  return useQuery({
    queryKey: ['repos', owner, repo, 'excluded-files'],
    queryFn: () =>
      api.get<{ patterns: string }>(`/api/v1/repos/${owner}/${repo}/excluded-files`, excludedFilesSchema),
    enabled: Boolean(owner && repo),
  })
}

export function useUpdateExcludedFiles(owner: string, repo: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (patterns: string) =>
      api.put<{ patterns: string }>(`/api/v1/repos/${owner}/${repo}/excluded-files`, excludedFilesSchema, { patterns }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['repos', owner, repo, 'excluded-files'] })
    },
  })
}
