'use client';

import { ChangeEventHandler, useEffect, useMemo, useState } from 'react';
import { usePathname } from 'next/navigation';
import { useUiStore } from '@/stores/ui/ui.store';
import useSWR from 'swr';
import {
  CellContext,
  ColumnDef,
  Row,
  SortingState,
} from '@tanstack/react-table';
import toast from 'react-hot-toast';

import { Icon } from '@iconify/react';
import Table from '@/components/Table';
import Button from '@/components/Button';
import { useModal } from '@/components/Modal';
import CheckboxInput from '@/components/input/CheckboxInput';
import RequirePermission from '@/components/helper/RequirePermission';
import PopoverButton from '@/components/popover/PopoverButton';
import PopoverContent from '@/components/popover/PopoverContent';
import Dropdown from '@/components/Dropdown';
import StatusBadge from '@/components/helper/StatusBadge';
import TransferToLayingFilterModal from '@/components/pages/production/transfer-to-laying/TransferToLayingFilterModal';
import TransferToLayingConfirmationModal from '@/components/pages/production/transfer-to-laying/TransferToLayingConfirmationModal';
import TransferToLayingTableSkeleton from '@/components/pages/production/transfer-to-laying/skeleton/TransferToLayingTableSkeleton';

import { TransferToLaying } from '@/types/api/production/transfer-to-laying';
import { TransferToLayingFilterValues } from '@/components/pages/production/transfer-to-laying/filter/TransferToLayingFilter';
import { OptionType } from '@/components/input/SelectInput';
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
import { cn, formatDate, formatNumber } from '@/lib/helper';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { Color } from '@/types/theme';
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
import ButtonFilter from '@/components/helper/ButtonFilter';

const RowOptionsMenu = ({
  props,
  popoverPosition = 'bottom',

  deleteClickHandler,
}: {
  props: CellContext<TransferToLaying, unknown>;
  popoverPosition: 'bottom' | 'top';
  deleteClickHandler: () => void;
}) => {
  const showEditButton = props.row.original.approval.action !== 'APPROVED';

  const showDeleteButton =
    props.row.original.approval.action === 'APPROVED' ||
    props.row.original.approval.step_name.toLowerCase() === 'pengajuan';

  const popoverId = `transferToLaying#${props.row.original.id}`;
  const popoverAnchorName = `--anchor-transferToLaying#${props.row.original.id}`;

  return (
    <div className='relative'>
      <PopoverButton
        tabIndex={0}
        variant='ghost'
        color='none'
        popoverTarget={popoverId}
        anchorName={popoverAnchorName}
      >
        <Icon icon='material-symbols:more-vert' width={16} height={16} />
      </PopoverButton>

      <PopoverContent
        id={popoverId}
        anchorName={popoverAnchorName}
        position={popoverPosition === 'bottom' ? 'bottom-start' : 'left'}
        className='w-full max-w-40 rounded-xl border border-base-content/5 shadow-sm'
      >
        <div className='flex flex-col bg-base-100 rounded-xl'>
          <RequirePermission permissions='lti.production.transfer_to_laying.detail'>
            <Button
              href={`/production/transfer-to-laying/?action=detail&id=${props.row.original.id}`}
              variant='ghost'
              color='none'
              className='p-3 justify-start text-sm font-semibold w-full'
            >
              <Icon icon='heroicons:eye' width={20} height={20} />
              View Details
            </Button>
          </RequirePermission>

          {showEditButton && (
            <RequirePermission permissions='lti.production.transfer_to_laying.update'>
              <Button
                href={`/production/transfer-to-laying/?action=edit&id=${props.row.original.id}`}
                variant='ghost'
                color='none'
                className='p-3 justify-start text-sm font-semibold w-full'
              >
                <Icon icon='heroicons:pencil-square' width={20} height={20} />
                Edit
              </Button>
            </RequirePermission>
          )}

          {showDeleteButton && (
            <RequirePermission permissions='lti.production.transfer_to_laying.delete'>
              <hr className='mx-3 border-base-content/10 h-px' />
              <Button
                onClick={deleteClickHandler}
                variant='ghost'
                color='error'
                className='p-3 justify-start text-sm font-semibold w-full'
              >
                <Icon icon='heroicons:trash' width={20} height={20} />
                Delete
              </Button>
            </RequirePermission>
          )}
        </div>
      </PopoverContent>
    </div>
  );
};

const TransferToLayingsTable = () => {
  const { searchValue, setSearchValue, setTableState } = useUiStore();
  const pathname = usePathname();

  const {
    state: tableFilterState,
    updateFilter,
    setPage,
    setPageSize,
    toQueryString: getTableFilterQueryString,
  } = useTableFilter({
    initial: {
      search: '',
      startDate: '',
      endDate: '',
      flockSource: '',
      flockDestination: '',
      status: '',
      filter_by: '',
      sort_by: '',
      flockSourceNames: '',
      flockDestinationNames: '',
    },
    paramMap: {
      page: 'page',
      pageSize: 'limit',
      startDate: 'start_date',
      endDate: 'end_date',
      flockSource: 'flock_source',
      flockDestination: 'flock_destination',
      status: 'status',
      filter_by: 'filter_by',
      sort_by: 'sort_by',
    },
    excludeKeysFromUrl: ['flockSourceNames', 'flockDestinationNames'],
    persist: true,
    storeName: 'transfer-to-laying-table',
  });

  const {
    data: transferToLayings,
    isLoading,
    mutate: refreshTransferToLayings,
  } = useSWR(
    `${TransferToLayingApi.basePath}${getTableFilterQueryString()}`,
    TransferToLayingApi.getAllFetcher
  );

  const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
    useState(false);

  // Modal hooks
  const filterModal = useModal();
  const deleteModal = useModal();
  const approveModal = useModal();
  const rejectModal = useModal();

  const [selectedTransferToLaying, setSelectedTransferToLaying] = useState<
    TransferToLaying | undefined
  >(undefined);

  // Modal loading state
  const [isDeleteLoading, setIsDeleteLoading] = useState(false);
  const [isApproveLoading, setIsApproveLoading] = useState(false);
  const [isRejectLoading, setIsRejectLoading] = useState(false);

  const [sorting, setSorting] = useState<SortingState>([]);
  const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
  const selectedRowIds = Object.keys(rowSelection).map((item) =>
    parseInt(item)
  );

  const transferToLayingsColumns: ColumnDef<TransferToLaying>[] = [
    {
      id: 'select',
      header: ({ table }) => (
        <div className='w-full flex flex-row justify-center'>
          <CheckboxInput
            name='allRow'
            checked={table.getIsAllRowsSelected()}
            indeterminate={table.getIsSomeRowsSelected()}
            onChange={table.getToggleAllRowsSelectedHandler()}
          />
        </div>
      ),
      cell: ({ row }) => {
        const isCheckboxDisabled =
          !row.getCanSelect() ||
          row.original.approval.action === 'APPROVED' ||
          row.original.approval.action === 'REJECTED';

        return (
          <div>
            <CheckboxInput
              name='row'
              checked={row.getIsSelected()}
              disabled={isCheckboxDisabled}
              indeterminate={row.getIsSomeSelected()}
              onChange={row.getToggleSelectedHandler()}
            />
          </div>
        );
      },
    },
    {
      accessorKey: 'transfer_date',
      header: 'Tanggal Transfer',
      cell: (props) => formatDate(props.getValue() as string, 'DD MMM YYYY'),
    },
    {
      accessorKey: 'transfer_number',
      header: 'No. Transfer',
    },
    {
      accessorKey: 'flock_source',
      header: 'Flock Asal',
      cell: (props) => props.row.original.from_project_flock.flock_name,
    },
    {
      accessorKey: 'flock_destination',
      header: 'Flock Tujuan',
      cell: (props) => props.row.original.to_project_flock.flock_name,
    },
    {
      accessorKey: 'usage_qty',
      header: 'Kuantitas',
      cell: (props) => {
        const totalQuantity = props.row.original.targets.reduce(
          (total, target) => total + target.qty,
          0
        );

        return formatNumber(totalQuantity, 'en-US');
      },
    },
    {
      accessorKey: 'notes',
      header: 'Alasan Transfer',
      enableSorting: false,
      cell: (props) => {
        return (
          <span title={props.row.original.notes} className='line-clamp-1'>
            {props.row.original.notes}
          </span>
        );
      },
    },
    {
      header: 'Status',
      cell: (props) => {
        const isLatestApprovalRejected =
          props.row.original.approval.action === 'REJECTED';
        let latestApprovalStepName = props.row.original.approval.step_name;

        let badgeColor: Color = 'neutral';

        switch (latestApprovalStepName.toLowerCase()) {
          case 'pengajuan':
            badgeColor = 'neutral';
            break;

          case 'disetujui':
            badgeColor = 'success';
            break;
        }

        if (isLatestApprovalRejected) {
          badgeColor = 'error';
          latestApprovalStepName = 'Ditolak';
        }

        return <StatusBadge color={badgeColor} text={latestApprovalStepName} />;
      },
    },
    {
      id: 'actions',
      cell: (props) => {
        const currentPageSize = props.table.getPaginationRowModel().rows.length;
        const currentPageRows = props.table.getPaginationRowModel().flatRows;
        const currentRowRelativeIndex =
          currentPageRows.findIndex((r) => r.id === props.row.id) + 1;

        const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;

        const deleteClickHandler = () => {
          setSelectedTransferToLaying(props.row.original);

          // Set row selection
          setRowSelection({
            [String(props.row.original.id)]: true,
          });

          deleteModal.openModal();
        };

        return (
          <RowOptionsMenu
            props={props}
            deleteClickHandler={deleteClickHandler}
            popoverPosition={isLast2Rows ? 'top' : 'bottom'}
          />
        );
      },
    },
  ];

  const tableEnableRowSelectionHandler: (
    row: Row<TransferToLaying>
  ) => boolean = (row) => {
    return (
      row.original.approval.action !== 'APPROVED' &&
      row.original.approval.action !== 'REJECTED'
    );
  };

  const bulkApproveClickHandler = () => {
    approveModal.openModal();
  };

  const bulkRejectClickHandler = () => {
    rejectModal.openModal();
  };

  // Modal confirm click handler
  const confirmationModalDeleteClickHandler = async () => {
    setIsDeleteLoading(true);

    const deleteResponse = await TransferToLayingApi.delete(
      selectedTransferToLaying?.id as number
    );

    if (isResponseError(deleteResponse)) {
      toast.error(deleteResponse.message);
      setIsDeleteLoading(false);
      return;
    }

    refreshTransferToLayings();

    setRowSelection({});
    setSelectedTransferToLaying(undefined);
    deleteModal.closeModal();
    toast.success('Berhasil menghapus data transfer ke laying!');
    setIsDeleteLoading(false);
  };

  const confirmationModalApproveClickHandler = async (notes: string) => {
    setIsApproveLoading(true);

    const bulkApproveResponse = await TransferToLayingApi.bulkApprove(
      selectedRowIds,
      notes
    );

    if (isResponseSuccess(bulkApproveResponse)) {
      refreshTransferToLayings();
      approveModal.closeModal();

      toast.success(
        `Berhasil approve ${selectedRowIds.length} data transfer ke laying!`
      );

      setRowSelection({});
    } else {
      approveModal.closeModal();

      toast.error(
        `Gagal approve ${selectedRowIds.length} data transfer ke laying!`
      );
    }

    setIsApproveLoading(false);
  };

  const confirmationModalRejectClickHandler = async (notes: string) => {
    setIsRejectLoading(true);

    const bulkRejectResponse = await TransferToLayingApi.bulkReject(
      selectedRowIds,
      notes
    );

    if (isResponseSuccess(bulkRejectResponse)) {
      refreshTransferToLayings();
      rejectModal.closeModal();

      toast.success(
        `Berhasil reject ${selectedRowIds.length} data transfer ke laying!`
      );
      setRowSelection({});
    } else {
      rejectModal.closeModal();

      toast.error(
        `Gagal reject ${selectedRowIds.length} data transfer ke laying!`
      );
    }

    setIsRejectLoading(false);
  };

  useEffect(() => {
    updateFilter('search', searchValue);
  }, [searchValue, updateFilter]);

  useEffect(() => {
    setTableState('transfer-to-laying-table', pathname);
  }, [pathname, setTableState]);

  const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
    setSearchValue(e.target.value);
    updateFilter('search', e.target.value);
  };

  const STATUS_FILTER_OPTIONS = [
    { value: 'PENDING', label: 'Pengajuan' },
    { value: 'APPROVED', label: 'Disetujui' },
    { value: 'REJECTED', label: 'Ditolak' },
  ];

  const filterModalInitialValues = useMemo(() => {
    const flockSourceIds = tableFilterState.flockSource
      ? tableFilterState.flockSource.split(',')
      : [];
    const flockSourceNameList = tableFilterState.flockSourceNames
      ? tableFilterState.flockSourceNames.split(',')
      : [];
    const flockSourceOptions = flockSourceIds.filter(Boolean).map((id, i) => ({
      value: parseInt(id),
      label: flockSourceNameList[i] || id,
    }));

    const flockDestIds = tableFilterState.flockDestination
      ? tableFilterState.flockDestination.split(',')
      : [];
    const flockDestNameList = tableFilterState.flockDestinationNames
      ? tableFilterState.flockDestinationNames.split(',')
      : [];
    const flockDestOptions = flockDestIds.filter(Boolean).map((id, i) => ({
      value: parseInt(id),
      label: flockDestNameList[i] || id,
    }));

    const statusIds = tableFilterState.status
      ? tableFilterState.status.split(',')
      : [];
    const statusOptions = statusIds.filter(Boolean).map((id) => {
      const found = STATUS_FILTER_OPTIONS.find((opt) => opt.value === id);
      return found || { value: id, label: id };
    });

    return {
      startDate: tableFilterState.startDate || '',
      endDate: tableFilterState.endDate || '',
      flockSource: flockSourceOptions,
      flockDestination: flockDestOptions,
      status: statusOptions,
    };
  }, [
    tableFilterState.startDate,
    tableFilterState.endDate,
    tableFilterState.flockSource,
    tableFilterState.flockDestination,
    tableFilterState.status,
    tableFilterState.flockSourceNames,
    tableFilterState.flockDestinationNames,
  ]);

  const filterSubmitHandler = (values: TransferToLayingFilterValues) => {
    const flockSourceOpts = (values.flockSource as OptionType[]) || [];
    const flockDestOpts = (values.flockDestination as OptionType[]) || [];
    const statusOpts = (values.status as OptionType[]) || [];

    updateFilter('startDate', values.startDate || '');
    updateFilter('endDate', values.endDate || '');
    updateFilter(
      'flockSource',
      flockSourceOpts.map((o) => String(o.value)).join(',')
    );
    updateFilter(
      'flockDestination',
      flockDestOpts.map((o) => String(o.value)).join(',')
    );
    updateFilter('status', statusOpts.map((o) => String(o.value)).join(','));
    updateFilter(
      'flockSourceNames',
      flockSourceOpts.map((o) => String(o.label)).join(',')
    );
    updateFilter(
      'flockDestinationNames',
      flockDestOpts.map((o) => String(o.label)).join(',')
    );
  };

  const filterResetHandler = () => {
    updateFilter('startDate', '');
    updateFilter('endDate', '');
    updateFilter('flockSource', '');
    updateFilter('flockDestination', '');
    updateFilter('status', '');
    updateFilter('flockSourceNames', '');
    updateFilter('flockDestinationNames', '');
  };

  const exportToExcelHandler = async () => {
    setIsLoadingExportingToExcel(true);

    await TransferToLayingApi.exportToExcel(getTableFilterQueryString());

    setIsLoadingExportingToExcel(false);
  };

  useEffect(() => {
    if (sorting.length === 1) {
      updateFilter('filter_by', sorting[0].id);
      updateFilter('sort_by', sorting[0].desc ? 'desc' : 'asc');
    } else {
      updateFilter('filter_by', '');
      updateFilter('sort_by', '');
    }
  }, [sorting]);

  return (
    <>
      <div className='@container w-full'>
        <div className='w-full p-3 flex flex-row justify-between gap-3 flex-wrap border-b border-base-content/10'>
          <div className='w-fit flex flex-row gap-3 flex-wrap'>
            <RequirePermission permissions='lti.production.transfer_to_laying.create'>
              <Button
                href={{
                  pathname: '/production/transfer-to-laying',
                  query: {
                    action: 'add',
                  },
                }}
                color='primary'
                className='px-3 py-2.5 w-fit text-sm text-base-100 rounded-lg shadow-sm'
              >
                <Icon icon='heroicons:plus' width={20} height={20} />
                Add Transfer to Laying
              </Button>
            </RequirePermission>

            {selectedRowIds.length > 0 && (
              <>
                <hr className='w-px h-full border-none bg-base-content/10 hidden @sm:block' />

                <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
                  <Button
                    variant='outline'
                    color='none'
                    onClick={bulkRejectClickHandler}
                    disabled={selectedRowIds.length === 0}
                    className='px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
                  >
                    <Icon
                      icon='heroicons:x-mark'
                      width={20}
                      height={20}
                      className='text-error'
                    />
                    Reject
                  </Button>
                </RequirePermission>

                <RequirePermission permissions='lti.production.transfer_to_laying.approve'>
                  <Button
                    variant='outline'
                    color='none'
                    onClick={bulkApproveClickHandler}
                    disabled={selectedRowIds.length === 0}
                    className='px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
                  >
                    <Icon
                      icon='heroicons:check'
                      width={20}
                      height={20}
                      className='text-success'
                    />
                    Approve
                  </Button>
                </RequirePermission>
              </>
            )}
          </div>

          <div className='flex flex-1 flex-row justify-start sm:justify-end items-center gap-3 flex-wrap'>
            <DebouncedTextInput
              name='search'
              placeholder='Search'
              value={tableFilterState.search ?? ''}
              onChange={searchChangeHandler}
              startAdornment={
                <Icon
                  icon='heroicons:magnifying-glass'
                  width={20}
                  height={20}
                />
              }
              className={{
                wrapper: 'w-full min-w-24 max-w-3xs',
                inputWrapper: 'rounded-xl! shadow-button-soft',
                input:
                  'placeholder:font-semibold placeholder:text-base-content/50',
              }}
            />

            <ButtonFilter
              values={tableFilterState}
              excludeFields={[
                'page',
                'pageSize',
                'search',
                'filter_by',
                'sort_by',
                'flockSourceNames',
                'flockDestinationNames',
              ]}
              fieldGroups={[['startDate', 'endDate']]}
              onClick={filterModal.openModal}
              className='px-3 py-2.5'
            />

            <Dropdown
              align='end'
              direction='bottom'
              className={{
                content:
                  'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
              }}
              trigger={
                <Button
                  variant='outline'
                  color='none'
                  className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
                >
                  <div className='flex flex-row items-center gap-1.5'>
                    <Icon
                      icon='heroicons:cloud-arrow-down'
                      width={20}
                      height={20}
                    />

                    <span>Export</span>

                    <div className='w-px self-stretch bg-base-content/10' />

                    <Icon
                      icon='heroicons:chevron-down'
                      width={14}
                      height={14}
                    />
                  </div>
                </Button>
              }
            >
              <Button
                variant='ghost'
                color='none'
                onClick={exportToExcelHandler}
                isLoading={isLoadingExportingToExcel}
                className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
              >
                <Icon icon='heroicons:table-cells' width={20} height={20} />
                Export to Excel
              </Button>
            </Dropdown>
          </div>
        </div>

        <div className='flex flex-col mb-4'>
          {isLoading ? (
            <div className='w-full flex flex-row justify-center items-center p-4'>
              <span className='loading loading-spinner loading-xl' />
            </div>
          ) : !isResponseSuccess(transferToLayings) ||
            transferToLayings.data?.length === 0 ? (
            <div className='p-3'>
              <TransferToLayingTableSkeleton
                columns={transferToLayingsColumns}
                icon={
                  <Icon
                    icon='heroicons:document-text'
                    className='text-white'
                    width={20}
                    height={20}
                  />
                }
              />
            </div>
          ) : (
            <Table<TransferToLaying>
              data={
                isResponseSuccess(transferToLayings)
                  ? transferToLayings?.data
                  : []
              }
              columns={transferToLayingsColumns}
              pageSize={tableFilterState.pageSize}
              page={
                isResponseSuccess(transferToLayings)
                  ? transferToLayings?.meta?.page
                  : 0
              }
              totalItems={
                isResponseSuccess(transferToLayings)
                  ? transferToLayings?.meta?.total_results
                  : 0
              }
              onPageChange={setPage}
              onPageSizeChange={setPageSize}
              isLoading={isLoading}
              sorting={sorting}
              setSorting={setSorting}
              rowSelection={rowSelection}
              setRowSelection={setRowSelection}
              enableRowSelection={tableEnableRowSelectionHandler}
              withCheckbox
              className={{
                containerClassName: cn('p-3 mb-0'),
                headerColumnClassName: 'text-nowrap',
              }}
            />
          )}
        </div>
      </div>

      <TransferToLayingFilterModal
        ref={filterModal.ref}
        initialValues={filterModalInitialValues}
        onSubmit={filterSubmitHandler}
        onReset={filterResetHandler}
      />

      <TransferToLayingConfirmationModal
        ref={deleteModal.ref}
        type='error'
        text='Delete This Data?'
        subtitleText='Are you sure you want to delete this data? '
        transferToLayingIds={selectedRowIds}
        primaryButton={{
          text: 'Delete',
          isLoading: isDeleteLoading,
          color: 'error',
          onClick: confirmationModalDeleteClickHandler,
        }}
        secondaryButton={{
          text: 'Cancel',
          color: 'none',
          onClick: () => {
            setRowSelection({});
            deleteModal.closeModal();
          },
        }}
      />

      {/* Approve Modal */}
      <TransferToLayingConfirmationModal
        ref={approveModal.ref}
        text='Approve This Submission?'
        subtitleText='Are you sure you want to approve this submission?'
        type='success'
        transferToLayingIds={selectedRowIds}
        withNote
        noteLabel='Notes Approval'
        primaryButton={{
          text: 'Approve',
          isLoading: isApproveLoading,
          onClick: confirmationModalApproveClickHandler,
        }}
        secondaryButton={{
          text: 'Cancel',
          color: 'none',
          onClick: () => {
            setRowSelection({});
            approveModal.closeModal();
          },
        }}
      />

      {/* Reject Modal */}
      <TransferToLayingConfirmationModal
        ref={rejectModal.ref}
        type='error'
        text='Reject This Submission?'
        subtitleText='Are you sure you want to reject this submission?'
        transferToLayingIds={selectedRowIds}
        withNote
        noteLabel='Notes Reject'
        secondaryButton={{
          text: 'Cancel',
          color: 'none',
          onClick: () => {
            setRowSelection({});
            rejectModal.closeModal();
          },
        }}
        primaryButton={{
          text: 'Reject',
          isLoading: isRejectLoading,
          color: 'error',
          onClick: confirmationModalRejectClickHandler,
        }}
      />
    </>
  );
};

export default TransferToLayingsTable;
