import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"

import { apiClient } from "@/lib/api-client"

// --- Types ---

export type PaymentMethod = "CASH" | "BANK_TRANSFER" | "SEPA" | "CARD"
export type PaymentStatus = "PAID" | "PENDING" | "OVERDUE" | "VOIDED"
export type FeeInterval = "MONTHLY" | "QUARTERLY" | "YEARLY" | "ONE_TIME"
export type ExpenseCategory =
  | "RENT"
  | "UTILITIES"
  | "EQUIPMENT"
  | "SEEDS"
  | "SUPPLIES"
  | "INSURANCE"
  | "LEGAL"
  | "OTHER"
export type TransactionType = "INCOME" | "EXPENSE"

export interface FeeSchedule {
  id: string
  tenantId: string
  name: string
  amountCents: number
  interval: FeeInterval
  description: string | null
  active: boolean
  isDefault: boolean
  createdAt: string
  updatedAt: string
}

export interface MemberFeeAssignment {
  id: string
  tenantId: string
  memberId: string
  feeScheduleId: string
  validFrom: string
  validUntil: string | null
  notes: string | null
  createdAt: string
}

export interface Payment {
  id: string
  tenantId: string
  memberId: string
  memberName?: string
  amountCents: number
  paymentDate: string
  paymentMethod: PaymentMethod
  reference: string | null
  periodFrom: string | null
  periodTo: string | null
  receiptNumber: string | null
  notes: string | null
  voided: boolean
  voidedReason: string | null
  voidedAt: string | null
  recordedBy: string
  createdAt: string
}

export interface LedgerEntry {
  id: string
  tenantId: string
  transactionDate: string
  transactionType: TransactionType
  category: string | null
  description: string
  amountCents: number
  reference: string | null
  relatedPaymentId: string | null
  relatedExpenseId: string | null
  runningBalanceCents?: number
  recordedBy: string
  createdAt: string
}

export interface FinancialSummary {
  totalIncomeCents: number
  totalExpenseCents: number
  netBalanceCents: number
  incomeThisMonthCents: number
  expensesThisMonthCents: number
  outstandingMembersCount: number
  totalOutstandingCents: number
}

export interface MemberBalance {
  memberId: string
  memberName: string
  feeScheduleName: string | null
  totalDueCents: number
  totalPaidCents: number
  outstandingCents: number
  lastPaymentDate: string | null
  status: "CURRENT" | "OVERDUE" | "NO_FEE"
}

export interface OutstandingMember {
  memberId: string
  memberName: string
  memberNumber: string | null
  outstandingCents: number
  lastPaymentDate: string | null
  monthsOverdue: number
}

// --- Request Types ---

export interface CreateFeeScheduleRequest {
  name: string
  amountCents: number
  interval: FeeInterval
  description?: string
  isDefault?: boolean
}

export interface UpdateFeeScheduleRequest {
  name?: string
  amountCents?: number
  interval?: FeeInterval
  description?: string
  isDefault?: boolean
}

export interface AssignFeeRequest {
  feeScheduleId: string
  validFrom: string
}

export interface RecordPaymentRequest {
  memberId: string
  amountCents: number
  paymentMethod: PaymentMethod
  periodFrom?: string
  periodTo?: string
  reference?: string
  notes?: string
}

export interface VoidPaymentRequest {
  reason: string
}

export interface RecordExpenseRequest {
  category: ExpenseCategory
  amountCents: number
  description: string
  reference?: string
  transactionDate?: string
}

// --- Response Types ---

export interface PaginatedResponse<T> {
  content: T[]
  totalElements: number
  totalPages: number
  number: number
  size: number
}

// --- Admin Query Hooks ---

export function useFeeSchedulesQuery() {
  return useQuery({
    queryKey: ["finance", "fee-schedules"],
    queryFn: () => apiClient<FeeSchedule[]>("/finance/fee-schedules"),
  })
}

export function usePaymentsQuery(options?: {
  memberId?: string
  status?: PaymentStatus
  page?: number
  size?: number
}) {
  return useQuery({
    queryKey: ["finance", "payments", options],
    queryFn: () => {
      const params = new URLSearchParams()
      if (options?.memberId) params.set("memberId", options.memberId)
      if (options?.status) params.set("status", options.status)
      params.set("page", String(options?.page ?? 0))
      params.set("size", String(options?.size ?? 20))
      return apiClient<PaginatedResponse<Payment>>(
        `/finance/payments?${params}`
      )
    },
  })
}

export function useLedgerQuery(
  from: string,
  to: string,
  options?: { page?: number; size?: number }
) {
  return useQuery({
    queryKey: ["finance", "ledger", from, to, options],
    queryFn: () => {
      const params = new URLSearchParams()
      params.set("from", from)
      params.set("to", to)
      params.set("page", String(options?.page ?? 0))
      params.set("size", String(options?.size ?? 50))
      return apiClient<PaginatedResponse<LedgerEntry>>(
        `/finance/ledger?${params}`
      )
    },
    enabled: !!from && !!to,
  })
}

export function useFinancialSummaryQuery(from: string, to: string) {
  return useQuery({
    queryKey: ["finance", "summary", from, to],
    queryFn: () =>
      apiClient<FinancialSummary>(`/finance/summary?from=${from}&to=${to}`),
    enabled: !!from && !!to,
  })
}

export function useOutstandingMembersQuery() {
  return useQuery({
    queryKey: ["finance", "outstanding"],
    queryFn: () => apiClient<OutstandingMember[]>("/finance/outstanding"),
  })
}

export function useMemberBalanceQuery(memberId: string | undefined) {
  return useQuery({
    queryKey: ["finance", "balance", memberId],
    queryFn: () =>
      apiClient<MemberBalance>(`/finance/members/${memberId}/balance`),
    enabled: !!memberId,
  })
}

// --- Portal Query Hooks ---

export function useMyPaymentsQuery(options?: { page?: number; size?: number }) {
  return useQuery({
    queryKey: ["portal", "finance", "payments", options],
    queryFn: () => {
      const params = new URLSearchParams()
      params.set("page", String(options?.page ?? 0))
      params.set("size", String(options?.size ?? 20))
      return apiClient<PaginatedResponse<Payment>>(
        `/portal/finance/payments?${params}`
      )
    },
  })
}

export function useMyBalanceQuery() {
  return useQuery({
    queryKey: ["portal", "finance", "balance"],
    queryFn: () => apiClient<MemberBalance>("/portal/finance/balance"),
  })
}

// --- Mutation Hooks ---

export function useCreateFeeScheduleMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (data: CreateFeeScheduleRequest) =>
      apiClient<FeeSchedule>("/finance/fee-schedules", {
        method: "POST",
        body: data,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance", "fee-schedules"] })
    },
  })
}

export function useUpdateFeeScheduleMutation(id: string) {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (data: UpdateFeeScheduleRequest) =>
      apiClient<FeeSchedule>(`/finance/fee-schedules/${id}`, {
        method: "PUT",
        body: data,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance", "fee-schedules"] })
    },
  })
}

export function useDeactivateFeeScheduleMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (id: string) =>
      apiClient<void>(`/finance/fee-schedules/${id}/deactivate`, {
        method: "POST",
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance", "fee-schedules"] })
    },
  })
}

export function useAssignFeeMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: ({
      memberId,
      ...data
    }: AssignFeeRequest & { memberId: string }) =>
      apiClient<MemberFeeAssignment>(
        `/finance/members/${memberId}/assign-fee`,
        {
          method: "POST",
          body: data,
        }
      ),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance"] })
    },
  })
}

export function useRecordPaymentMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (data: RecordPaymentRequest) =>
      apiClient<Payment>("/finance/payments", {
        method: "POST",
        body: data,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance"] })
    },
  })
}

export function useVoidPaymentMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: ({ id, reason }: { id: string; reason: string }) =>
      apiClient<Payment>(`/finance/payments/${id}/void`, {
        method: "POST",
        body: { reason } as VoidPaymentRequest,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance"] })
    },
  })
}

export function useRecordExpenseMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: (data: RecordExpenseRequest) =>
      apiClient<LedgerEntry>("/finance/expenses", {
        method: "POST",
        body: data,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["finance"] })
    },
  })
}

// --- Utility: PDF Download ---

export function getReceiptDownloadUrl(paymentId: string): string {
  return `/api/backend/finance/payments/${paymentId}/receipt`
}

export function getPortalReceiptDownloadUrl(paymentId: string): string {
  return `/api/backend/portal/finance/payments/${paymentId}/receipt`
}

export function getAnnualReportDownloadUrl(year: number): string {
  return `/api/backend/finance/reports/annual?year=${year}`
}

export function getKassenbuchCsvDownloadUrl(from: string, to: string): string {
  return `/api/backend/finance/ledger/export?from=${from}&to=${to}`
}

// --- Utility: Amount formatting ---

export function formatAmountCents(cents: number): string {
  return new Intl.NumberFormat("de-DE", {
    style: "currency",
    currency: "EUR",
  }).format(cents / 100)
}

export function formatAmountCentsShort(cents: number): string {
  return `${(cents / 100).toFixed(2).replace(".", ",")} €`
}
