import Button from '@/components/Button';
import Card from '@/components/Card';
import Dropdown from '@/components/Dropdown';
import DateInput from '@/components/input/DateInput';
import SelectInput, {
  OptionType,
  useSelect,
} from '@/components/input/SelectInput';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import Modal, { useModal } from '@/components/Modal';
import Table from '@/components/Table';
import { isResponseSuccess } from '@/lib/api-helper';
import { formatCurrency, formatDate, formatNumber } from '@/lib/helper';
import { SupplierApi } from '@/services/api/master-data';
import {
  DebtRow,
  DebtSupplier,
  DebtSupplierFilter,
} from '@/types/api/report/debt-supplier';
import { generateDebtSupplierExcel } from '@/components/pages/report/finance/export/DebtSupplierExportXLSX';
import { generateDebtSupplierPDF } from '@/components/pages/report/finance/export/DebtSupllierExportPDF';
import { Icon } from '@iconify/react';
import { ColumnDef } from '@tanstack/react-table';
import { useCallback, useMemo, useState } from 'react';
import toast from 'react-hot-toast';
import useSWR from 'swr';
import { DebtSupplierApi } from '@/services/api/report/debt-supplier';
import { useFormik } from 'formik';
import {
  DebtSupplierFilterSchema,
  DebtSupplierFilterType,
} from '@/components/pages/report/finance/filter/DebtSupplierFilter';
import { getFilledFormikValuesCount } from '@/lib/formik-helper';
import ButtonFilter from '@/components/helper/ButtonFilter';
import { Supplier } from '@/types/api/master-data/supplier';

const DebtSupplierTab = () => {
  // ===== STATE MANAGEMENT =====
  const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
  const [isExcelExportLoading, setIsExcelExportLoading] = useState(false);
  const isAnyExportLoading = isPdfExportLoading || isExcelExportLoading;

  // ===== SUBMISSION STATE =====
  const [filterParams, setFilterParams] = useState<DebtSupplierFilter>({
    start_date: undefined,
    end_date: undefined,
    supplier_ids: undefined,
    filter_by: undefined,
  });
  const [isSubmitted, setIsSubmitted] = useState(false);

  const filterModal = useModal();

  const {
    setInputValue: setSupplierInputValue,
    options: supplierOptions,
    isLoadingOptions: isLoadingSupplierOptions,
    loadMore: loadMoreSuppliers,
  } = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name');

  const dataTypeOptions = useMemo(
    () => [
      { value: 'received_date', label: 'Tanggal Terima' },
      { value: 'po_date', label: 'Tanggal PO' },
    ],
    []
  );

  const handleFilterModalOpen = () => {
    filterModal.openModal();
  };

  // ===== FORMIK SETUP =====
  const formik = useFormik<DebtSupplierFilterType>({
    initialValues: {
      startDate: null,
      endDate: null,
      supplierIds: null,
      filterBy: null,
    },
    validationSchema: DebtSupplierFilterSchema,
    onSubmit: (values) => {
      setFilterParams({
        start_date: values.startDate?.toString() || undefined,
        end_date: values.endDate?.toString() || undefined,
        supplier_ids:
          values.supplierIds?.map((v) => String(v.value)).join(',') ||
          undefined,
        filter_by: values.filterBy?.value?.toString() || undefined,
      });
      filterModal.closeModal();
      setIsSubmitted(true);
    },
    onReset: (values) => {
      setFilterParams({
        start_date: undefined,
        end_date: undefined,
        supplier_ids: undefined,
        filter_by: undefined,
      });
      setIsSubmitted(false);
    },
  });

  // ===== DATA FETCHING =====
  const { data: debtSupplier, isLoading } = useSWR(
    isSubmitted
      ? () => {
          const params = {
            supplier_ids: filterParams.supplier_ids,
            filter_by: filterParams.filter_by,
            start_date: filterParams.start_date,
            end_date: filterParams.end_date,
          };

          return ['debt-supplier-report', params];
        }
      : null,
    ([, params]) =>
      DebtSupplierApi.getDebtSupplierReport(
        params.supplier_ids,
        params.filter_by,
        params.start_date,
        params.end_date
      )
  );

  const data: DebtSupplier[] = useMemo(
    () =>
      isResponseSuccess(debtSupplier)
        ? (debtSupplier?.data as unknown as DebtSupplier[]) || []
        : [],
    [debtSupplier]
  );
  const meta =
    isResponseSuccess(debtSupplier) && debtSupplier?.meta
      ? debtSupplier.meta
      : null;

  // ===== EXPORT DATA FETCHER =====
  const debtSupplierExport = useCallback(async (): Promise<
    DebtSupplier[] | null
  > => {
    const params = {
      supplier_ids:
        formik.values.supplierIds && formik.values.supplierIds.length > 0
          ? formik.values.supplierIds.map((v) => String(v.value)).join(',')
          : undefined,
      filter_by: formik.values.filterBy?.value?.toString() || undefined,
      start_date: formik.values.startDate || undefined,
      end_date: formik.values.endDate || undefined,
      date_type: formik.values.filterBy
        ? formik.values.filterBy.value
        : undefined,
      limit: 100,
      page: 1,
    };

    const response = await DebtSupplierApi.getDebtSupplierReport(
      params.supplier_ids,
      params.filter_by,
      params.start_date,
      params.end_date
    );

    return isResponseSuccess(response)
      ? (response.data as unknown as DebtSupplier[])
      : null;
  }, [
    formik.values.supplierIds,
    formik.values.startDate,
    formik.values.endDate,
    formik.values.filterBy,
  ]);

  // ===== EXPORT HANDLERS =====
  const handleExportExcel = useCallback(async () => {
    setIsExcelExportLoading(true);
    try {
      const allDataForExport = await debtSupplierExport();

      if (
        !allDataForExport ||
        !Array.isArray(allDataForExport) ||
        allDataForExport.length === 0
      ) {
        toast.error('Tidak ada data untuk diekspor.');
        return;
      }

      generateDebtSupplierExcel({ data: allDataForExport });
      toast.success('Excel berhasil dibuat dan diunduh.');
    } catch {
      toast.error('Gagal membuat Excel. Silakan coba lagi.');
    } finally {
      setIsExcelExportLoading(false);
    }
  }, [debtSupplierExport]);

  const handleExportPdf = useCallback(async () => {
    setIsPdfExportLoading(true);
    try {
      const allDataForExport = await debtSupplierExport();

      if (
        !allDataForExport ||
        !Array.isArray(allDataForExport) ||
        allDataForExport.length === 0
      ) {
        toast.error('Tidak ada data untuk diekspor.');
        return;
      }

      await generateDebtSupplierPDF({ data: allDataForExport });
      toast.success('PDF berhasil dibuat dan diunduh.');
    } catch {
      toast.error('Gagal membuat PDF. Silakan coba lagi.');
    } finally {
      setIsPdfExportLoading(false);
    }
  }, [debtSupplierExport]);

  const getTableColumns = (supplier: DebtSupplier): ColumnDef<DebtRow>[] => [
    {
      id: 'no',
      header: 'No',
      enableSorting: false,
      cell: (props) => props.row.index,
    },
    {
      id: 'pr_number',
      header: 'Nomor PR',
      accessorKey: 'pr_number',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.pr_number;
        return value || '-';
      },
    },
    {
      id: 'po_number',
      header: 'Nomor PO',
      accessorKey: 'po_number',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.po_number;
        return value || '-';
      },
    },
    {
      id: 'received_date',
      header: 'Tanggal Terima/Bayar',
      accessorKey: 'received_date',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.received_date;
        return value
          ? value != '-'
            ? formatDate(value, 'DD MMM YYYY')
            : '-'
          : '-';
      },
    },
    {
      id: 'po_date',
      header: 'Tanggal PO',
      accessorKey: 'po_date',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.po_date;
        return value
          ? value != '-'
            ? formatDate(value, 'DD MMM YYYY')
            : '-'
          : '-';
      },
    },
    {
      id: 'aging',
      header: 'Aging',
      accessorKey: 'aging',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.aging;
        return <div className='text-center'>{formatNumber(value)} Hari</div>;
      },
      footer: () => {
        const value = supplier.total.aging;
        return <div className='text-center'>{formatNumber(value)} Hari</div>;
      },
    },
    {
      id: 'area',
      header: 'Area',
      accessorKey: 'area',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.area?.name;
        return value || '-';
      },
    },
    {
      id: 'warehouse',
      header: 'Gudang',
      accessorKey: 'warehouse',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.warehouse?.name;
        return value || '-';
      },
    },
    {
      id: 'due_date',
      header: 'Jatuh Tempo',
      accessorKey: 'due_date',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.due_date;
        return value
          ? value != '-'
            ? formatDate(value, 'DD MMM YYYY')
            : '-'
          : '-';
      },
    },
    {
      id: 'due_status',
      header: 'Status Jatuh Tempo',
      accessorKey: 'due_status',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.due_status;
        return value || '-';
      },
    },
    {
      id: 'total_price',
      header: 'Nominal Pembelian',
      accessorKey: 'total_price',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.total_price;
        return (
          <div className={`text-right ${value < 0 ? 'text-red-500' : ''}`}>
            {formatCurrency(value)}
          </div>
        );
      },
      footer: () => {
        const value = supplier.total.total_price;
        return (
          <div className={`text-right ${value < 0 ? 'text-red-500' : ''}`}>
            {formatCurrency(value)}
          </div>
        );
      },
    },
    {
      id: 'payment_price',
      header: 'Pembayaran',
      accessorKey: 'payment_price',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.payment_price;
        return (
          <div className={`text-right ${value < 0 ? 'text-red-500' : ''}`}>
            {formatCurrency(value)}
          </div>
        );
      },
      footer: () => {
        const value = supplier.total.payment_price;
        return (
          <div className={`text-right ${value < 0 ? 'text-red-500' : ''}`}>
            {formatCurrency(value)}
          </div>
        );
      },
    },
    {
      id: 'balance',
      header: 'Sisa Saldo Hutang',
      accessorKey: 'balance',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.balance;
        return (
          <div className={`text-right ${value < 0 ? 'text-red-500' : ''}`}>
            {formatCurrency(value)}
          </div>
        );
      },
      footer: () => {
        const value = supplier.total.debt_price;
        return (
          <div className={`text-right ${value < 0 ? 'text-red-500' : ''}`}>
            {formatCurrency(value)}
          </div>
        );
      },
    },
    {
      id: 'status',
      header: 'Status',
      accessorKey: 'status',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.status;
        return value || '-';
      },
    },
    {
      id: 'travel_number',
      header: 'Nomor Perjalanan',
      accessorKey: 'travel_number',
      enableSorting: false,
      cell: (props) => {
        const value = props.row.original.travel_number;
        return value || '-';
      },
    },
  ];
  return (
    <>
      <div className='w-full p-0 sm:p-4 flex flex-col gap-4'>
        <Card
          subtitle='Laporan > Rekapitulasi Hutang ke Supplier'
          className={{ wrapper: 'w-full', body: 'p-1!' }}
        >
          <div className='mb-4 flex justify-end gap-2 [&_button]:px-4'>
            <ButtonFilter
              values={formik.values}
              onClick={handleFilterModalOpen}
              variant='outline'
            />

            <Dropdown
              trigger={
                <Button variant='outline' isLoading={isAnyExportLoading}>
                  <Icon
                    icon='heroicons:cloud-arrow-down'
                    width={18}
                    height={18}
                  />
                  Export
                </Button>
              }
              align='end'
            >
              <Menu>
                <MenuItem title='Excel' onClick={handleExportExcel} />
                <MenuItem title='PDF' onClick={handleExportPdf} />
              </Menu>
            </Dropdown>
          </div>
        </Card>

        {!isSubmitted ? (
          <div className='mt-6 text-center text-gray-500'>
            Silakan klik tombol Filter untuk mengatur filter dan menampilkan
            data.
          </div>
        ) : isLoading ? (
          <div className='w-full flex flex-row justify-center items-center p-4'>
            <span className='loading loading-spinner loading-xl' />
          </div>
        ) : data.length === 0 ? (
          <div className='mt-6 text-center text-gray-500'>
            Tidak ada data yang dapat ditampilkan...
          </div>
        ) : (
          data.map((supplierReport) => {
            return (
              <Card
                key={supplierReport.supplier.id}
                title={supplierReport.supplier.name}
                className={{ wrapper: 'w-full' }}
                variant='bordered'
                collapsible={true}
              >
                <Table
                  data={[
                    {
                      balance: supplierReport.initial_balance,
                    } as DebtRow,
                    ...supplierReport.rows,
                  ]}
                  columns={getTableColumns(supplierReport)}
                  pageSize={supplierReport.rows.length + 1}
                  renderFooter={supplierReport.rows.length > 0}
                  className={{
                    containerClassName: 'w-full',
                    tableWrapperClassName: 'overflow-x-auto mt-4',
                    tableClassName: 'w-full table-auto text-sm',
                    headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
                    headerColumnClassName:
                      'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
                    bodyRowClassName:
                      'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
                    bodyColumnClassName:
                      'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
                    tableFooterClassName:
                      'bg-gray-100 font-semibold border border-gray-200',
                    footerRowClassName: 'border-t-2 border-gray-300',
                    footerColumnClassName:
                      'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
                    paginationClassName: 'hidden',
                  }}
                  renderCustomRow={(row) => {
                    if (row.index == 0) {
                      return (
                        <tr
                          className='hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200'
                          key={row.index}
                        >
                          <td
                            className='px-4 py-3 text-xs text-gray-900 whitespace-nowrap'
                            colSpan={12}
                          ></td>
                          <td className='px-4 py-3 text-xs text-gray-900 whitespace-nowrap'>
                            <div
                              className={`text-right ${row.original.balance < 0 ? 'text-red-500' : ''}`}
                            >
                              {formatCurrency(row.original.balance)}
                            </div>
                          </td>
                          <td
                            className='px-4 py-3 text-xs text-gray-900 whitespace-nowrap'
                            colSpan={2}
                          ></td>
                        </tr>
                      );
                    }
                  }}
                />
              </Card>
            );
          })
        )}
      </div>

      {/* Filter Modal */}
      <Modal
        ref={filterModal.ref}
        className={{
          modal: 'p-0',
          modalBox: 'p-0 rounded-2xl xl:max-w-4/12 max-w-sm',
        }}
      >
        <form
          className='space-y-6'
          onSubmit={formik.handleSubmit}
          onReset={formik.handleReset}
        >
          {/* Modal Header */}
          <div className='flex items-center justify-between gap-2 py-3 border-b border-gray-300 px-4'>
            <div className='flex items-center gap-2 text-primary'>
              <Icon icon='heroicons:funnel' width={20} height={20} />
              <h3 className='font-semibold'>Filter Data</h3>
            </div>
            <Button
              variant='link'
              onClick={filterModal.closeModal}
              className='text-gray-500 hover:text-gray-700 transition-colors cursor-pointer'
            >
              <Icon icon='heroicons:x-mark' width={20} height={20} />
            </Button>
          </div>
          <div className='space-y-4 px-4'>
            <div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-4'>
              <div>
                <DateInput
                  label='Tanggal'
                  name='startDate'
                  value={formik.values.startDate || ''}
                  onChange={(e) => {
                    formik.setFieldValue('startDate', e.target.value || null);
                  }}
                  className={{ wrapper: 'w-full' }}
                  isError={
                    formik.touched.startDate && !!formik.errors.startDate
                  }
                  errorMessage={formik.errors.startDate}
                />
              </div>

              <div className='mt-auto'>
                <DateInput
                  label='‎ '
                  name='endDate'
                  value={formik.values.endDate || ''}
                  onChange={(e) => {
                    formik.setFieldValue('endDate', e.target.value || null);
                  }}
                  className={{ wrapper: 'w-full' }}
                  isError={formik.touched.endDate && !!formik.errors.endDate}
                  errorMessage={formik.errors.endDate}
                />
              </div>
            </div>

            <div>
              <SelectInput
                label='Supplier'
                placeholder='Pilih Supplier'
                isMulti
                options={supplierOptions}
                value={formik.values.supplierIds || []}
                onChange={(val) => {
                  formik.setFieldValue(
                    'supplierIds',
                    Array.isArray(val) ? val : val ? [val] : null
                  );
                }}
                onInputChange={setSupplierInputValue}
                onMenuScrollToBottom={loadMoreSuppliers}
                isLoading={isLoadingSupplierOptions}
                isClearable
                className={{ wrapper: 'w-full' }}
                isError={
                  formik.touched.supplierIds && !!formik.errors.supplierIds
                }
                errorMessage={formik.errors.supplierIds as string}
              />
            </div>

            <div>
              <SelectInput
                label='Filter Berdasarkan'
                placeholder='Pilih Filter Berdasarkan'
                options={dataTypeOptions}
                value={formik.values.filterBy || null}
                onChange={(val) => {
                  formik.setFieldValue(
                    'filterBy',
                    val ? (val as OptionType) : null
                  );
                }}
                className={{ wrapper: 'w-full' }}
                isClearable
                isError={formik.touched.filterBy && !!formik.errors.filterBy}
                errorMessage={formik.errors.filterBy as string}
              />
            </div>
          </div>

          {/* Action Buttons */}
          <div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
            <Button
              variant='soft'
              className='ms-4 min-w-36 rounded-lg'
              type='reset'
            >
              Reset Filter
            </Button>
            <Button className='me-4 min-w-36 rounded-lg' type='submit'>
              Apply Filter
            </Button>
          </div>
        </form>
      </Modal>
    </>
  );
};

export default DebtSupplierTab;
