'use client'

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

import * as PaginationConstant from '@/lib/constants/pagination'
import { paginationDefaultData } from '@/lib/data/pagination'
import buttonTheme from '@/lib/themes/button'
import Pagination from '@/lib/components/Pagination'
import { constructSearchURL } from '@/lib/utils/url'
import { useAuth } from '@/lib/context/AuthContext'
import * as affiliatePartnerServices from '@/lib/services/affiliate-partner-services'
import { AffiliatePartner } from '@/lib/types/partner'
import { SearchFormProps } from './types'
import SearchForm from './partials/SearchForm'
import DataTable from './partials/DataTable'
import ModalDeleteAffiliatePartner from './partials/ModalDeleteAffiliatePartner'

export default function MainContent() {
  const router = useRouter()
  const searchParams = useSearchParams()
  const [selectedAffiliatePartner, setSelectedAffiliatePartner] =
    useState<AffiliatePartner | null>(null)
  const [affiliatePartners, setAffiliatePartners] = useState<
    Pagination<AffiliatePartner>
  >(paginationDefaultData)
  const [refreshTrigger, setRefreshTrigger] = useState(0)
  const [searchForm, setSearchForm] = useState<SearchFormProps>({
    searching: false,
    params: {
      search: searchParams.get('search') || '',
      affiliate_category_id: searchParams.get('affiliate_category_id')
        ? Number(searchParams.get('affiliate_category_id'))
        : undefined,
      affiliate_experience: searchParams.get('affiliate_experience') || '',
      affiliate_level_id: searchParams.get('affiliate_level_id')
        ? Number(searchParams.get('affiliate_level_id'))
        : undefined,
      guest_market: searchParams.get('guest_market') || '',
      page: searchParams.get('page') ? Number(searchParams.get('page')) : 1,
      limit: searchParams.get('limit')
        ? Number(searchParams.get('limit'))
        : PaginationConstant.MIN_DATA_PER_PAGE,
      has_links: searchParams.get('has_links')
        ? searchParams.get('has_links') === 'true'
        : undefined,
      merchant_id: searchParams.get('merchant_id')
        ? Number(searchParams.get('merchant_id'))
        : undefined,
    },
  })
  const [isLoadingInitial, setIsLoadingInitial] = useState(true)
  const [affiliatePartnerModal, setAffiliatePartnerModal] = useState<
    ModalState<AffiliatePartner>
  >({
    isOpened: false,
    processing: false,
    type: 'delete',
    data: null,
  })
  const { user } = useAuth()

  async function handleConfirmDelete() {
    if (!selectedAffiliatePartner?.id) return

    setAffiliatePartnerModal((prev) => ({ ...prev, processing: true }))

    try {
      await affiliatePartnerServices.deleteAffiliatePartner(
        selectedAffiliatePartner.id,
      )

      const updatedAffiliatePartners =
        (await affiliatePartnerServices.getAffiliatePartners({
          search: searchParams.get('search') || '',
          affiliate_category_id: searchParams.get('affiliate_category_id')
            ? Number(searchParams.get('affiliate_category_id'))
            : undefined,
          affiliate_experience: searchParams.get('affiliate_experience') || '',
          affiliate_level_id: searchParams.get('affiliate_level_id')
            ? Number(searchParams.get('affiliate_level_id'))
            : undefined,
          guest_market: searchParams.get('guest_market') || '',
          page: Number(searchParams.get('page') ?? 1),
          limit: Number(
            searchParams.get('limit') ?? PaginationConstant.MIN_DATA_PER_PAGE,
          ),
          has_links: searchParams.get('has_links')
            ? searchParams.get('has_links') === 'true'
            : undefined,
          merchant_id: searchParams.get('merchant_id')
            ? Number(searchParams.get('merchant_id'))
            : undefined,
        })) as Pagination<AffiliatePartner>

      if (
        updatedAffiliatePartners.data.length === 0 &&
        updatedAffiliatePartners.current_page > 1
      ) {
        const prevPage = updatedAffiliatePartners.current_page - 1

        setSearchForm((prev) => ({
          ...prev,
          params: {
            ...prev.params,
            page: prevPage,
            limit: updatedAffiliatePartners.per_page,
          },
        }))

        // Directly pass the updated state value
        return router.push(
          constructSearchURL('/affiliate-partners', {
            ...searchForm.params,
            page: prevPage,
            limit: updatedAffiliatePartners.per_page,
          }),
        )
      }

      setAffiliatePartners(updatedAffiliatePartners)
      setSelectedAffiliatePartner(null)
      setAffiliatePartnerModal({
        ...affiliatePartnerModal,
        type: 'delete',
        isOpened: false,
        processing: false,
      })

      toast.success('Affiliate partner deleted successfully!')
    } catch {
      toast.error(
        'Oops! something went wrong on delete affiliate partner data. Please try again later',
      )
    }
  }

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

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

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

    // Check if the URL would be the same (search with same parameters)
    const currentUrl = `${window.location.pathname}${window.location.search}`

    if (currentUrl === newUrl) {
      // If URL is the same, trigger a refresh instead of navigation
      setRefreshTrigger((prev) => prev + 1)
      return
    }

    return router.push(newUrl)
  }

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

      // Directly pass the updated state value
      return router.push(
        constructSearchURL('/affiliate-partners', {
          ...searchForm.params,
          page: 1,
        }),
      )
    }

    setSearchForm((prev) => ({
      ...prev,
      params: {
        ...prev.params,
        page,
      },
    }))

    // Directly pass the updated state value
    return router.push(
      constructSearchURL('/affiliate-partners', {
        ...searchForm.params,
        page,
      }),
    )
  }

  function handleLimitChange(limit: number) {
    if (isNaN(Number(limit))) {
      setSearchForm((prev) => ({
        ...prev,
        params: {
          ...prev.params,
          page: 1,
          limit: PaginationConstant.MIN_DATA_PER_PAGE,
        },
      }))

      // Directly pass the updated state value
      return router.push(
        constructSearchURL('/affiliate-partners', {
          ...searchForm.params,
          page: 1,
          limit: PaginationConstant.MIN_DATA_PER_PAGE,
        }),
      )
    }

    limit =
      Number(limit) < PaginationConstant.MIN_DATA_PER_PAGE ||
      Number(limit) > PaginationConstant.MAX_DATA_PER_PAGE
        ? PaginationConstant.MIN_DATA_PER_PAGE
        : limit

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

    // Directly pass the updated state value
    return router.push(
      constructSearchURL('/affiliate-partners', {
        ...searchForm.params,
        page: 1,
        limit,
      }),
    )
  }

  useEffect(() => {
    setIsLoadingInitial(true)

    affiliatePartnerServices
      .getAffiliatePartners({
        search: searchParams.get('search') || '',
        guest_market: searchParams.get('guest_market') || '',
        page: Number(searchParams.get('page') ?? 1),
        affiliate_category_id: searchParams.get('affiliate_category_id')
          ? Number(searchParams.get('affiliate_category_id'))
          : undefined,
        affiliate_experience: searchParams.get('affiliate_experience') || '',
        affiliate_level_id: searchParams.get('affiliate_level_id')
          ? Number(searchParams.get('affiliate_level_id'))
          : undefined,
        limit: Number(
          searchParams.get('limit') ?? PaginationConstant.MIN_DATA_PER_PAGE,
        ),
        has_links: searchParams.get('has_links')
          ? searchParams.get('has_links') === 'true'
          : undefined,
        merchant_id: searchParams.get('merchant_id')
          ? Number(searchParams.get('merchant_id'))
          : undefined,
      })
      .then((data) => {
        setAffiliatePartners(data as Pagination<AffiliatePartner>)
      })
      .catch(() => {
        toast.error('Failed to load affiliate partners. Please try again.')
      })
      .finally(() => {
        setIsLoadingInitial(false)
        setSearchForm((prev) => ({ ...prev, searching: false }))
      })
  }, [searchParams, refreshTrigger])

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

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

        <Button
          theme={buttonTheme.button}
          color="default"
          className="mt-4"
          onClick={() => {
            router.push('/affiliate-partners/create')
          }}
        >
          Create Affiliate Partner
        </Button>
      </div>

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

      <DataTable
        affiliatePartners={searchForm.searching ? [] : affiliatePartners.data}
        isLoading={isLoadingInitial}
        setModal={setAffiliatePartnerModal}
        setAffiliatePartner={setSelectedAffiliatePartner}
      />

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

      <ModalDeleteAffiliatePartner
        isOpen={
          affiliatePartnerModal.isOpened &&
          affiliatePartnerModal.type === 'delete'
        }
        affiliatePartner={selectedAffiliatePartner}
        isDeleting={
          affiliatePartnerModal.processing &&
          affiliatePartnerModal.type === 'delete'
        }
        onClose={() =>
          setAffiliatePartnerModal({
            ...affiliatePartnerModal,
            isOpened: false,
          })
        }
        onConfirm={handleConfirmDelete}
      />
    </section>
  )
}
