import { useCallback, useState } from "react"
import axios from "axios"
import i18n from "@/lib/i18n"
import { api } from "@/lib/api"
import { ENDPOINTS } from "@/constants/endpoints"
import type {
  PaginatedResponse,
  SellOrderCreateRequest,
  SellOrderDetail,
  SellOrderFilters,
  SellOrderItem,
  SellOrderItemPayload,
  SellOrderListItem,
  SellOrderSupportData,
  SellPrice,
} from "@/types"

const emptySupport: SellOrderSupportData = {
  availability: null,
  history: [],
  approvals: [],
  walletMovements: [],
  inventoryMovements: [],
  journals: [],
  auditLogs: [],
  voucher: null,
}

function unwrap<T>(value: any): T {
  return (value && typeof value === "object" && "data" in value ? value.data : value) as T
}

export function sellErrorMessage(error: unknown): string {
  if (axios.isAxiosError(error)) {
    const detail = error.response?.data?.detail
    if (detail && typeof detail === "object") {
      const code = detail.error_code as string | undefined
      const messages: Record<string, { en: string; ar: string }> = {
        SELL_PRICE_EXPIRED: { en: "The price has expired. Recalculate before continuing.", ar: "انتهت صلاحية السعر. أعد الاحتساب قبل المتابعة." },
        SELL_INSUFFICIENT_BALANCE: { en: "The customer cash balance is insufficient.", ar: "رصيد العميل النقدي غير كاف." },
        SELL_WALLET_NOT_FOUND: { en: "The required customer wallet was not found.", ar: "لم يتم العثور على محفظة العميل المطلوبة." },
        SELL_AVAILABILITY_FAILED: { en: "The order failed the availability check.", ar: "فشل أمر البيع في التحقق من التوفر." },
        SELL_POSTED_CANNOT_UPDATE: { en: "A posted sell order cannot be changed.", ar: "لا يمكن تعديل أمر بيع مرحل." },
        SELL_POSTED_CANNOT_CANCEL: { en: "A posted sell order must be reversed, not cancelled.", ar: "يجب عكس أمر البيع المرحل ولا يمكن إلغاؤه مباشرة." },
        SELL_POSTING_ALREADY_EXISTS: { en: "This sell order has already been posted.", ar: "تم ترحيل أمر البيع مسبقا." },
        SELL_INVALID_STATUS_TRANSITION: { en: "This action is not allowed in the current status.", ar: "هذا الإجراء غير مسموح في الحالة الحالية." },
        SELL_PERMISSION_DENIED: { en: "You do not have permission for this action.", ar: "ليس لديك صلاحية لتنفيذ هذا الإجراء." },
      }
      if (code && messages[code]) return messages[code][i18n.language.startsWith("ar") ? "ar" : "en"]
      return detail.message || code || "Sell order request failed"
    }
    return error.response?.data?.message || detail || error.message
  }
  return error instanceof Error ? error.message : "Sell order request failed"
}

export function useSellOrders() {
  const [items, setItems] = useState<SellOrderListItem[]>([])
  const [selected, setSelected] = useState<SellOrderDetail | null>(null)
  const [support, setSupport] = useState<SellOrderSupportData>(emptySupport)
  const [total, setTotal] = useState(0)
  const [pages, setPages] = useState(1)
  const [isLoading, setIsLoading] = useState(false)
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const list = useCallback(async (filters: SellOrderFilters = {}) => {
    setIsLoading(true)
    setError(null)
    try {
      const response = unwrap<PaginatedResponse<SellOrderListItem>>(await api.get(ENDPOINTS.SELL_ORDERS.LIST, { params: filters }))
      setItems(response.items ?? [])
      setTotal(response.total ?? 0)
      setPages(response.pages ?? 1)
      return response
    } catch (err) {
      setError(sellErrorMessage(err))
      return null
    } finally {
      setIsLoading(false)
    }
  }, [])

  const get = useCallback(async (id: string) => {
    setIsLoading(true)
    setError(null)
    try {
      const detail = unwrap<SellOrderDetail>(await api.get(ENDPOINTS.SELL_ORDERS.GET_BY_ID(id)))
      setSelected(detail)
      return detail
    } catch (err) {
      setError(sellErrorMessage(err))
      return null
    } finally {
      setIsLoading(false)
    }
  }, [])

  const create = useCallback(async (payload: SellOrderCreateRequest) => {
    setIsSubmitting(true)
    try {
      return unwrap<SellOrderDetail>(await api.post(ENDPOINTS.SELL_ORDERS.CREATE, payload))
    } finally {
      setIsSubmitting(false)
    }
  }, [])

  const update = useCallback(async (id: string, payload: Partial<SellOrderCreateRequest>) => {
    setIsSubmitting(true)
    try {
      return unwrap<SellOrderDetail>(await api.patch(ENDPOINTS.SELL_ORDERS.UPDATE(id), payload))
    } finally {
      setIsSubmitting(false)
    }
  }, [])

  const quote = useCallback((purityId: string, currencyId: string) =>
    api.post(ENDPOINTS.SELL_ORDERS.COMPUTE_PRICE, { purity_id: purityId, currency_id: currencyId }).then(unwrap<SellPrice>), [])

  const addItem = useCallback((id: string, payload: SellOrderItemPayload) =>
    api.post(ENDPOINTS.SELL_ORDERS.ITEMS(id), payload).then(unwrap<SellOrderItem>), [])

  const updateItem = useCallback((id: string, itemId: string, payload: Partial<SellOrderItemPayload>) =>
    api.patch(ENDPOINTS.SELL_ORDERS.ITEM(id, itemId), payload).then(unwrap<SellOrderItem>), [])

  const deleteItem = useCallback((id: string, itemId: string) =>
    api.del(ENDPOINTS.SELL_ORDERS.ITEM(id, itemId)), [])

  const recalculate = useCallback((id: string) =>
    api.post(ENDPOINTS.SELL_ORDERS.RECALCULATE(id)).then(unwrap<SellOrderDetail>), [])

  const act = useCallback(async (id: string, action: string, reason?: string) => {
    const e = ENDPOINTS.SELL_ORDERS
    const endpoint: Record<string, string> = {
      submit: e.SUBMIT_FOR_REVIEW(id),
      review: e.SUBMIT_FOR_APPROVAL(id),
      approve: e.APPROVE(id),
      reject: e.REJECT(id),
      cancel: e.CANCEL(id),
      post: e.POST(id),
      delivering: e.MARK_DELIVERING(id),
      delivered: e.MARK_DELIVERED(id),
      close: e.CLOSE(id),
      reverse: e.REVERSE(id),
    }
    const body = action === "cancel" || action === "reverse" ? { reason } : action === "post" ? undefined : { note: reason || null }
    setIsSubmitting(true)
    try {
      return unwrap<any>(await api.post(endpoint[action], body))
    } finally {
      setIsSubmitting(false)
    }
  }, [])

  const loadSupport = useCallback(async (id: string) => {
    const e = ENDPOINTS.SELL_ORDERS
    const requests = [
      api.get(e.AVAILABILITY(id)),
      api.get(e.STATUS_HISTORY(id)),
      api.get(e.APPROVALS(id)),
      api.get(e.WALLET_MOVEMENTS(id)),
      api.get(e.INVENTORY_MOVEMENTS(id)),
      api.get(e.JOURNAL_DETAILS(id)),
      api.get(ENDPOINTS.AUDIT_LOGS.LIST, { params: { entity_type: "sell_order", entity_id: id } }),
      api.get(e.VOUCHER(id)),
    ]
    const results = await Promise.allSettled(requests)
    const value = (index: number, fallback: any) =>
      results[index].status === "fulfilled" ? unwrap<any>((results[index] as PromiseFulfilledResult<any>).value) : fallback
    const walletPayload = value(3, { cash_movements: [], gold_movements: [] })
    const inventoryPayload = value(4, { movements: [] })
    const journalPayload = value(5, { journals: [] })
    const next: SellOrderSupportData = {
      availability: value(0, null),
      history: value(1, []),
      approvals: value(2, []),
      walletMovements: [...(walletPayload.cash_movements ?? []), ...(walletPayload.gold_movements ?? [])],
      inventoryMovements: inventoryPayload.movements ?? [],
      journals: journalPayload.journals ?? [],
      auditLogs: value(6, { items: [] }).items ?? [],
      voucher: value(7, null),
    }
    setSupport(next)
    return next
  }, [])

  return {
    items,
    selected,
    support,
    total,
    pages,
    isLoading,
    isSubmitting,
    error,
    list,
    get,
    create,
    update,
    quote,
    addItem,
    updateItem,
    deleteItem,
    recalculate,
    act,
    loadSupport,
  }
}
