'use client'

import { useEffect, useState } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { toast } from 'react-toastify'
import { Button } from 'flowbite-react'

import { useAuth } from '@/lib/context/AuthContext'
import { paginationDefaultData } from '@/lib/data/pagination'
import * as PaginationConstant from '@/lib/constants/pagination'
import { constructSearchURL } from '@/lib/utils/url'
import * as withdrawalServices from '@/lib/services/withdrawal-services'
import Pagination from '@/lib/components/Pagination'
import { useWithdrawalBroadcast } from '@/lib/hooks/useWithdrawalBroadcast'
import buttonTheme from '@/lib/themes/button'
import { SearchFormProps, Withdrawal } from './types'
import SearchForm from './partials/SearchForm'
import TransferProofModal from './partials/TransferProofModal'
import DataTable from './partials/DataTable'
import CreateReportModal from './partials/CreateReportModal'

export default function MainContent() {
  const router = useRouter()
  const { user } = useAuth()
  const searchParams = useSearchParams()
  const [selectedWithdrawal, setSelectedWithdrawal] =
    useState<Withdrawal | null>(null)
  const [withdrawals, setWithdrawals] = useState<Pagination<Withdrawal>>(
    paginationDefaultData,
  )
  const [refreshTrigger, setRefreshTrigger] = useState(0)
  const [searchForm, setSearchForm] = useState<SearchFormProps>({
    searching: false,
    params: {
      status: (searchParams.get('status') as Withdrawal['status']) || '',
      code: searchParams.get('code') || '',
      startDate: searchParams.get('startDate') || '',
      endDate: searchParams.get('endDate') || '',
      partnerId: searchParams.get('partnerId')
        ? Number(searchParams.get('partnerId'))
        : undefined,
      page: searchParams.get('page') ? Number(searchParams.get('page')) : 1,
      limit: searchParams.get('limit')
        ? Number(searchParams.get('limit'))
        : PaginationConstant.MIN_DATA_PER_PAGE,
    },
  })
  const [isLoadingInitial, setIsLoadingInitial] = useState(true)
  const [transferProofModal, setTransferProofModal] = useState<ModalState>({
    type: 'view',
    isOpened: false,
  })
  const [reportModal, setReportModal] = useState<ModalState>({
    type: 'create',
    isOpened: false,
  })

  async function handleSearchSubmit(e?: React.FormEvent) {
    e?.preventDefault()

    setSearchForm((prev) => ({ ...prev, searching: true }))
    setWithdrawals(paginationDefaultData)

    const newUrl = constructSearchURL('/withdrawals', {
      ...searchForm.params,
      page: 1,
    })

    const currentUrl = `${window.location.pathname}${window.location.search}`

    if (currentUrl === newUrl) {
      setRefreshTrigger((prev) => prev + 1)
      return
    }

    return router.push(newUrl)
  }

  async function handlePageChange(page: number) {
    setSearchForm((prev) => ({
      ...prev,
      params: {
        ...prev.params,
        page,
      },
    }))

    return router.push(
      constructSearchURL('/withdrawals', {
        ...searchForm.params,
        page,
      }),
    )
  }

  function handleLimitChange(limit: number) {
    setSearchForm((prev) => ({
      ...prev,
      params: {
        ...prev.params,
        page: 1,
        limit,
      },
    }))

    return router.push(
      constructSearchURL('/withdrawals', {
        ...searchForm.params,
        page: 1,
        limit,
      }),
    )
  }

  function handleViewTransferProof(withdrawal: Withdrawal) {
    setSelectedWithdrawal(withdrawal)

    setTransferProofModal({
      type: 'view',
      isOpened: true,
    })
  }

  useEffect(() => {
    setIsLoadingInitial(true)

    withdrawalServices
      .getWithdrawals({
        status: (searchParams.get('status') as Withdrawal['status']) || '',
        code: searchParams.get('code') || '',
        startDate: searchParams.get('startDate') || '',
        endDate: searchParams.get('endDate') || '',
        partnerId: searchParams.get('partnerId')
          ? Number(searchParams.get('partnerId'))
          : undefined,
        page: Number(searchParams.get('page') ?? 1),
        limit: Number(
          searchParams.get('limit') ?? PaginationConstant.MIN_DATA_PER_PAGE,
        ),
      })
      .then((data) => {
        setWithdrawals(data as Pagination<Withdrawal>)
      })
      .catch(() => {
        toast.error('Failed to load withdrawals. Please try again.')
      })
      .finally(() => {
        setIsLoadingInitial(false)
        setSearchForm((prev) => ({ ...prev, searching: false }))
      })
  }, [searchParams, refreshTrigger])

  // Withdrawal Broadcast Handlers
  useWithdrawalBroadcast({
    onWithdrawalRequest: () => {
      if (user?.role === 'manager' || user?.role === 'accounting') {
        setRefreshTrigger((prev) => prev + 1)
      }
    },
    onWithdrawalCancelled: () => {
      if (user?.role === 'manager' || user?.role === 'accounting') {
        setRefreshTrigger((prev) => prev + 1)
      }
    },
  })

  // Authorize User
  useEffect(() => {
    if (user && user.role !== 'manager' && user.role !== 'accounting') {
      router.replace('/')
    }
  }, [user, router])

  return (
    <section className="mt-8">
      <div>
        <h1 className="text-3xl font-semibold text-black mb-2">Withdrawals</h1>
        <p className="font-medium text-slate-500">
          Following are the list of withdrawals. You can manage them here.
        </p>

        <Button
          theme={buttonTheme.button}
          color="green"
          className="mt-4"
          onClick={() => {
            setReportModal({ isOpened: true, type: 'create' })
          }}
        >
          Create Report
        </Button>
      </div>

      <SearchForm
        searchForm={searchForm}
        handleSearch={handleSearchSubmit}
        setSearchForm={setSearchForm}
      />

      <DataTable
        withdrawals={searchForm.searching ? [] : withdrawals.data}
        isLoading={isLoadingInitial}
        onViewTransferProof={handleViewTransferProof}
      />

      {!isLoadingInitial && (
        <Pagination
          currentPage={withdrawals.current_page}
          lastPage={withdrawals.last_page}
          limit={
            searchParams.get('limit')
              ? Number(searchParams.get('limit'))
              : PaginationConstant.MIN_DATA_PER_PAGE
          }
          from={withdrawals.from}
          to={withdrawals.to}
          total={withdrawals.total}
          handlePageChange={handlePageChange}
          handleLimitChange={handleLimitChange}
        />
      )}

      <TransferProofModal
        withdrawal={selectedWithdrawal}
        transferProofModal={transferProofModal}
        setTransferProofModal={setTransferProofModal}
      />

      <CreateReportModal
        reportModal={reportModal}
        setReportModal={setReportModal}
      />
    </section>
  )
}
