import {
  Button,
  Column,
  Grid,
  Icon,
  Label,
  List,
  ListItem,
  ListSection,
  Menu,
  MenuItem,
  MenuSection,
  MenuTrigger,
  Popover,
  Row,
  Select,
} from '@umami/react-zen';
import { endOfDay, subMonths } from 'date-fns';
import type { Key } from 'react';
import { Empty } from '@/components/common/Empty';
import { FilterRecord } from '@/components/common/FilterRecord';
import { type FieldGroup, useFields, useMessages, useMobile } from '@/components/hooks';
import { Plus } from '@/components/icons';

export interface FieldFiltersProps {
  websiteId?: string;
  value?: { name: string; operator: string; value: string }[];
  exclude?: string[];
  match?: string;
  onChange?: (data: any) => void;
  onMatchChange?: (match: string) => void;
}

export function FieldFilters({
  websiteId,
  value,
  exclude = [],
  match = 'all',
  onChange,
  onMatchChange,
}: FieldFiltersProps) {
  const { t, labels, messages } = useMessages();
  const { fields, groupLabels } = useFields();
  const startDate = subMonths(endOfDay(new Date()), 6);
  const endDate = endOfDay(new Date());
  const { isMobile } = useMobile();

  const groupedFields = fields
    .filter(({ name }) => !exclude.includes(name))
    .reduce(
      (acc, field) => {
        const group = field.group;
        if (!acc[group]) {
          acc[group] = [];
        }
        acc[group].push(field);
        return acc;
      },
      {} as Record<FieldGroup, typeof fields>,
    );

  const updateFilter = (index: number, props: Record<string, any>) => {
    onChange(value.map((filter, i) => (i === index ? { ...filter, ...props } : filter)));
  };

  const handleAdd = (name: Key) => {
    onChange(value.concat({ name: name.toString(), operator: 'eq', value: '' }));
  };

  const handleChange = (index: number, val: Key) => {
    updateFilter(index, { value: val });
  };

  const handleSelect = (index: number, operator: Key) => {
    updateFilter(index, { operator });
  };

  const handleRemove = (index: number) => {
    onChange(value.filter((_, i) => i !== index));
  };

  return (
    <Grid columns={{ base: '1fr', md: '180px 1fr' }} overflow="hidden" gapY="6">
      <Row display={{ base: 'flex', md: 'none' }}>
        <MenuTrigger>
          <Button>
            <Icon>
              <Plus />
            </Icon>
          </Button>
          <Popover placement={isMobile ? 'left' : 'bottom start'} shouldFlip>
            <Menu
              onAction={handleAdd}
              style={{ maxHeight: 'calc(100vh - 2rem)', overflowY: 'auto' }}
            >
              {groupLabels.map(({ key: groupKey, label }) => {
                const groupFields = groupedFields[groupKey];
                if (!groupFields || groupFields.length === 0) return null;
                return (
                  <MenuSection key={groupKey} title={label}>
                    {groupFields.map(field => {
                      return (
                        <MenuItem key={field.name} id={field.name}>
                          {field.filterLabel}
                        </MenuItem>
                      );
                    })}
                  </MenuSection>
                );
              })}
            </Menu>
          </Popover>
        </MenuTrigger>
      </Row>
      <Column
        display={{ base: 'none', md: 'flex' }}
        border="right"
        paddingRight="3"
        marginRight="6"
      >
        <List onAction={handleAdd}>
          {groupLabels.map(({ key: groupKey, label }) => {
            const groupFields = groupedFields[groupKey];
            if (!groupFields || groupFields.length === 0) return null;

            return (
              <ListSection key={groupKey} title={label}>
                {groupFields.map(field => {
                  return (
                    <ListItem key={field.name} id={field.name}>
                      {field.filterLabel}
                    </ListItem>
                  );
                })}
              </ListSection>
            );
          })}
        </List>
      </Column>
      <Column overflow="auto" gapY="4" style={{ contain: 'layout' }}>
        {onMatchChange && (
          <Row alignItems="center" gap>
            <Column gap="1">
              <Label>{t(labels.match)}</Label>
              <Select value={match} onChange={onMatchChange} style={{ width: 150 }}>
                <ListItem id="all">{t(labels.matchAll)}</ListItem>
                <ListItem id="any">{t(labels.matchAny)}</ListItem>
              </Select>
            </Column>
          </Row>
        )}
        {value.map((filter, index) => {
          return (
            <FilterRecord
              key={`${filter.name}-${index}`}
              websiteId={websiteId}
              type={filter.name}
              startDate={startDate}
              endDate={endDate}
              {...filter}
              onSelect={(_name, operator) => handleSelect(index, operator)}
              onRemove={() => handleRemove(index)}
              onChange={(_name, val) => handleChange(index, val)}
            />
          );
        })}
        {!value.length && <Empty message={t(messages.nothingSelected)} />}
      </Column>
    </Grid>
  );
}
