"use client"

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { apiClient } from "@/lib/api/client"

export type MailDomain = {
  id: string
  name: string
  status: string
  verification_token?: string
  dkim_selector?: string
  dkim_public_key?: string
  is_platform_domain: boolean
  mx_verified_at?: string | null
  txt_verified_at?: string | null
  created_at: string
}

export type MigrationProject = {
  id: string
  domain_id?: string
  name: string
  source_provider: string
  auth_mode: string
  status: string
  cutover_at?: string | null
  delta_mode: boolean
  shared_drive_mode?: "auto" | "manual"
  created_at: string
  microsoft_tenant_id?: string
  microsoft_admin_consent_at?: string | null
  microsoft_admin_consent_error?: string
  cutover_dns?: DNSCheckReport
}

export type MigrationSharedDrive = {
  id: string
  project_id: string
  drive_id: string
  name: string
  status: "pending" | "approved" | "rejected"
  discovered_by_user_id?: string | null
  created_at: string
  updated_at: string
}

export type MicrosoftAdminConsent = {
  tenant_id: string
  client_id: string
  project_id?: string
  granted: boolean
  error_code?: string
  error_description?: string
  consented_at: string
  updated_at: string
}

export type MigrationJob = {
  id: string
  project_id: string
  user_id: string
  service: string
  status: string
  stats_json?: Record<string, number | boolean | string>
  error?: string
  user_email?: string
  started_at?: string | null
  completed_at?: string | null
}

export type MigrationJobAuditItem = {
  source_id: string
  rel_path?: string
  status: "imported" | "failed" | "skipped"
  reason?: string
  imported_at: string
}

export type MigrationJobAuditSummary = {
  service: string
  imported: number
  failed: number
  skipped: number
  total: number
  by_status?: Record<string, number>
}

export type MigrationOnboardingHints = {
  needs_user_oauth: boolean
  oauth_provider?: string
  waiting_for_admin: boolean
  waiting_reason?: string
  has_migration_credentials?: boolean
  needs_microsoft_admin_consent?: boolean
}

export type MigrationUserStatus = {
  project?: MigrationProject
  invite?: MigrationInvite
  jobs?: MigrationJob[]
  onboarding?: MigrationOnboardingHints
}

export type MigrationInviteResponse = {
  invite: MigrationInvite
  project: MigrationProject
  onboarding?: MigrationOnboardingHints
}

export type MigrationInvite = {
  id: string
  project_id: string
  email: string
  alternate_emails?: string[]
  token?: string
  status: string
}

export type MigrationRosterEntry = {
  id: string
  project_id: string
  email: string
  display_name?: string
  alternate_emails?: string[]
  status: "pending" | "invited" | "claimed"
  invite_id?: string
  created_at: string
  updated_at: string
}

export type MigrationRosterImportResult = {
  created: number
  skipped_duplicates: number
  errors?: Array<{ row: number; email?: string; message: string }>
}

export type DNSCheckReport = {
  domain?: string
  txt_verified: boolean
  txt_records?: string[]
  txt_expected?: string
  mx_verified: boolean
  mx_records?: string[]
  expected_mx?: string[]
  warnings?: string[]
  errors?: string[]
}

export type MigrationCutoverResult = {
  project: MigrationProject
  dns: DNSCheckReport
}

export function useMailDomains() {
  return useQuery({
    queryKey: ["admin", "mail", "domains"],
    queryFn: () => apiClient.get<{ domains: MailDomain[] }>("/admin/mail/domains"),
  })
}

export function useCreateMailDomain() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (body: { name: string }) =>
      apiClient.post<MailDomain>("/admin/mail/domains", body),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "mail", "domains"] })
    },
  })
}

export function useVerifyMailDomainTXT(domainId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: () => apiClient.post<MailDomain>(`/admin/mail/domains/${domainId}/verify-txt`),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "mail", "domains"] })
    },
  })
}

export function useVerifyMailDomainMX(domainId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: () => apiClient.post<MailDomain>(`/admin/mail/domains/${domainId}/verify-mx`),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "mail", "domains"] })
    },
  })
}

export function useMigrationProjects() {
  return useQuery({
    queryKey: ["admin", "migration", "projects"],
    queryFn: () =>
      apiClient.get<{ projects: MigrationProject[] }>("/admin/migration/projects"),
  })
}

export function useCreateMigrationProject() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (body: {
      name: string
      source_provider: string
      domain_id?: string
      auth_mode?: string
    }) => apiClient.post<MigrationProject>("/admin/migration/projects", body),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "migration", "projects"] })
    },
  })
}

export function useActivateMigrationProject() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (projectId: string) =>
      apiClient.post<MigrationProject>(`/admin/migration/projects/${projectId}/activate`),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "migration", "projects"] })
    },
  })
}

export function useCutoverMigrationProject() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (projectId: string) =>
      apiClient.post<MigrationCutoverResult>(`/admin/migration/projects/${projectId}/cutover`),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "migration", "projects"] })
    },
  })
}

export function usePreflightCutoverDNS(projectId: string) {
  return useQuery({
    queryKey: ["admin", "migration", "projects", projectId, "cutover-dns"],
    enabled: Boolean(projectId),
    queryFn: () =>
      apiClient.get<{ dns: DNSCheckReport }>(
        `/admin/migration/projects/${projectId}/cutover-dns`
      ),
  })
}

export function useCreateMigrationInvite(projectId: string) {
  return useMutation({
    mutationFn: (body: { email: string; alternate_emails?: string[] }) =>
      apiClient.post<MigrationInvite>(`/admin/migration/projects/${projectId}/invites`, body),
  })
}

export function useImportMigrationInvites(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (emails: string[]) =>
      apiClient.post<{ imported: number }>(
        `/admin/migration/projects/${projectId}/invites/import`,
        { emails }
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "migration", "projects"] })
    },
    meta: { requiresProjectId: projectId },
  })
}

export function useMigrationRoster(projectId: string, enabled = true) {
  return useQuery({
    queryKey: ["admin", "migration", "projects", projectId, "roster"],
    enabled: Boolean(projectId) && enabled,
    queryFn: () =>
      apiClient.get<{ roster: MigrationRosterEntry[] }>(
        `/admin/migration/projects/${projectId}/roster`
      ),
  })
}

export function useImportMigrationRoster(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (csv: string) =>
      apiClient.post<MigrationRosterImportResult>(
        `/admin/migration/projects/${projectId}/roster`,
        { csv }
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "roster"],
      })
    },
    meta: { requiresProjectId: projectId },
  })
}

export function useMigrationProjectJobs(projectId: string, enabled = true) {
  return useQuery({
    queryKey: ["admin", "migration", "projects", projectId, "jobs"],
    enabled: Boolean(projectId) && enabled,
    queryFn: () =>
      apiClient.get<{ jobs: MigrationJob[] }>(
        `/admin/migration/projects/${projectId}/jobs`
      ),
    refetchInterval: 10_000,
  })
}

export function useMigrationJobAuditSummary(projectId: string, jobId: string | null) {
  return useQuery({
    queryKey: ["admin", "migration", "projects", projectId, "jobs", jobId, "audit", "summary"],
    enabled: Boolean(projectId && jobId),
    queryFn: () =>
      apiClient.get<MigrationJobAuditSummary>(
        `/admin/migration/projects/${projectId}/jobs/${jobId}/audit/summary`
      ),
    refetchInterval: 10_000,
  })
}

export function useMigrationJobAudit(
  projectId: string,
  jobId: string | null,
  status: "failed" | "skipped" | "imported" | "all" = "failed"
) {
  const statusParam = status === "all" ? "" : status
  return useQuery({
    queryKey: ["admin", "migration", "projects", projectId, "jobs", jobId, "audit", status],
    enabled: Boolean(projectId && jobId),
    queryFn: () => {
      const params = new URLSearchParams({ page_size: "50" })
      if (statusParam) params.set("status", statusParam)
      return apiClient.get<{ items: MigrationJobAuditItem[]; pagination: { total?: number } }>(
        `/admin/migration/projects/${projectId}/jobs/${jobId}/audit?${params.toString()}`
      )
    },
    refetchInterval: 10_000,
  })
}

export async function downloadMigrationJobAudit(
  projectId: string,
  jobId: string,
  format: "csv" | "ndjson"
) {
  const blob = await apiClient.getBlob(
    `/admin/migration/projects/${projectId}/jobs/${jobId}/audit/export?format=${format}`
  )
  const url = URL.createObjectURL(blob)
  const anchor = document.createElement("a")
  anchor.href = url
  anchor.download = `migration-job-audit-${jobId.slice(0, 8)}.${format === "csv" ? "csv" : "ndjson"}`
  anchor.click()
  URL.revokeObjectURL(url)
}

export async function downloadMigrationProjectAudit(
  projectId: string,
  format: "csv" | "ndjson"
) {
  const blob = await apiClient.getBlob(
    `/admin/migration/projects/${projectId}/audit/export?format=${format}`
  )
  const url = URL.createObjectURL(blob)
  const anchor = document.createElement("a")
  anchor.href = url
  anchor.download = `migration-project-audit-${projectId.slice(0, 8)}.${format === "csv" ? "csv" : "ndjson"}`
  anchor.click()
  URL.revokeObjectURL(url)
}

export function useUpdateMigrationSharedDriveMode(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (shared_drive_mode: "auto" | "manual") =>
      apiClient.patch<MigrationProject>(
        `/admin/migration/projects/${projectId}/shared-drive-mode`,
        { shared_drive_mode }
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["admin", "migration", "projects"] })
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "shared-drives"],
      })
    },
  })
}

export function useMigrationSharedDrives(projectId: string, enabled = true) {
  return useQuery({
    queryKey: ["admin", "migration", "projects", projectId, "shared-drives"],
    enabled: Boolean(projectId) && enabled,
    queryFn: () =>
      apiClient.get<{ shared_drives: MigrationSharedDrive[] }>(
        `/admin/migration/projects/${projectId}/shared-drives`
      ),
    refetchInterval: 15_000,
  })
}

export function useApproveMigrationSharedDrive(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (driveId: string) =>
      apiClient.post<MigrationSharedDrive>(
        `/admin/migration/projects/${projectId}/shared-drives/${encodeURIComponent(driveId)}/approve`
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "shared-drives"],
      })
    },
  })
}

export function useRejectMigrationSharedDrive(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (driveId: string) =>
      apiClient.post<MigrationSharedDrive>(
        `/admin/migration/projects/${projectId}/shared-drives/${encodeURIComponent(driveId)}/reject`
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "shared-drives"],
      })
    },
  })
}

export function useRetryMigrationJob(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (jobId: string) =>
      apiClient.post<MigrationJob>(
        `/admin/migration/projects/${projectId}/jobs/${jobId}/retry`
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "jobs"],
      })
    },
  })
}

export function useResetMigrationJobCursor(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (jobId: string) =>
      apiClient.post<MigrationJob>(
        `/admin/migration/projects/${projectId}/jobs/${jobId}/reset-cursor`
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "jobs"],
      })
    },
  })
}

export function useRetryMigrationFailedJobs(projectId: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: () =>
      apiClient.post<{ retried: number }>(
        `/admin/migration/projects/${projectId}/jobs/retry-failed`
      ),
    onSuccess: () => {
      void queryClient.invalidateQueries({
        queryKey: ["admin", "migration", "projects", projectId, "jobs"],
      })
    },
  })
}

export function useMicrosoftMigrationAdminConsentURL() {
  return useMutation({
    mutationFn: (body: { tenant?: string; projectId?: string }) => {
      const params = new URLSearchParams()
      if (body.tenant?.trim()) params.set("tenant", body.tenant.trim())
      if (body.projectId) params.set("project_id", body.projectId)
      const query = params.toString()
      return apiClient.get<{ url: string }>(
        `/admin/migration/microsoft/admin-consent-url${query ? `?${query}` : ""}`
      )
    },
  })
}

export function useMicrosoftAdminConsents() {
  return useQuery({
    queryKey: ["admin", "migration", "microsoft", "admin-consents"],
    queryFn: () =>
      apiClient.get<{ consents: MicrosoftAdminConsent[] }>(
        "/admin/migration/microsoft/admin-consents"
      ),
  })
}

export function useMigrationInvite(token: string | null) {
  return useQuery({
    queryKey: ["migration", "invite", token],
    enabled: Boolean(token),
    queryFn: () =>
      apiClient.get<MigrationInviteResponse>(
        `/migration/invite?token=${encodeURIComponent(token ?? "")}`
      ),
  })
}

export function useMigrationStatus() {
  return useQuery({
    queryKey: ["migration", "status"],
    queryFn: () => apiClient.get<MigrationUserStatus>("/migration/status"),
  })
}

export function useClaimMigration() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (body: { token: string; password?: string }) =>
      apiClient.post("/migration/claim", body),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["migration"] })
    },
  })
}

export function useStartMigrationOAuth() {
  return useMutation({
    mutationFn: (body: { provider: string; invite_token?: string; project_id?: string }) =>
      apiClient.post<{ auth_url: string }>("/migration/oauth/start", body),
  })
}

export function useCheckMailAddress(local: string, domain: string) {
  return useQuery({
    queryKey: ["mail", "address-check", local, domain],
    enabled: local.length > 0 && domain.length > 0,
    queryFn: () =>
      apiClient.get<{ available: boolean; reason?: string }>(
        `/mail/addresses/check?local=${encodeURIComponent(local)}&domain=${encodeURIComponent(domain)}`
      ),
  })
}

export type HostedMailEndpoints = {
  imap_host: string
  imap_port: number
  imap_tls: boolean
  smtp_host: string
  smtp_port: number
  smtp_tls: boolean
}

export type HostedMailStatus = {
  enabled: boolean
  platform_domain?: string
  domain_status?: string
  endpoints?: HostedMailEndpoints
  mailbox?: {
    id: string
    email: string
    mail_account_id?: string
    status: string
  }
  hosted_mail_account_id?: string
  hosted_mail_account_email?: string
}

export function useHostedMailStatus() {
  return useQuery({
    queryKey: ["mail", "hosted", "status"],
    queryFn: () => apiClient.get<HostedMailStatus>("/mail/hosted/status"),
  })
}

export function useSetupHostedMailbox() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (body: { local_part: string; password: string; display_name?: string }) =>
      apiClient.post<{ email: string; mail_account_id: string }>("/mail/hosted/setup", body),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ["mail", "hosted", "status"] })
      void queryClient.invalidateQueries({ queryKey: ["accounts"] })
      void queryClient.invalidateQueries({ queryKey: ["identities"] })
    },
  })
}
