import React, { useMemo, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useForm, Controller } from 'react-hook-form';
import Toast from '@arcblock/ux/lib/Toast';
import { Button, Dialog, useMediaQuery, DialogTitle, DialogContent, DialogActions, TextField, Tooltip, Checkbox, Box, List, ListItem, Collapse, Typography, IconButton, Chip, FormHelperText, Avatar, Alert, CircularProgress, FormControlLabel, useTheme } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import { WELLKNOWN_SERVICE_PATH_PREFIX } from '@abtnode/constant';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { joinURL } from 'ufo';
import { useNodeContext } from '../../contexts/node';
import { useTeamContext } from '../../contexts/team';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const useOpenEvent = initialData => {
  const [openEvent, setOpenEvent] = useState(initialData || null);
  const [loading, setLoading] = useState(!initialData);
  const [error, setError] = useState(null);
  const site = window.blocklet?.appUrl;
  const eventsBySource = useMemo(() => {
    const result = {};
    if (openEvent) {
      openEvent.sources.forEach(source => {
        result[source.did] = {
          source,
          events: [],
          count: 0
        };
      });
      openEvent.events.forEach(event => {
        if (result[event.source]) {
          result[event.source].events.push(event);
          result[event.source].count += 1;
        }
      });
    }
    return result;
  }, [openEvent]);
  const loadData = async () => {
    try {
      setLoading(true);
      if (!site) return;
      const response = await fetch(joinURL(site, WELLKNOWN_SERVICE_PATH_PREFIX, '/openevent.json'));
      const data = await response.json();
      setOpenEvent(data);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err : new Error(String(err)));
    } finally {
      setLoading(false);
    }
  };
  useEffect(() => {
    loadData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [site]);
  return {
    openEvent,
    setOpenEvent,
    eventsBySource,
    loading,
    error,
    loadData
  };
};
function EventSelector({
  eventsBySource,
  selectedEvents,
  setSelectedEvents,
  error = null
}) {
  const {
    t
  } = useLocaleContext();
  const [expandedSources, setExpandedSources] = useState({});
  const selectedCounts = useMemo(() => {
    const counts = {};
    Object.entries(eventsBySource).forEach(([sourceDid, {
      events
    }]) => {
      const count = events.filter(event => selectedEvents[`${event.type}-${event.source}`]).length;
      counts[sourceDid] = count;
    });
    return counts;
  }, [eventsBySource, selectedEvents]);
  const totalSelectedCount = useMemo(() => {
    return Object.values(selectedCounts).reduce((sum, count) => sum + count, 0);
  }, [selectedCounts]);
  const totalEventCount = useMemo(() => {
    return Object.values(eventsBySource).reduce((sum, {
      events
    }) => sum + events.length, 0);
  }, [eventsBySource]);
  const handleToggleSource = (did, event) => {
    event.stopPropagation();
    setExpandedSources({
      ...expandedSources,
      [did]: !expandedSources[did]
    });
  };
  const handleToggleEvent = event => {
    const key = `${event.type}-${event.source}`;
    setSelectedEvents(prev => ({
      ...prev,
      [key]: !prev[key]
    }));
  };
  const handleSelectAllForSource = (events, isSelected) => {
    const updates = {};
    events.forEach(event => {
      const key = `${event.type}-${event.source}`;
      updates[key] = !isSelected;
    });
    setSelectedEvents(prev => ({
      ...prev,
      ...updates
    }));
  };
  const handleSelectAll = e => {
    const newState = {};
    Object.values(eventsBySource).forEach(({
      events
    }) => {
      events.forEach(event => {
        const key = `${event.type}-${event.source}`;
        newState[key] = e.target.checked;
      });
    });
    setSelectedEvents(newState);
  };
  return /*#__PURE__*/_jsxs(Box, {
    sx: {
      width: '100%'
    },
    children: [/*#__PURE__*/_jsxs(Box, {
      sx: {
        display: 'flex',
        alignItems: 'center',
        mb: 1,
        mt: 1
      },
      children: [/*#__PURE__*/_jsx(FormControlLabel, {
        control: /*#__PURE__*/_jsx(Checkbox, {
          onChange: handleSelectAll,
          checked: totalSelectedCount > 0 && totalSelectedCount === totalEventCount
        }),
        label: /*#__PURE__*/_jsxs(Box, {
          sx: {
            display: 'flex',
            alignItems: 'center',
            cursor: 'pointer'
          },
          children: [t('webhookEndpoint.selectAllEvents'), /*#__PURE__*/_jsx(Box, {
            sx: {
              display: 'flex',
              alignItems: 'center'
            },
            children: /*#__PURE__*/_jsx(Tooltip, {
              title: t('webhookEndpoint.selectAllEventsTooltip'),
              placement: "right",
              children: /*#__PURE__*/_jsx(InfoOutlinedIcon, {
                fontSize: "small",
                sx: {
                  ml: 0.5,
                  cursor: 'help'
                }
              })
            })
          })]
        }),
        sx: {
          m: 0
        }
      }), totalSelectedCount > 0 && /*#__PURE__*/_jsx(Typography, {
        variant: "body2",
        color: "primary",
        sx: {
          ml: 'auto'
        },
        children: t('webhookEndpoint.selectedEventsCount', {
          count: totalSelectedCount
        })
      })]
    }), /*#__PURE__*/_jsx(Box, {
      className: "webhook-event-selector",
      sx: {
        maxHeight: '50vh',
        overflowY: 'auto',
        overflowX: 'hidden'
      },
      children: /*#__PURE__*/_jsx(List, {
        disablePadding: true,
        sx: {
          border: '1px solid',
          borderColor: 'divider',
          borderRadius: 0.5
        },
        children: Object.entries(eventsBySource).map(([did, {
          source,
          events,
          count
        }], index) => {
          const isSelected = selectedCounts[did] > 0;
          const isAllSelected = selectedCounts[did] === events.length && events.length > 0;
          const isExpanded = expandedSources[did];
          return /*#__PURE__*/_jsxs(React.Fragment, {
            children: [/*#__PURE__*/_jsx(ListItem, {
              sx: {
                borderBottom: ({
                  palette
                }) => index < Object.keys(eventsBySource).length - 1 ? `1px solid ${palette.divider}` : 'none',
                px: 0,
                py: 1,
                '&:hover': {
                  bgcolor: 'rgba(0, 0, 0, 0.02)'
                }
              },
              children: /*#__PURE__*/_jsxs(Box, {
                sx: {
                  display: 'flex',
                  width: '100%',
                  justifyContent: 'space-between',
                  alignItems: 'center'
                },
                onClick: e => {
                  if (!e.target.closest('.MuiFormControlLabel-root')) {
                    handleToggleSource(did, e);
                  }
                },
                children: [/*#__PURE__*/_jsx(Box, {
                  sx: {
                    display: 'flex',
                    alignItems: 'center'
                  },
                  children: events.length > 0 && /*#__PURE__*/_jsx(FormControlLabel, {
                    control: /*#__PURE__*/_jsx(Checkbox, {
                      checked: isAllSelected,
                      indeterminate: isSelected && !isAllSelected,
                      onChange: e => {
                        e.stopPropagation();
                        handleSelectAllForSource(events, isAllSelected);
                      }
                    }),
                    label: /*#__PURE__*/_jsxs(Box, {
                      sx: {
                        display: 'flex',
                        alignItems: 'center',
                        gap: 1
                      },
                      children: [source.logo && /*#__PURE__*/_jsx(Avatar, {
                        src: source.logo,
                        sx: {
                          width: 24,
                          height: 24
                        }
                      }), /*#__PURE__*/_jsx(Box, {
                        children: source.title || did
                      }), isSelected && /*#__PURE__*/_jsx(Chip, {
                        label: t('webhookEndpoint.selectedCount', {
                          count: selectedCounts[did]
                        }),
                        size: "small",
                        sx: {
                          mt: '2px',
                          height: '20px',
                          fontSize: '12px',
                          bgcolor: theme => `${theme.palette.primary.main}20`,
                          color: 'primary.main',
                          fontWeight: 500
                        }
                      })]
                    }),
                    sx: {
                      m: 0,
                      '& .MuiFormControlLabel-label': {
                        flex: 1
                      }
                    }
                  })
                }), /*#__PURE__*/_jsxs(Box, {
                  sx: {
                    display: 'flex',
                    alignItems: 'center'
                  },
                  children: [/*#__PURE__*/_jsx(Typography, {
                    variant: "body2",
                    sx: {
                      color: 'text.secondary',
                      mr: 1
                    },
                    children: t('webhookEndpoint.eventsCount', {
                      count
                    })
                  }), events.length > 0 && /*#__PURE__*/_jsx(IconButton, {
                    size: "small",
                    edge: "end",
                    children: isExpanded ? /*#__PURE__*/_jsx(ExpandLessIcon, {}) : /*#__PURE__*/_jsx(ExpandMoreIcon, {})
                  })]
                })]
              })
            }), events.length > 0 && /*#__PURE__*/_jsx(Collapse, {
              in: isExpanded,
              timeout: "auto",
              unmountOnExit: true,
              children: /*#__PURE__*/_jsx(List, {
                disablePadding: true,
                sx: {
                  p: 0,
                  bgcolor: 'rgba(0, 0, 0, 0.01)'
                },
                children: events.map(event => {
                  const key = `${event.type}-${event.source}`;
                  const isChecked = !!selectedEvents[key];
                  return /*#__PURE__*/_jsx(ListItem, {
                    dense: true,
                    sx: {
                      py: 0.75,
                      px: 1
                    },
                    onClick: () => handleToggleEvent(event),
                    children: /*#__PURE__*/_jsxs(Box, {
                      sx: {
                        display: 'flex',
                        alignItems: 'flex-start',
                        width: '100%'
                      },
                      children: [/*#__PURE__*/_jsx(Checkbox, {
                        checked: isChecked,
                        sx: {
                          flexShrink: 0
                        }
                      }), /*#__PURE__*/_jsxs(Box, {
                        sx: {
                          flex: 1,
                          minWidth: 0
                        },
                        children: [/*#__PURE__*/_jsx(Typography, {
                          variant: "body1",
                          className: "webhook-event-type",
                          sx: {
                            cursor: 'pointer',
                            color: 'text.primary',
                            wordBreak: 'break-word',
                            overflowWrap: 'break-word'
                          },
                          children: event.type
                        }), /*#__PURE__*/_jsx(Typography, {
                          variant: "caption",
                          sx: {
                            color: 'text.secondary',
                            display: 'block',
                            cursor: 'pointer',
                            wordBreak: 'break-word',
                            overflowWrap: 'break-word'
                          },
                          children: event.description
                        })]
                      })]
                    })
                  }, key);
                })
              })
            })]
          }, did);
        })
      })
    }), error && /*#__PURE__*/_jsx(FormHelperText, {
      error: true,
      sx: {
        mt: 1
      },
      children: error
    })]
  });
}
EventSelector.propTypes = {
  eventsBySource: PropTypes.objectOf(PropTypes.shape({
    source: PropTypes.shape({
      did: PropTypes.string.isRequired,
      title: PropTypes.string,
      description: PropTypes.string,
      version: PropTypes.string,
      logo: PropTypes.string
    }).isRequired,
    events: PropTypes.arrayOf(PropTypes.shape({
      type: PropTypes.string.isRequired,
      description: PropTypes.string.isRequired,
      source: PropTypes.string.isRequired
    })).isRequired,
    count: PropTypes.number.isRequired
  })).isRequired,
  selectedEvents: PropTypes.objectOf(PropTypes.bool).isRequired,
  setSelectedEvents: PropTypes.func.isRequired,
  error: PropTypes.string
};
function CreateOrEditHook({
  id = null,
  url = '',
  description = '',
  enabledEvents = [],
  onSubmit,
  onClose = () => {}
}) {
  const {
    t
  } = useLocaleContext();
  const [selectedEvents, setSelectedEvents] = useState({});
  const {
    teamDid
  } = useTeamContext();
  const {
    api
  } = useNodeContext();
  const {
    loading,
    error,
    eventsBySource
  } = useOpenEvent();
  const theme = useTheme();
  const {
    control,
    handleSubmit: validateSubmit,
    formState: {
      errors
    },
    reset,
    setValue,
    trigger
  } = useForm({
    defaultValues: {
      url: '',
      description: ''
    }
  });
  const isBreakpointsDownSm = useMediaQuery(theme.breakpoints.down('md'));
  useEffect(() => {
    const hasSelectedEvents = Object.values(selectedEvents).some(value => value);
    setValue('selectedEvents', hasSelectedEvents ? 'valid' : '');
    trigger('selectedEvents');
  }, [selectedEvents, setValue, trigger]);
  const handleClose = () => {
    setSelectedEvents({});
    reset();
    onClose();
  };
  const onFormSubmit = async data => {
    const selectedEventTypes = Object.keys(selectedEvents).filter(key => selectedEvents[key]);
    const submitData = {
      url: data.url,
      description: data.description,
      enabledEvents: selectedEventTypes.map(key => {
        const [type, source] = key.split('-');
        if (!type || !source) return null;
        return {
          type,
          source
        };
      }).filter(Boolean)
    };
    try {
      if (id) {
        const res = await api.updateWebhookEndpoint({
          input: {
            teamDid,
            id,
            data: submitData
          }
        });
        Toast.success(`${t('webhookEndpoint.updateWebhook')} ${t('webhookEndpoint.success')}`);
        onSubmit(res);
      } else {
        const res = await api.createWebhookEndpoint({
          input: {
            teamDid,
            input: submitData
          }
        });
        Toast.success(`${t('webhookEndpoint.createWebhook')} ${t('webhookEndpoint.success')}`);
        onSubmit(res);
      }
    } catch (err) {
      Toast.error(err?.message);
    }
    handleClose();
  };
  useEffect(() => {
    reset({
      url,
      description
    });
    setSelectedEvents(enabledEvents.reduce((acc, event) => {
      acc[`${event.type}-${event.source}`] = true;
      return acc;
    }, {}));
  }, [reset, setSelectedEvents, url, description, enabledEvents]);
  return /*#__PURE__*/_jsx(Dialog, {
    open: true,
    onClose: handleClose,
    maxWidth: "lg",
    fullWidth: true,
    fullScreen: isBreakpointsDownSm,
    children: /*#__PURE__*/_jsxs("form", {
      onSubmit: validateSubmit(onFormSubmit),
      children: [/*#__PURE__*/_jsx(DialogTitle, {
        children: id ? t('webhookEndpoint.editWebhookTitle') : t('webhookEndpoint.createWebhookTitle')
      }), /*#__PURE__*/_jsx(DialogContent, {
        children: /*#__PURE__*/_jsxs(Box, {
          sx: {
            display: 'flex',
            flexDirection: 'column',
            gap: 2,
            mt: 2
          },
          children: [/*#__PURE__*/_jsx(Controller, {
            name: "url",
            control: control,
            rules: {
              required: t('webhookEndpoint.validation.urlRequired'),
              pattern: {
                value: /^(http|https):\/\/[^ "]+$/,
                message: t('webhookEndpoint.validation.urlInvalid')
              }
            },
            render: ({
              field
            }) => /*#__PURE__*/_jsx(TextField, {
              ...field,
              label: t('webhookEndpoint.url.label'),
              fullWidth: true,
              error: !!errors.url,
              helperText: errors.url?.message
            })
          }), /*#__PURE__*/_jsx(Controller, {
            name: "description",
            control: control,
            rules: {
              required: t('webhookEndpoint.validation.descriptionRequired')
            },
            render: ({
              field
            }) => /*#__PURE__*/_jsx(TextField, {
              ...field,
              label: t('webhookEndpoint.description.label'),
              fullWidth: true,
              multiline: true,
              minRows: 2,
              maxRows: 4,
              error: !!errors.description,
              helperText: errors.description?.message
            })
          }), /*#__PURE__*/_jsx(Controller, {
            name: "selectedEvents",
            control: control,
            rules: {
              required: t('webhookEndpoint.validation.eventRequired')
            },
            render: ({
              field
            }) => /*#__PURE__*/_jsx("input", {
              type: "hidden",
              ...field
            })
          }), !loading && eventsBySource && Object.keys(eventsBySource).length > 0 && /*#__PURE__*/_jsx(EventSelector, {
            eventsBySource: eventsBySource,
            selectedEvents: selectedEvents,
            setSelectedEvents: setSelectedEvents,
            error: errors.selectedEvents?.message
          }), !loading && (!eventsBySource || Object.keys(eventsBySource).length === 0) && /*#__PURE__*/_jsx(Typography, {
            sx: {
              color: 'text.secondary'
            },
            children: t('webhookEndpoint.noAvailableEvents')
          }), loading && /*#__PURE__*/_jsx(Box, {
            sx: {
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center',
              height: '500px',
              width: '100%'
            },
            children: /*#__PURE__*/_jsx(CircularProgress, {
              size: 20
            })
          }), error && /*#__PURE__*/_jsx(Alert, {
            severity: "error",
            children: t('webhookEndpoint.loadingError', {
              message: error?.message
            })
          })]
        })
      }), /*#__PURE__*/_jsxs(DialogActions, {
        sx: {
          p: '8px 24px 24px'
        },
        children: [/*#__PURE__*/_jsx(Button, {
          onClick: handleClose,
          children: t('common.cancel')
        }), /*#__PURE__*/_jsx(Button, {
          type: "submit",
          variant: "contained",
          color: "primary",
          children: id ? t('webhookEndpoint.updateWebhook') : t('webhookEndpoint.saveWebhook')
        })]
      })]
    })
  });
}
CreateOrEditHook.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  id: PropTypes.string,
  url: PropTypes.string,
  description: PropTypes.string,
  enabledEvents: PropTypes.arrayOf(PropTypes.shape({
    type: PropTypes.string.isRequired,
    source: PropTypes.string.isRequired
  })),
  onClose: PropTypes.func
};
export default CreateOrEditHook;