import { useCallback, useContext, useEffect, useMemo, useState, type ReactElement } from 'react';
import { format } from 'date-fns';
import { Loader2 } from 'lucide-react';
import { useQuery } from 'urql';
import {
  ChargeFilterType,
  VatMonthlyReportDocument,
  type VatReportFilter,
} from '../../../gql/graphql.js';
import { dedupeFragments, type TimelessDateString } from '../../../helpers/index.js';
import { useUrlQuery } from '../../../hooks/use-url-query.js';
import { FiltersContext } from '../../../providers/filters-context.js';
import { UserContext } from '../../../providers/user-provider.js';
import { MergeChargesButton } from '../../common/index.js';
import { PageLayout } from '../../layout/page-layout.js';
import { BusinessTripsTable } from './business-trips-table.js';
import { ExpensesTable } from './expenses-section/expenses-table.js';
import { IncomeTable } from './income-section/income-table.js';
import { MiscTable } from './misc-table.js';
import { MissingInfoTable } from './missing-info-table.js';
import { PCNGenerator } from './pcn-generator.js';
import { ReportSummary } from './report-summary.js';
import { VatMonthlyReportFilter } from './vat-monthly-report-filters.js';

// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
/* GraphQL */ `
  query VatMonthlyReport($filters: VatReportFilter) {
    vatReport(filters: $filters) {
      ...VatReportSummaryFields
      ...VatReportIncomeFields
      ...VatReportExpensesFields
      ...VatReportMissingInfoFields
      ...VatReportMiscTableFields
      ...VatReportBusinessTripsFields
    }
  }
`;

export const VatMonthlyReport = (): ReactElement => {
  const { get } = useUrlQuery();
  const { setFiltersContext } = useContext(FiltersContext);
  const { userContext } = useContext(UserContext);
  const [filter, setFilter] = useState<VatReportFilter>(
    get('vatMonthlyReportFilters')
      ? (JSON.parse(
          decodeURIComponent(get('vatMonthlyReportFilters') as string),
        ) as VatReportFilter)
      : {
          financialEntityId: userContext?.context.adminBusinessId ?? '',
          monthDate: format(new Date(), 'yyyy-MM-15') as TimelessDateString,
        },
  );
  const [mergeSelectedCharges, setMergeSelectedCharges] = useState<Array<string>>([]);

  // auto default admin business if not set
  useEffect(() => {
    if (
      (!filter.financialEntityId || filter.financialEntityId === '') &&
      userContext?.context.adminBusinessId
    ) {
      setFilter({
        ...filter,
        financialEntityId: userContext.context.adminBusinessId,
      });
    }
  }, [filter, userContext?.context.adminBusinessId]);

  // fetch data
  const [{ data, fetching }] = useQuery({
    query: dedupeFragments(VatMonthlyReportDocument),
    variables: {
      filters: filter,
    },
    pause: filter.financialEntityId === '',
  });

  const toggleMergeCharge = useCallback(
    (chargeId: string) => {
      if (mergeSelectedCharges.includes(chargeId)) {
        setMergeSelectedCharges(mergeSelectedCharges.filter(id => id !== chargeId));
      } else {
        setMergeSelectedCharges([...mergeSelectedCharges, chargeId]);
      }
    },
    [mergeSelectedCharges],
  );

  function onResetMerge(): void {
    setMergeSelectedCharges([]);
  }

  useEffect(() => {
    setFiltersContext(
      <div className="flex flex-row gap-2">
        <PCNGenerator filter={filter} isLoading={fetching} />
        <VatMonthlyReportFilter filter={{ ...filter }} setFilter={setFilter} />
        <MergeChargesButton
          selected={mergeSelectedCharges.map(id => ({
            id,
            onChange: (): void => {
              return;
            },
          }))}
          resetMerge={onResetMerge}
        />
      </div>,
    );
  }, [data, filter, fetching, setFiltersContext, mergeSelectedCharges]);

  const mergeSelectedChargesSet = useMemo(
    () => new Set(mergeSelectedCharges),
    [mergeSelectedCharges],
  );

  return (
    <PageLayout
      title={`VAT Monthly Report${filter.monthDate ? `, ${format(new Date(filter.monthDate), 'MMMM yyyy')}` : ''}`}
    >
      {fetching ? (
        <Loader2 className="h-10 w-10 animate-spin mr-2 self-center" />
      ) : (
        <div className="min-h-screen">
          <div className="space-y-4">
            {filter.financialEntityId && filter.monthDate && (
              <ReportSummary data={data?.vatReport} />
            )}

            {filter.chargesType !== ChargeFilterType.Expense && (
              <IncomeTable
                data={data?.vatReport}
                toggleMergeCharge={toggleMergeCharge}
                mergeSelectedCharges={mergeSelectedChargesSet}
              />
            )}

            {filter.chargesType !== ChargeFilterType.Income && (
              <ExpensesTable
                data={data?.vatReport}
                toggleMergeCharge={toggleMergeCharge}
                mergeSelectedCharges={mergeSelectedChargesSet}
              />
            )}

            <MissingInfoTable
              data={data?.vatReport}
              toggleMergeCharge={toggleMergeCharge}
              mergeSelectedCharges={mergeSelectedChargesSet}
            />

            <BusinessTripsTable
              data={data?.vatReport}
              toggleMergeCharge={toggleMergeCharge}
              mergeSelectedCharges={mergeSelectedChargesSet}
            />

            <MiscTable
              data={data?.vatReport}
              toggleMergeCharge={toggleMergeCharge}
              mergeSelectedCharges={mergeSelectedChargesSet}
            />
          </div>
        </div>
      )}
    </PageLayout>
  );
};
