'use client'

import { useCallback, useEffect, useMemo, useState } from 'react'
import type { ChangeEvent } from 'react'
import { Chip, IconButton, Stack, Tooltip, Typography } from '@mui/material'
import { useTheme } from '@mui/material/styles'
import { useRouter, useSearchParams } from 'next/navigation'
import { useLocale, useTranslations } from 'next-intl'
import { ColumnDef, createColumnHelper, getCoreRowModel, useReactTable } from '@tanstack/react-table'
import { toast } from 'react-toastify'

import { formatDate, getSearchParams } from '@/utils'
import {
  PaymentLinksFilters,
  PaymentLinkStatus,
  useCancelPaymentLink,
  useCreatePaymentLink,
  useDeletePaymentLink,
  useGetPaymentLinks,
  useUpdatePaymentLink
} from '@/hooks/data/payment-link'
import { IPaymentLink } from '@/types'
import PaymentLinksDialogs from './PaymentLinksDialogs'
import PaymentLinksFiltersSection from './PaymentLinksFiltersSection'
import PaymentLinksHero from './PaymentLinksHero'
import PaymentLinksTableSection from './PaymentLinksTableSection'

type PaymentLinkWithActions = IPaymentLink & { actions?: string }

const statusOptions: PaymentLinkStatus[] = ['pending', 'paid', 'failed', 'cancelled']

const sortByOptions: PaymentLinksFilters['sort_by'][] = ['created_at', 'updated_at', 'expires_at', 'paid_at', 'amount']

const statusColorMap: Record<PaymentLinkStatus, 'default' | 'warning' | 'success' | 'error'> = {
  pending: 'warning',
  paid: 'success',
  failed: 'error',
  cancelled: 'default'
}

const columnHelper = createColumnHelper<PaymentLinkWithActions>()

const PaymentLinksView = () => {
  const theme = useTheme()
  const router = useRouter()
  const searchParams = useSearchParams()
  const t = useTranslations('PAYMENT_LINKS')
  const locale = useLocale()
  const statusLabelMap = useMemo(
    () => ({
      pending: t('status.pending'),
      paid: t('status.paid'),
      failed: t('status.failed'),
      cancelled: t('status.cancelled')
    }),
    [t]
  )

  const [searchValue, setSearchValue] = useState(searchParams.get('search') || '')
  const [debouncedSearch, setDebouncedSearch] = useState(searchParams.get('search') || '')
  const [createOpen, setCreateOpen] = useState(false)
  const [createValues, setCreateValues] = useState({
    amount: '',
    customer_name: '',
    customer_email: '',
    customer_phone: '',
    description: '',
    expires_at: ''
  })
  const [createErrors, setCreateErrors] = useState<Record<string, string>>({})
  const [createdLinkUrl, setCreatedLinkUrl] = useState<string | null>(null)
  const [createdDialogOpen, setCreatedDialogOpen] = useState(false)
  const [activeLink, setActiveLink] = useState<IPaymentLink | null>(null)
  const [editValues, setEditValues] = useState({ customer_name: '', description: '' })
  const [editOpen, setEditOpen] = useState(false)
  const [viewOpen, setViewOpen] = useState(false)
  const [cancelOpen, setCancelOpen] = useState(false)
  const [deleteOpen, setDeleteOpen] = useState(false)

  const page = Number(searchParams.get('page')) || 1
  const rowsPerPage = Number(searchParams.get('per_page')) || 10
  const sortBy = (searchParams.get('sort_by') as PaymentLinksFilters['sort_by']) || 'created_at'
  const sortAs = (searchParams.get('sort_as') as PaymentLinksFilters['sort_as']) || 'desc'
  const statusParam = searchParams.get('status') || ''
  const statusFilter = statusParam ? (statusParam.split(',') as PaymentLinkStatus[]) : []
  const amountMin = searchParams.get('amount_min') || ''
  const amountMax = searchParams.get('amount_max') || ''
  const createdFrom = searchParams.get('created_from') || ''
  const createdTo = searchParams.get('created_to') || ''
  const expiresFrom = searchParams.get('expires_from') || ''
  const expiresTo = searchParams.get('expires_to') || ''
  const paidFrom = searchParams.get('paid_from') || ''
  const paidTo = searchParams.get('paid_to') || ''

  const updateParams = useCallback(
    (updates: Record<string, string | number | undefined>) => {
      const params = new URLSearchParams(searchParams.toString())

      Object.entries(updates).forEach(([key, value]) => {
        if (value === undefined || value === '') {
          params.delete(key)
        } else {
          params.set(key, String(value))
        }
      })

      router.replace(`?${params.toString()}`, { scroll: false })
    },
    [router, searchParams]
  )

  useEffect(() => {
    const timeout = setTimeout(() => {
      const trimmed = searchValue.trim()
      setDebouncedSearch(trimmed)
      updateParams({ search: trimmed || undefined, page: 1 })
    }, 600)

    return () => clearTimeout(timeout)
  }, [searchValue, updateParams])

  const queryFilters = useMemo<PaymentLinksFilters>(() => {
    const parsedMin = amountMin.trim() === '' ? undefined : Number(amountMin)
    const parsedMax = amountMax.trim() === '' ? undefined : Number(amountMax)
    const amountMinValue = Number.isFinite(parsedMin) ? parsedMin : undefined
    const amountMaxValue = Number.isFinite(parsedMax) ? parsedMax : undefined

    return {
      page,
      per_page: rowsPerPage,
      search: debouncedSearch || undefined,
      status: statusFilter.length ? statusFilter : undefined,
      amount_min: amountMinValue,
      amount_max: amountMaxValue,
      created_from: createdFrom || undefined,
      created_to: createdTo || undefined,
      expires_from: expiresFrom || undefined,
      expires_to: expiresTo || undefined,
      paid_from: paidFrom || undefined,
      paid_to: paidTo || undefined,
      sort_by: sortBy,
      sort_as: sortAs
    }
  }, [
    amountMax,
    amountMin,
    createdFrom,
    createdTo,
    debouncedSearch,
    expiresFrom,
    expiresTo,
    page,
    paidFrom,
    paidTo,
    rowsPerPage,
    sortAs,
    sortBy,
    statusFilter
  ])

  const { data, isLoading, isFetching } = useGetPaymentLinks(queryFilters)
  const { mutateAsync: updatePaymentLink, isPending: isUpdating } = useUpdatePaymentLink()
  const { mutateAsync: cancelPaymentLink, isPending: isCancelling } = useCancelPaymentLink()
  const { mutateAsync: deletePaymentLink, isPending: isDeleting } = useDeletePaymentLink()
  const { mutateAsync: createPaymentLink, isPending: isCreating } = useCreatePaymentLink()

  const links = data?.data?.payment_links ?? []
  const pagination = data?.meta?.pagination
  const total = pagination?.total ?? 0

  const isTableLoading = isLoading || isFetching
  const isDark = theme.palette.mode === 'dark'

  const activeFiltersCount = [
    debouncedSearch,
    statusFilter.length ? 'status' : '',
    amountMin,
    amountMax,
    createdFrom,
    createdTo,
    expiresFrom,
    expiresTo,
    paidFrom,
    paidTo,
    sortBy !== 'created_at' ? 'sortBy' : '',
    sortAs !== 'desc' ? 'sortAs' : ''
  ].filter(Boolean).length

  const handleEditOpen = useCallback((link: IPaymentLink) => {
    setActiveLink(link)
    setEditValues({
      customer_name: link.customer_name || '',
      description: link.description || ''
    })
    setEditOpen(true)
  }, [])

  const handleCancelOpen = useCallback((link: IPaymentLink) => {
    setActiveLink(link)
    setCancelOpen(true)
  }, [])

  const handleViewOpen = useCallback((link: IPaymentLink) => {
    setActiveLink(link)
    setViewOpen(true)
  }, [])

  const handleDeleteOpen = useCallback((link: IPaymentLink) => {
    setActiveLink(link)
    setDeleteOpen(true)
  }, [])

  const handleCopy = useCallback(
    (value?: string | null) => {
      if (!value) return
      if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
        navigator.clipboard.writeText(value)
        toast.success(t('actions.copied'))
      }
    },
    [t]
  )

  const handleUpdateSubmit = useCallback(async () => {
    if (!activeLink) return
    await updatePaymentLink({ paymentLinkId: activeLink.id, data: editValues })
    setEditOpen(false)
  }, [activeLink, editValues, updatePaymentLink])

  const handleCancelSubmit = useCallback(async () => {
    if (!activeLink) return
    await cancelPaymentLink({ paymentLinkId: activeLink.id })
    setCancelOpen(false)
  }, [activeLink, cancelPaymentLink])

  const handleDeleteSubmit = useCallback(async () => {
    if (!activeLink) return
    await deletePaymentLink({ paymentLinkId: activeLink.id })
    setDeleteOpen(false)
  }, [activeLink, deletePaymentLink])

  const handleCreateSubmit = useCallback(async () => {
    const nextErrors: Record<string, string> = {}
    const amountValue = Number(createValues.amount)
    const phoneValue = createValues.customer_phone.trim()
    const phoneRegex = /^\+?\d{7,15}$/

    if (!createValues.amount || !Number.isFinite(amountValue) || amountValue <= 0) {
      nextErrors.amount = t('validation.amountPositive')
    }
    if (!createValues.customer_name.trim()) {
      nextErrors.customer_name = t('validation.customerNameRequired')
    }
    if (!createValues.customer_email.trim()) {
      nextErrors.customer_email = t('validation.customerEmailRequired')
    }
    if (!/^\S+@\S+\.\S+$/.test(createValues.customer_email.trim())) {
      nextErrors.customer_email = t('validation.customerEmailInvalid')
    }
    if (!phoneValue) {
      nextErrors.customer_phone = t('validation.customerPhoneRequired')
    } else if (!phoneRegex.test(phoneValue)) {
      nextErrors.customer_phone = t('validation.customerPhoneInvalid')
    }
    if (!createValues.expires_at) {
      nextErrors.expires_at = t('validation.expiryRequired')
    }

    setCreateErrors(nextErrors)
    if (Object.keys(nextErrors).length) return

    const response = await createPaymentLink({
      amount: Number.isFinite(amountValue) ? amountValue : 0,
      currency: 'AED',
      customer_name: createValues.customer_name,
      customer_email: createValues.customer_email,
      customer_phone: createValues.customer_phone,
      description: createValues.description,
      expires_at: createValues.expires_at
    })

    setCreateValues({
      amount: '',
      customer_name: '',
      customer_email: '',
      customer_phone: '',
      description: '',
      expires_at: ''
    })
    setCreateErrors({})
    setCreatedLinkUrl(response?.data?.payment_link?.public_url || null)
    setCreatedDialogOpen(true)
    setCreateOpen(false)
  }, [createPaymentLink, createValues, t])

  const handlePageSizeChange = useCallback(
    (event: ChangeEvent<HTMLInputElement>) => {
      const newPageSize = Number(event.target.value)
      router.push(`?${getSearchParams({ per_page: newPageSize, page: 1 })}`, { scroll: false })
    },
    [router]
  )

  const resetFilters = useCallback(() => {
    setSearchValue('')
    updateParams({
      search: undefined,
      status: undefined,
      amount_min: undefined,
      amount_max: undefined,
      created_from: undefined,
      created_to: undefined,
      expires_from: undefined,
      expires_to: undefined,
      paid_from: undefined,
      paid_to: undefined,
      sort_by: 'created_at',
      sort_as: 'desc',
      page: 1
    })
  }, [updateParams])

  const columns = useMemo<ColumnDef<PaymentLinkWithActions, any>[]>(
    () => [
      columnHelper.display({
        id: 'number',
        header: t('table.number'),
        cell: ({ row }) => {
          const rowNumber = (page - 1) * rowsPerPage + row.index + 1
          return <Typography fontWeight={600}>{rowNumber}</Typography>
        }
      }),
      columnHelper.accessor('customer_name', {
        header: t('table.customer'),
        cell: ({ row }) => (
          <Stack spacing={0.5}>
            <Typography>{row.original.customer_name || '-'}</Typography>
            <Typography variant='caption' color='text.secondary'>
              {row.original.customer_email || '-'}
            </Typography>
          </Stack>
        )
      }),
      columnHelper.accessor('amount', {
        header: t('table.amount'),
        cell: ({ row }) => (
          <Typography fontWeight={600}>
            {row.original.amount} {row.original.currency}
          </Typography>
        )
      }),
      columnHelper.accessor('payment_status', {
        header: t('table.status'),
        cell: ({ row }) => (
          <Chip
            size='small'
            label={statusLabelMap[row.original.payment_status]}
            color={statusColorMap[row.original.payment_status]}
          />
        )
      }),
      columnHelper.accessor('created_at', {
        header: t('table.created'),
        cell: info => formatDate(info.getValue(), locale)
      }),
      columnHelper.accessor('expires_at', {
        header: t('table.expires'),
        cell: info => formatDate(info.getValue(), locale)
      }),
      columnHelper.accessor('paid_at', {
        header: t('table.paid'),
        cell: info => formatDate(info.getValue(), locale)
      }),
      columnHelper.accessor('public_url', {
        header: t('table.publicUrl'),
        cell: info =>
          info.getValue() ? (
            <Stack direction='row' spacing={1} alignItems='center'>
              <Tooltip title={t('table.open')}>
                <IconButton
                  size='small'
                  color='primary'
                  component='a'
                  href={info.getValue()}
                  target='_blank'
                  rel='noopener noreferrer'
                >
                  <i className='tabler-external-link' />
                </IconButton>
              </Tooltip>
              <Tooltip title={t('actions.copy')}>
                <IconButton size='small' color='primary' onClick={() => handleCopy(info.getValue())}>
                  <i className='tabler-copy' />
                </IconButton>
              </Tooltip>
            </Stack>
          ) : (
            '-'
          )
      }),
      columnHelper.display({
        id: 'actions',
        header: t('table.actions'),
        cell: ({ row }) => (
          <Stack direction='row' spacing={1} justifyContent='flex-end'>
            <Tooltip title={t('actions.view')}>
              <IconButton size='small' color='info' onClick={() => handleViewOpen(row.original)}>
                <i className='tabler-eye' />
              </IconButton>
            </Tooltip>
            <Tooltip title={t('actions.edit')}>
              <IconButton size='small' color='primary' onClick={() => handleEditOpen(row.original)}>
                <i className='tabler-edit' />
              </IconButton>
            </Tooltip>
            <Tooltip title={t('actions.cancel')}>
              <IconButton size='small' color='warning' onClick={() => handleCancelOpen(row.original)}>
                <i className='tabler-ban' />
              </IconButton>
            </Tooltip>
            <Tooltip title={t('actions.delete')}>
              <IconButton size='small' color='error' onClick={() => handleDeleteOpen(row.original)}>
                <i className='tabler-trash' />
              </IconButton>
            </Tooltip>
          </Stack>
        ),
        meta: { align: 'right' }
      })
    ],
    [handleCancelOpen, handleDeleteOpen, handleEditOpen, handleViewOpen, locale, page, rowsPerPage, statusLabelMap, t]
  )

  const table = useReactTable({
    data: links,
    columns,
    getCoreRowModel: getCoreRowModel(),
    manualPagination: true,
    pageCount: Math.max(1, Math.ceil(total / rowsPerPage)),
    state: { pagination: { pageIndex: page - 1, pageSize: rowsPerPage } },
    onPaginationChange: updater => {
      const newPagination = typeof updater === 'function' ? updater(table.getState().pagination) : updater
      updateParams({
        page: newPagination.pageIndex + 1,
        per_page: newPagination.pageSize
      })
    }
  })

  return (
    <Stack spacing={4}>
      <PaymentLinksHero
        theme={theme}
        isDark={isDark}
        title={t('title')}
        subtitle={t('subtitle')}
        createLabel={t('actions.create')}
        onCreate={() => setCreateOpen(true)}
      />

      <PaymentLinksFiltersSection
        t={t}
        isFetching={isFetching}
        activeFiltersCount={activeFiltersCount}
        resetFilters={resetFilters}
        searchValue={searchValue}
        onSearchChange={setSearchValue}
        statusFilter={statusFilter}
        statusOptions={statusOptions}
        statusLabelMap={statusLabelMap}
        statusColorMap={statusColorMap}
        updateParams={updateParams}
        amountMin={amountMin}
        amountMax={amountMax}
        createdFrom={createdFrom}
        createdTo={createdTo}
        expiresFrom={expiresFrom}
        expiresTo={expiresTo}
        paidFrom={paidFrom}
        paidTo={paidTo}
        sortBy={sortBy}
        sortAs={sortAs}
        sortByOptions={sortByOptions}
      />

      <PaymentLinksTableSection
        t={t}
        table={table}
        isTableLoading={isTableLoading}
        total={total}
        rowsPerPage={rowsPerPage}
        theme={theme}
        onPageSizeChange={handlePageSizeChange}
      />

      <PaymentLinksDialogs
        t={t}
        theme={theme}
        locale={locale}
        statusLabelMap={statusLabelMap}
        statusColorMap={statusColorMap}
        handleCopy={handleCopy}
        createOpen={createOpen}
        setCreateOpen={setCreateOpen}
        createValues={createValues}
        setCreateValues={setCreateValues}
        createErrors={createErrors}
        isCreating={isCreating}
        onCreateSubmit={handleCreateSubmit}
        editOpen={editOpen}
        setEditOpen={setEditOpen}
        editValues={editValues}
        setEditValues={setEditValues}
        isUpdating={isUpdating}
        onUpdateSubmit={handleUpdateSubmit}
        viewOpen={viewOpen}
        setViewOpen={setViewOpen}
        activeLink={activeLink}
        cancelOpen={cancelOpen}
        setCancelOpen={setCancelOpen}
        isCancelling={isCancelling}
        onCancelSubmit={handleCancelSubmit}
        deleteOpen={deleteOpen}
        setDeleteOpen={setDeleteOpen}
        isDeleting={isDeleting}
        onDeleteSubmit={handleDeleteSubmit}
        createdDialogOpen={createdDialogOpen}
        setCreatedDialogOpen={setCreatedDialogOpen}
        createdLinkUrl={createdLinkUrl}
      />
    </Stack>
  )
}

export default PaymentLinksView
