/* eslint-disable react/no-unstable-nested-components */
import Toast from '@arcblock/ux/lib/Toast';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { api, formatError, Table, ConfirmDialog, Switch, clearDonateCache, getPrefix } from '@blocklet/payment-react';
import { Alert, Typography, Button, CircularProgress, Stack, Avatar, Box, IconButton, Tooltip } from '@mui/material';
import { ContentCopy } from '@mui/icons-material';
import { useLocalStorageState, useRequest } from 'ahooks';
import Dialog from '@arcblock/ux/lib/Dialog';
import { useState, useEffect } from 'react';
import { joinURL } from 'ufo';
import { getDurableData } from '@arcblock/ux/lib/Datatable';
import useBus from 'use-bus';
import EditDonationForm from './edit-form';

const exampleCode = `import { PaymentProvider, DonateProvider, CheckoutDonate } from '@blocklet/payment-react';

// In your component
function YourComponent() {
  return (
    <PaymentProvider session={session} connect={connectApi}>
      <DonateProvider
        mountLocation="your-unique-donate-instance"
        description="Help locate this donation instance"
      >
        <CheckoutDonate
          settings={{
            target: "post-123", // required, unique identifier for the donation instance
            title: "Support Author", // required, title of the donation modal
            description: "If you find this article helpful, feel free to buy me a coffee", // required, description of the donation
            reference: "https://your-site.com/posts/123", // required, reference link of the donation
            beneficiaries: [
              {
                address: "tip user did", // required, address of the beneficiary
                share: "100",  // required, percentage share
              },
            ],
          }}
        />
      </DonateProvider>
    </PaymentProvider>
  );
}`;

const fetchData = (params: Record<string, any> = {}): Promise<any> => {
  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/settings/donate?${search.toString()}`).then((res: any) => res.data);
};

function CodeExample({ code }: { code: string }) {
  const { t } = useLocaleContext();

  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(code);
      Toast.success(t('common.copySuccess'));
    } catch (err) {
      Toast.error(t('common.copyFailed'));
    }
  };

  return (
    <Box sx={{ position: 'relative' }}>
      <Box
        component="pre"
        sx={{
          backgroundColor: '#F8F9FA', // 更浅的背景色
          color: '#495057', // 更柔和的文字颜色
          borderRadius: 1,
          p: 2,
          overflow: 'auto',
          '&::-webkit-scrollbar': {
            height: 8,
            bgcolor: 'background.paper',
          },
          '&::-webkit-scrollbar-thumb': {
            bgcolor: '#CED4DA', // 更浅的滚动条颜色
            borderRadius: 4,
          },
          fontSize: '0.875rem',
          fontFamily: 'monospace',
          lineHeight: 1.5, // 增加行高
          border: '1px solid #E9ECEF', // 添加柔和的边框
        }}>
        {code}
      </Box>
      <Tooltip title={t('common.copy')} placement="top">
        <IconButton
          onClick={handleCopy}
          sx={{
            position: 'absolute',
            top: 8,
            right: 8,
            bgcolor: 'background.paper',
            '&:hover': {
              bgcolor: '#F8F9FA', // 更浅的悬停色
            },
          }}>
          <ContentCopy fontSize="small" />
        </IconButton>
      </Tooltip>
    </Box>
  );
}

type SearchProps = {
  pageSize: number;
  page: number;
  q?: {
    'like-description'?: string;
    'like-component_did'?: string;
    'like-mount_location'?: string;
  };
  o?: 'asc' | 'desc';
};

export default function DonationList() {
  const listKey = 'donation-settings';
  const { t } = useLocaleContext();
  const [editingItem, setEditingItem] = useState<any>(null);
  const [showExample, setShowExample] = useState(false);
  const [confirmDialog, setConfirmDialog] = useState({
    open: false,
    id: '',
    active: false,
    mountLocation: '',
  });

  const persisted = getDurableData(listKey);
  const [search, setSearch] = useLocalStorageState<SearchProps>(listKey, {
    defaultValue: {
      o: 'desc',
      pageSize: persisted.rowsPerPage || 10,
      page: persisted.page ? persisted.page + 1 : 1,
    },
  });

  const { error, data = { list: [], count: 0 }, refresh } = useRequest(() => fetchData(search));
  const listData = data.list || [];

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

  useBus('donation.updated', () => refresh(), []);

  const handleStatusChange = async (item: any, active: boolean) => {
    if (active) {
      setConfirmDialog({ open: true, id: item.id, active, mountLocation: item.mount_location });
      return;
    }
    try {
      await api.put(`/api/settings/${item.id}`, { active: !active });
      clearDonateCache(item.mount_location);
      Toast.success(t('admin.donate.status.activeSuccess'));
      refresh();
    } catch (err) {
      Toast.error(formatError(err));
    }
  };

  const handleConfirmStatusChange = async () => {
    try {
      await api.put(`/api/settings/${confirmDialog.id}`, { active: !confirmDialog.active });
      clearDonateCache(confirmDialog.mountLocation);
      Toast.success(t('admin.donate.status.inactiveSuccess'));
      refresh();
    } catch (err) {
      Toast.error(formatError(err));
    } finally {
      setConfirmDialog({ open: false, id: '', active: false, mountLocation: '' });
    }
  };

  const columns = [
    {
      label: t('admin.donate.component'),
      name: 'component_did',
      options: {
        sort: false,
        customBodyRenderLite: (index: number) => {
          const componentInfo = window.blocklet?.componentMountPoints.find(
            (c) => c?.did === listData[index]?.component_did
          );
          if (!componentInfo) {
            return data[index]?.component_did || t('common.none');
          }
          return (
            <Stack
              direction="row"
              sx={{
                alignItems: 'center',
                gap: 1,
              }}>
              <Avatar
                src={joinURL(getPrefix(), `.well-known/service/blocklet/logo-bundle/${componentInfo.did}`)}
                alt={componentInfo?.title}
              />
              <Typography onClick={() => window.open(componentInfo.mountPoint, '_blank')} sx={{ cursor: 'pointer' }}>
                {componentInfo?.title}
              </Typography>
            </Stack>
          );
        },
      },
    },
    {
      label: t('admin.donate.mountLocation'),
      name: 'mount_location',
      options: { sort: false },
    },
    {
      label: t('admin.donate.description'),
      name: 'description',
      options: { sort: false },
    },
    {
      label: t('admin.donate.status.title'),
      name: 'active',
      width: 100,
      options: {
        sort: false,
        customBodyRenderLite: (index: number) => (
          <Switch
            checked={listData[index].active}
            onChange={() => handleStatusChange(listData[index], listData[index].active)}
          />
        ),
      },
    },
    {
      label: t('common.setting'),
      width: 100,
      options: {
        sort: false,
        customBodyRenderLite: (index: number) => (
          <Button
            component="text"
            sx={{
              color: 'text.link',
              minWidth: 'fit-content',
            }}
            onClick={() => setEditingItem(listData[index])}>
            {t('common.edit')}
          </Button>
        ),
      },
    },
  ];

  const onTableChange = ({ page, rowsPerPage }: { page: number; rowsPerPage: number }) => {
    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 }));
    }
  };

  if (error) {
    return <Alert severity="error">{error.message}</Alert>;
  }

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

  return (
    <>
      <Stack
        direction="row"
        sx={{
          alignItems: 'center',
          gap: 1,
          flexWrap: 'wrap',
        }}>
        <Typography variant="body2">{t('admin.donate.intro')}</Typography>
        <Button variant="text" size="small" onClick={() => setShowExample(true)} sx={{ color: 'text.link' }}>
          {t('admin.donate.usage.viewExample')}
        </Button>
      </Stack>
      <Table
        hasSearch
        durable={`__${listKey}__`}
        durableKeys={['searchText']}
        data={listData}
        columns={columns}
        options={{
          count: data.count,
          page: search!.page - 1,
          rowsPerPage: search!.pageSize,
          onSearchChange: (text: string) => {
            if (text) {
              setSearch((x) => ({
                ...x!,
                q: {
                  'like-mount_location': text,
                  'like-description': text,
                  'like-component_did': text,
                },
                page: 1,
              }));
            } else {
              setSearch((x) => ({
                ...x!,
                page: 1,
                q: {},
              }));
            }
          },
        }}
        onChange={onTableChange}
      />
      {showExample && (
        <Dialog
          open
          onClose={() => setShowExample(false)}
          title={t('admin.donate.usage.title')}
          maxWidth="md"
          sx={{ '.MuiDialogContent-root': { padding: 0 } }}
          fullWidth>
          <Box sx={{ p: 3 }}>
            <Typography
              variant="body2"
              sx={{
                marginBottom: '16px',
              }}>
              {t('admin.donate.usage.description')}
            </Typography>
            <CodeExample code={exampleCode} />
            <Typography
              variant="body2"
              sx={{
                color: 'text.secondary',
                mt: 2,
              }}>
              {t('admin.donate.usage.note')}
            </Typography>
          </Box>
        </Dialog>
      )}
      {editingItem && (
        <Dialog
          open
          onClose={() => setEditingItem(null)}
          title={t('admin.donate.editTitle')}
          maxWidth="md"
          fullWidth
          sx={{ '.MuiDialogContent-root': { padding: 0 } }}>
          <EditDonationForm
            item={editingItem}
            onSuccess={() => {
              refresh();
              setEditingItem(null);
            }}
            onCancel={() => setEditingItem(null)}
          />
        </Dialog>
      )}
      {confirmDialog.open && (
        <ConfirmDialog
          title={t('admin.donate.status.inactiveTitle')}
          message={t('admin.donate.status.inactiveTip')}
          onConfirm={handleConfirmStatusChange}
          onCancel={() => setConfirmDialog({ open: false, id: '', active: false, mountLocation: '' })}
        />
      )}
    </>
  );
}
