/* eslint-disable react/no-unstable-nested-components */
import { getDurableData } from '@arcblock/ux/lib/Datatable';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { api, formatTime, Status, Table } from '@blocklet/payment-react';
import { ContentCopy } from '@mui/icons-material';
import { Box, Chip, CircularProgress, IconButton, Tooltip, Typography } from '@mui/material';
import { useEffect, useState } from 'react';
import useBus from 'use-bus';
import omit from 'lodash/omit';

import { useLocalStorageState } from 'ahooks';
import FilterToolbar from '../../../../components/filter-toolbar';
import InfoCard from '../../../../components/info-card';
import VendorActions from '../../../../components/vendor/actions';
import VendorCreate from './create';

interface Vendor {
  id: string;
  vendor_key: string;
  vendor_type: string;
  name: string;
  description: string;
  app_url: string;
  status: 'active' | 'inactive';
  metadata: Record<string, any>;
  created_at: string;
  updated_at: string;
}

const fetchData = (params: Record<string, any> = {}): Promise<{ list: Vendor[]; count: number; pk?: string }> => {
  const search = new URLSearchParams();
  Object.keys(params).forEach((key) => {
    let v = params[key];
    if (key === 'q') {
      v = (Object.entries(v) || []).map((x) => x.join(':')).join(' ');
    }
    search.set(key, String(v));
  });
  return api.get(`/api/vendors?${search.toString()}`).then((res: any) => ({
    list: res.data.data || [],
    count: res.data.total || 0,
    pk: res.data.pk || '',
  }));
};

type SearchProps = {
  status?: string;
  pageSize: number;
  page: number;
  q?: any;
  o?: string;
};

export default function VendorsList() {
  const listKey = 'vendors';
  const persisted = getDurableData(listKey);

  const { t } = useLocaleContext();
  const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
    defaultValue: {
      pageSize: persisted.rowsPerPage || 20,
      page: persisted.page ? persisted.page + 1 : 1,
    },
  });

  const [data, setData] = useState({}) as any;
  const [detailOpen, setDetailOpen] = useState(false);
  const [selectedVendor, setSelectedVendor] = useState<Vendor | null>(null);
  const [copySuccess, setCopySuccess] = useState(false);

  const refresh = () =>
    fetchData(search).then((res: any) => {
      setData(res);
    });

  useBus('vendor.created', () => refresh(), []);
  useBus('vendor.updated', () => refresh(), []);
  useBus('vendor.deleted', () => refresh(), []);

  useEffect(() => {
    refresh();
  }, [search]);

  if (!data.list) {
    return <CircularProgress />;
  }

  const columns = [
    {
      label: t('admin.vendor.name'),
      name: 'name',
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as Vendor;
          return (
            <InfoCard
              name={item.name}
              description={
                <Typography
                  variant="body2"
                  sx={{
                    color: 'text.secondary',
                    textTransform: 'capitalize',
                  }}>
                  {item.vendor_type}
                </Typography>
              }
              logo={undefined}
            />
          );
        },
      },
    },
    {
      label: t('admin.vendor.description'),
      name: 'description',
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as Vendor;
          return (
            <Typography
              variant="body2"
              sx={{
                color: 'text.secondary',
              }}>
              {item.description || '-'}
            </Typography>
          );
        },
      },
    },
    {
      label: t('common.status'),
      name: 'status',
      options: {
        filter: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as Vendor;
          return (
            <Status
              label={item?.status === 'active' ? t('admin.vendor.active') : t('admin.vendor.inactive')}
              color={item?.status === 'active' ? 'success' : 'default'}
            />
          );
        },
      },
    },
    {
      label: t('common.createdAt'),
      name: 'created_at',
      options: {
        sort: true,
        customBodyRenderLite: (_: string, index: number) => {
          const item = data.list[index] as Vendor;
          return formatTime(item.created_at);
        },
      },
    },
    {
      label: t('common.actions'),
      name: 'id',
      width: 100,
      align: 'center',
      options: {
        sort: false,
        customBodyRenderLite: (_: string, index: number) => {
          const vendor = data.list[index] as Vendor;
          return <VendorActions data={vendor} onChange={refresh} />;
        },
      },
    },
  ];

  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 handleRowClick = (vendor: Vendor) => {
    setSelectedVendor(vendor);
    setDetailOpen(true);
  };

  const handleCopyValue = async (value: string) => {
    try {
      await navigator.clipboard.writeText(value);
      setCopySuccess(true);
      setTimeout(() => setCopySuccess(false), 2000);
    } catch (err) {
      console.error('Failed to copy value:', err);
    }
  };

  const brokerInfo = [
    ...(window.blocklet.appId ? [{ label: t('admin.vendor.brokerDID'), value: window.blocklet.appId }] : []),
    ...(window.blocklet.appPk ? [{ label: t('admin.vendor.brokerPublicKey'), value: window.blocklet.appPk }] : []),
  ];

  return (
    <>
      {/* Broker Information */}
      {brokerInfo.length > 0 && (
        <Box
          sx={{
            px: 2,
            py: 1.5,
            my: 2,
            borderRadius: 1,
            border: '1px solid',
            borderColor: 'divider',
            backgroundColor: 'transparent',
            display: 'grid',
            gridTemplateColumns: 'max-content 1fr',
            gap: 1,
            alignItems: 'center',
          }}>
          {brokerInfo.map((info) => (
            <>
              <Typography
                key={`${info.label}-label`}
                variant="body2"
                sx={{
                  color: 'text.secondary',
                  justifySelf: 'start',
                }}>
                {info.label}:
              </Typography>
              <Box sx={{ display: 'flex', alignItems: 'center', overflow: 'hidden' }}>
                <Chip
                  key={`${info.label}-chip`}
                  label={info.value}
                  size="small"
                  sx={{
                    flexShrink: 1,
                    overflow: 'hidden',
                    '& .MuiChip-label': {
                      overflow: 'hidden',
                      textOverflow: 'ellipsis',
                    },
                  }}
                />
                <Tooltip key={`${info.label}-tooltip`} title={copySuccess ? t('common.copied') : t('common.copy')}>
                  <IconButton
                    size="small"
                    onClick={() => handleCopyValue(info.value)}
                    sx={{
                      color: copySuccess ? 'success.main' : 'text.secondary',
                      '&:hover': {
                        color: 'primary.main',
                      },
                    }}>
                    <ContentCopy sx={{ fontSize: 16 }} />
                  </IconButton>
                </Tooltip>
              </Box>
            </>
          ))}
        </Box>
      )}
      <Table
        hasRowLink
        durable={`__${listKey}__`}
        durableKeys={['page', 'rowsPerPage', 'searchText']}
        title={<FilterToolbar setSearch={setSearch} search={search} status={['active', 'inactive']} />}
        data={data.list || []}
        columns={columns}
        options={{
          count: data.count,
          page: search!.page - 1,
          rowsPerPage: search!.pageSize,
          onColumnSortChange(_: any, order: any) {
            setSearch({
              ...search!,
              q: search!.q || {},
              o: order,
            });
          },
          onSearchChange: (text: string) => {
            if (text) {
              setSearch({
                ...search!,
                q: {
                  'like-description': text,
                  'like-name': text,
                  'like-vendor_key': text,
                },
                pageSize: 100,
                page: 1,
              });
            } else {
              setSearch({
                ...search!,
                pageSize: 100,
                page: 1,
                q: {},
              });
            }
          },
          onRowClick: (_: object[], { dataIndex }: { dataIndex: number }) => {
            const vendor = data.list[dataIndex] as Vendor;
            handleRowClick(vendor);
          },
        }}
        loading={!data.list}
        onChange={onTableChange}
      />
      {selectedVendor && (
        <VendorCreate
          open={detailOpen}
          onClose={() => {
            setDetailOpen(false);
            setSelectedVendor(null);
          }}
          onSubmit={() => {
            setDetailOpen(false);
            setSelectedVendor(null);
            refresh();
          }}
          vendorData={{
            ...selectedVendor,
            metadata: omit(selectedVendor?.metadata || {}, 'mountPoint'),
          }}
        />
      )}
    </>
  );
}
