'use client'

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

import { paginationDefaultData } from '@/lib/data/pagination'
import * as PaginationConstant from '@/lib/constants/pagination'
import { Bank, bankFormSchema, BankFormValues, SearchFormProps } from './types'
import * as bankServices from '@/lib/services/bank-services'
import { handleApiError } from '@/lib/utils/error-handler'
import { constructSearchURL } from '@/lib/utils/url'
import buttonTheme from '@/lib/themes/button'
import Pagination from '@/lib/components/Pagination'
import SearchForm from './partials/SearchForm'
import DataTable from './partials/DataTable'
import ModalForm from './partials/ModalForm'
import ModalDeleteBank from './partials/ModalDeleteBank'
import { useAuth } from '@/lib/context/AuthContext'

export default function MainContent() {
  const router = useRouter()
  const { user } = useAuth()
  const [selectedBank, setSelectedBank] = useState<Bank | null>(null)
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [isDeletingBank, setIsDeletingBank] = useState(false)
  const [refreshTrigger, setRefreshTrigger] = useState(0)
  const [bankModal, setBankModal] = useState<ModalState>({
    isOpened: false,
    type: 'create',
  })
  const searchParams = useSearchParams()
  const [banks, setBanks] = useState<Pagination<Bank>>(paginationDefaultData)
  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 bankForm = useForm<BankFormValues>({
    resolver: yupResolver(bankFormSchema),
    defaultValues: {
      bank_name: '',
      short_name: '',
      logo: null,
    },
  })

  function handleOpenCreateModal() {
    bankForm.reset({
      bank_name: '',
      short_name: '',
      logo: null,
    })
    setBankModal({
      isOpened: true,
      type: 'create',
    })
  }

  useEffect(() => {
    if (bankModal.type === 'edit' && selectedBank) {
      bankForm.reset({
        bank_name: selectedBank.bank_name,
        short_name: selectedBank.short_name,
        logo: null,
      })
    }
  }, [bankModal, selectedBank, bankForm])

  function handleCloseModal() {
    bankForm.reset()
    setBankModal({
      isOpened: false,
      type: 'create',
    })
    setSelectedBank(null)
  }

  async function handleCreateBank(data: BankFormValues) {
    try {
      setIsSubmitting(true)
      const newBank = await bankServices.createBank(data)

      const totalData = banks.total + 1
      const lastPage = Math.ceil(totalData / banks.per_page)
      const prevBankData =
        banks.data.length < banks.per_page
          ? banks.data
          : banks.data.slice(0, -1)

      // Add new bank to the beginning of the list
      setBanks((prevBanks) => ({
        ...prevBanks,
        last_page: lastPage,
        total: prevBanks.total + 1,
        from: prevBanks.from ? prevBanks.from : 1,
        to: totalData < prevBanks.per_page ? totalData : prevBanks.per_page,
        data: [newBank, ...prevBankData],
      }))

      toast.success(`Bank ${data.bank_name} created successfully`)
      handleCloseModal()
    } catch (error) {
      handleApiError(error, 'Failed to create bank', (formErrors) => {
        Object.keys(formErrors).forEach((field) => {
          bankForm.setError(field as keyof BankFormValues, {
            type: 'manual',
            message: formErrors[field][0],
          })
        })
      })
    } finally {
      setIsSubmitting(false)
    }
  }

  async function handleUpdateBank(data: BankFormValues) {
    if (!selectedBank) return

    try {
      setIsSubmitting(true)

      const updatedBank = await bankServices.updateBank(selectedBank.id, data)

      // Update bank in the list
      setBanks((prev) => ({
        ...prev,
        data: prev.data.map((bank) =>
          bank.id === selectedBank.id ? updatedBank : bank,
        ),
      }))

      toast.success(`Bank ${data.bank_name} updated successfully`)
      handleCloseModal()
    } catch (error) {
      handleApiError(error, 'Failed to update bank', (formErrors) => {
        Object.keys(formErrors).forEach((field) => {
          bankForm.setError(field as keyof BankFormValues, {
            type: 'manual',
            message: formErrors[field][0],
          })
        })
      })
    } finally {
      setIsSubmitting(false)
    }
  }

  async function handleDeleteBank() {
    if (!selectedBank) return

    try {
      setIsDeletingBank(true)
      await bankServices.deleteBank(selectedBank.id)

      bankServices
        .getBanks({
          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,
        })
        .then((updatedBanks) => {
          if (
            (updatedBanks as Pagination<Bank>).data.length === 0 &&
            (updatedBanks as Pagination<Bank>).current_page > 1
          ) {
            const prevPage = (updatedBanks as Pagination<Bank>).current_page - 1

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

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

          setBanks(updatedBanks as Pagination<Bank>)
          setSelectedBank(null)
          setBankModal({
            ...bankModal,
            type: 'delete',
            isOpened: false,
          })

          toast.success(`Bank ${selectedBank.bank_name} deleted successfully`)
          handleCloseDeleteModal()
        })
    } catch (error) {
      handleApiError(error, 'Failed to delete bank')
    } finally {
      setIsDeletingBank(false)
    }
  }

  function handleCloseDeleteModal() {
    setBankModal({
      isOpened: false,
      type: 'create',
    })
    setSelectedBank(null)
  }

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

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

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

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

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

    return router.push(newUrl)
  }

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

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

  // Fetch banks
  useEffect(() => {
    setIsLoadingInitial(true)

    bankServices
      .getBanks({
        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,
      })
      .then((data) => {
        setBanks(data as Pagination<Bank>)
      })
      .finally(() => {
        setIsLoadingInitial(false)
        setSearchForm((prev) => ({
          ...prev,
          searching: false,
        }))
      })
  }, [refreshTrigger, searchParams])

  return (
    <section className="mt-8">
      <div>
        <h1 className="text-3xl font-semibold text-black mb-2">
          Banks Management
        </h1>
        <p className="text-gray-600">
          Following are the list of banks. You can manage them here.
        </p>

        {user?.role === 'super_admin' && (
          <Button
            className="mt-4"
            color="default"
            theme={buttonTheme.button}
            onClick={handleOpenCreateModal}
          >
            <FiPlus className="mr-2 h-5 w-5" />
            Create Bank
          </Button>
        )}
      </div>

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

      <DataTable
        banks={banks.data}
        isLoading={isLoadingInitial}
        setSelectedBank={setSelectedBank}
        setModal={setBankModal}
      />

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

      <ModalForm
        isOpen={bankModal.isOpened && bankModal.type !== 'delete'}
        mode={bankModal.type as 'create' | 'edit'}
        isSubmitting={isSubmitting}
        form={bankForm}
        originalLogoUrl={selectedBank?.logo_url}
        onClose={handleCloseModal}
        onSubmit={
          bankModal.type === 'create' ? handleCreateBank : handleUpdateBank
        }
      />

      <ModalDeleteBank
        isOpen={bankModal.isOpened && bankModal.type === 'delete'}
        bank={selectedBank}
        isDeleting={isDeletingBank}
        onClose={handleCloseDeleteModal}
        onConfirm={handleDeleteBank}
      />
    </section>
  )
}
