/* eslint-disable react/no-unstable-nested-components */
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { api, formatBNStr, formatCreditAmount, Table, useDefaultPageSize } from '@blocklet/payment-react';
import type { TCustomer, TPaymentCurrency } from '@blocklet/payment-types';
import { Add, Close } from '@mui/icons-material';
import { Box, Button, CircularProgress, Menu, MenuItem, styled } from '@mui/material';
import { useEffect, useState } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
import CustomerLink from '../../../../components/customer/link';

type OverdueRecord = {
  customer: TCustomer;
  currency: TPaymentCurrency;
  total_pending: string;
  event_count: number;
};

type SearchProps = {
  pageSize: number;
  page: number;
  currency_id: string;
  q?: string;
};

type ApiResponse = {
  list: OverdueRecord[];
  count: number;
  paging: { page: number; pageSize: number };
};

const fetchData = (params: Record<string, any> = {}): Promise<ApiResponse> => {
  const search = new URLSearchParams();
  Object.keys(params).forEach((key) => {
    const v = params[key];
    if (v !== undefined && v !== null && v !== '') {
      search.set(key, String(v));
    }
  });
  return api.get(`/api/meter-events/overdue-customers?${search.toString()}`).then((res: any) => res.data);
};

const fetchCreditCurrencies = (): Promise<TPaymentCurrency[]> => {
  return api.get('/api/payment-currencies?credit=true').then((res: any) => {
    // Filter to only return credit type currencies
    return (res.data || []).filter((c: TPaymentCurrency) => c.type === 'credit');
  });
};

export default function OverdueList() {
  const listKey = 'overdue-customers';

  const { t } = useLocaleContext();
  const defaultPageSize = useDefaultPageSize(20);
  const [searchParams, setSearchParams] = useSearchParams();

  const [currencies, setCurrencies] = useState<TPaymentCurrency[]>([]);
  const [search, setSearch] = useState<SearchProps>({
    pageSize: defaultPageSize,
    page: 1,
    currency_id: '',
  });
  const [data, setData] = useState<ApiResponse | null>(null);
  const [loading, setLoading] = useState(true);

  // Load credit currencies on mount
  useEffect(() => {
    fetchCreditCurrencies().then((list) => {
      setCurrencies(list);
      // Check if currency_id is provided in URL
      const urlCurrencyId = searchParams.get('currency_id');
      if (urlCurrencyId && list.some((c) => c.id === urlCurrencyId)) {
        // Use URL parameter and clear it from URL
        setSearch((prev: any) => ({ ...prev, currency_id: urlCurrencyId, page: 1 }));
        setSearchParams({}, { replace: true });
      }
      // Do not auto-select first currency, keep empty by default
    });
  }, []);

  useEffect(() => {
    // Fetch data regardless of currency_id - API supports empty currency_id to return all
    setLoading(true);
    fetchData(search)
      .then((res) => setData(res))
      .finally(() => setLoading(false));
  }, [search]);

  const columns = [
    {
      label: t('common.customer'),
      name: 'customer',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as OverdueRecord | undefined;
          if (!item) return null;
          return <CustomerLink customer={item.customer} />;
        },
      },
    },
    {
      label: t('admin.overdue.selectCurrency'),
      name: 'currency',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as OverdueRecord | undefined;
          if (!item?.currency) return null;
          return item.currency.symbol;
        },
      },
    },
    {
      label: t('admin.overdue.pendingAmount'),
      name: 'total_pending',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as OverdueRecord | undefined;
          if (!item) return null;
          const { currency } = item;
          return (
            <Box component="span" sx={{ fontWeight: 600, color: 'error.main' }}>
              -{formatCreditAmount(formatBNStr(item.total_pending, currency?.decimal || 18), currency?.symbol || '')}
            </Box>
          );
        },
      },
    },
    {
      label: t('admin.overdue.eventCount'),
      name: 'event_count',
      options: {
        customBodyRenderLite: (_: string, index: number) => {
          const item = data?.list[index] as OverdueRecord | undefined;
          if (!item) return null;
          if (!item.customer?.id) {
            return item.event_count;
          }

          const params = new URLSearchParams({
            customer_id: item.customer.id,
            status: 'requires_capture,requires_action',
          });

          return <Link to={`/admin/billing/meter-events?${params.toString()}`}>{item.event_count}</Link>;
        },
      },
    },
  ];

  const onTableChange = ({ page, rowsPerPage }: any) => {
    if (search!.pageSize !== rowsPerPage) {
      setSearch((x: any) => ({ ...x, pageSize: rowsPerPage, page: 1 }));
    } else if (search!.page !== page + 1) {
      setSearch((x: any) => ({ ...x, page: page + 1 }));
    }
  };

  const handleCurrencyChange = (currencyId: string) => {
    setSearch((prev: any) => ({ ...prev, currency_id: currencyId, page: 1 }));
  };

  if (loading && !data) {
    return <CircularProgress />;
  }

  return (
    <Table
      data={data?.list || []}
      durable={`__${listKey}__`}
      durableKeys={['page', 'rowsPerPage', 'searchText']}
      columns={columns}
      loading={loading}
      onChange={onTableChange}
      options={{
        count: data?.count || 0,
        page: search!.page - 1,
        rowsPerPage: search!.pageSize,
        onSearchChange: (text: string) => {
          setSearch((prev: any) => ({
            ...prev,
            q: text || undefined,
            page: 1,
          }));
        },
      }}
      title={
        <CurrencyFilter
          currencies={currencies}
          selectedCurrencyId={search?.currency_id || ''}
          onChange={handleCurrencyChange}
        />
      }
      emptyNodeText={t('admin.overdue.noOverdue')}
    />
  );
}

function CurrencyFilter({
  currencies,
  selectedCurrencyId,
  onChange,
}: {
  currencies: TPaymentCurrency[];
  selectedCurrencyId: string;
  onChange: (currencyId: string) => void;
}) {
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
  const { t } = useLocaleContext();
  const selectedCurrency = currencies.find((c) => c.id === selectedCurrencyId);

  return (
    <Root>
      <Box className="table-toolbar-left">
        <section>
          <Button className="option-btn" variant="text" onClick={(e) => setAnchorEl(e.currentTarget)}>
            {selectedCurrencyId ? (
              <Close
                sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }}
                onClick={(e) => {
                  e.stopPropagation();
                  onChange('');
                  setAnchorEl(null);
                }}
              />
            ) : (
              <Add sx={{ color: 'text.secondary', cursor: 'pointer', fontSize: '1.05rem' }} />
            )}
            {t('admin.overdue.selectCurrency')}
            <span>{selectedCurrency?.symbol}</span>
          </Button>
          <Menu
            anchorEl={anchorEl}
            open={Boolean(anchorEl)}
            onClose={() => setAnchorEl(null)}
            className="status-options">
            {currencies.map((currency) => (
              <MenuItem
                key={currency.id}
                onClick={() => {
                  onChange(currency.id);
                  setAnchorEl(null);
                }}>
                {currency.name} ({currency.symbol})
              </MenuItem>
            ))}
          </Menu>
        </section>
      </Box>
    </Root>
  );
}

const Root = styled(Box)`
  .table-toolbar-left {
    display: flex;
    align-items: center;
  }

  .table-toolbar-left section {
    position: relative;
    list-style: none;
    font-size: 14px;
    font-weight: normal;
    padding: 0 5px;
    cursor: pointer;
  }

  .option-btn {
    display: flex;
    align-items: center;
    border-radius: 25px;
    background: ${({ theme }) => theme.palette.grey[100]};
    padding: 5px 10px;
    color: ${({ theme }) => theme.palette.text.secondary};
    font-size: 14px;
    line-height: 14px;
    overflow: visible;
  }

  .option-btn span {
    color: #3773f2;
    padding: 0 3px;
    overflow: visible;
  }

  .status-options {
    max-height: 300px;
    overflow-y: auto;
  }
`;
