'use client'

import { useEffect, useState } from 'react'
import { toast } from 'react-toastify'
import { Button } from 'flowbite-react'
import { useRouter, useSearchParams } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'

import * as PaginationConstant from '@/lib/constants/pagination'
import { paginationDefaultData } from '@/lib/data/pagination'
import * as marketplaceServices from '@/lib/services/marketplace-services'
import buttonTheme from '@/lib/themes/button'
import Pagination from '@/lib/components/Pagination'
import { constructSearchURL } from '@/lib/utils/url'
import { handleApiError } from '@/lib/utils/error-handler'
import { Marketplace, MarketplaceFormValues, SearchFormProps } from './types'
import { marketplaceFormSchema } from './schema'
import SearchForm from './partials/SearchForm'
import DataTable from './partials/DataTable'
import ModalForm from './partials/ModalForm'
import ModalDeleteMarketplace from './partials/ModalDeleteMarketplace'
import { useAuth } from '@/lib/context/AuthContext'

export default function MainContent() {
  const router = useRouter()
  const { user } = useAuth()
  const searchParams = useSearchParams()
  const [selectedMarketplace, setSelectedMarketplace] =
    useState<Marketplace | null>(null)
  const [marketplaces, setMarketplaces] = useState<Pagination<Marketplace>>(
    paginationDefaultData,
  )
  const [refreshTrigger, setRefreshTrigger] = useState(0)
  const [searchForm, setSearchForm] = useState<SearchFormProps>({
    searching: false,
    params: {
      search: searchParams.get('search') || '',
      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 [marketplaceModal, setMarketplaceModal] = useState<
    ModalState<Marketplace>
  >({
    isOpened: false,
    processing: false,
    type: 'create',
    data: null,
  })

  // Form for create/edit
  const marketplaceForm = useForm<MarketplaceFormValues>({
    resolver: yupResolver(marketplaceFormSchema),
    defaultValues: {
      name: '',
    },
  })

  function handleCloseModal() {
    marketplaceForm.reset()
    setMarketplaceModal((prev) => ({ ...prev, isOpened: false, data: null }))
    setSelectedMarketplace(null)
  }

  async function handleSubmitMarketplace(formValues: MarketplaceFormValues) {
    const isEditMode = marketplaceModal.type === 'edit'
    setMarketplaceModal((prev) => ({ ...prev, processing: true }))

    try {
      let marketplace: Marketplace

      if (isEditMode && selectedMarketplace?.id) {
        // Edit existing marketplace
        marketplace = await marketplaceServices.updateMarketplace(
          selectedMarketplace.id,
          formValues,
        )

        // Update the marketplace in the current data
        setMarketplaces((prev) => ({
          ...prev,
          data: prev.data.map((item) =>
            item.id === selectedMarketplace.id ? marketplace : item,
          ),
        }))

        toast.success('Marketplace updated successfully!')
      } else {
        // Create new marketplace
        marketplace = await marketplaceServices.createMarketplace(formValues)

        // Add to the beginning of current data
        const totalData = marketplaces.total + 1
        const lastPage = Math.ceil(totalData / marketplaces.per_page)
        const prevMarketplaceData =
          marketplaces?.data.length < marketplaces.per_page
            ? marketplaces.data
            : marketplaces.data.slice(0, -1)

        setMarketplaces((prev) => ({
          ...prev,
          last_page: lastPage,
          total: totalData,
          from: prev.from ? prev.from : 1,
          to: totalData < prev.per_page ? totalData : prev.per_page,
          data: [marketplace, ...prevMarketplaceData],
        }))

        toast.success('Marketplace created successfully!')
      }

      marketplaceForm.reset()
      setMarketplaceModal((prev) => ({
        ...prev,
        isOpened: false,
        processing: false,
      }))
      setSelectedMarketplace(null)
    } catch (err) {
      handleApiError(
        err,
        'Oops! Something went wrong. Please try again later.',
        (formErrors) => {
          Object.keys(formErrors).forEach((field) => {
            marketplaceForm.setError(field as keyof MarketplaceFormValues, {
              type: 'manual',
              message: formErrors[field][0],
            })
          })
        },
      )
    } finally {
      setMarketplaceModal((prev) => ({ ...prev, processing: false }))
    }
  }

  async function handleDeleteMarketplace() {
    if (!selectedMarketplace?.id) return

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

    try {
      await marketplaceServices.deleteMarketplace(selectedMarketplace.id)

      const updatedMarketplaces = (await marketplaceServices.getMarketplaces({
        search: searchParams.get('search') || '',
        page: Number(searchParams.get('page') ?? 1),
        limit: Number(
          searchParams.get('limit') ?? PaginationConstant.MIN_DATA_PER_PAGE,
        ),
      })) as Pagination<Marketplace>

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

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

        return router.push(
          constructSearchURL('/marketplaces', {
            ...searchForm.params,
            page: prevPage,
            limit: marketplaces.per_page,
          }),
        )
      }

      setMarketplaces(updatedMarketplaces)
      setSelectedMarketplace(null)
      setMarketplaceModal((prev) => ({
        ...prev,
        isOpened: false,
        processing: false,
      }))

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

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

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

    const newUrl = constructSearchURL('/marketplaces', {
      ...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,
        },
      }))

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

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

    return router.push(
      constructSearchURL('/marketplaces', {
        ...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,
        },
      }))

      return router.push(
        constructSearchURL('/marketplaces', {
          ...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,
      },
    }))

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

  useEffect(() => {
    setIsLoadingInitial(true)

    marketplaceServices
      .getMarketplaces({
        search: searchParams.get('search') || '',
        page: Number(searchParams.get('page') ?? 1),
        limit: Number(
          searchParams.get('limit') ?? PaginationConstant.MIN_DATA_PER_PAGE,
        ),
      })
      .then((data) => {
        setMarketplaces(data as Pagination<Marketplace>)
      })
      .catch(() => {
        toast.error('Failed to load marketplaces. 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">Marketplaces</h1>
        <p className="font-medium text-slate-500">
          Following are the list of marketplaces. You can manage them here.
        </p>

        <Button
          theme={buttonTheme.button}
          color="default"
          className="mt-4"
          onClick={() => {
            setMarketplaceModal({
              type: 'create',
              isOpened: true,
              processing: false,
              data: null,
            })
          }}
        >
          Create Marketplace
        </Button>
      </div>

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

      <DataTable
        marketplaces={searchForm.searching ? [] : marketplaces.data}
        isLoading={isLoadingInitial}
        setModal={setMarketplaceModal}
        setMarketplace={setSelectedMarketplace}
        onEdit={(marketplace: Marketplace) => {
          marketplaceForm.reset({
            name: marketplace.name,
          })
        }}
      />

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

      <ModalForm
        isOpen={
          marketplaceModal.isOpened &&
          (marketplaceModal.type === 'create' ||
            marketplaceModal.type === 'edit')
        }
        marketplaceForm={marketplaceForm}
        isProcessing={marketplaceModal.processing || false}
        onClose={handleCloseModal}
        onSubmit={handleSubmitMarketplace}
        mode={marketplaceModal.type === 'edit' ? 'edit' : 'create'}
      />

      <ModalDeleteMarketplace
        isOpen={marketplaceModal.isOpened && marketplaceModal.type === 'delete'}
        marketplace={selectedMarketplace}
        isDeleting={marketplaceModal.processing || false}
        onClose={() =>
          setMarketplaceModal((prev) => ({ ...prev, isOpened: false }))
        }
        onConfirm={handleDeleteMarketplace}
      />
    </section>
  )
}
