import React, { Component } from 'react';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';
import CircularProgress from '@mui/material/CircularProgress';
import NotificationsIcon from '@mui/icons-material/Notifications';
import NotificationsActiveIcon from '@mui/icons-material/NotificationsActive';
import Filter from './Filter.js';
import { useParams, useSearchParams, useNavigate, useLocation } from 'react-router-dom';
import { setSessionSetting, removeSessionSetting, clearAllSessionSettings } from '../utils/sessionStorage.js';
import { withI18n } from '../i18n/withTranslation.js';
import {
  PUSH_SUBSCRIPTIONS_CHANGED_EVENT,
  emitPushSubscriptionsChanged,
  isPushApiSupported,
  fetchPushConfiguration,
  registerPushServiceWorker,
  ensurePushSubscription,
  categoryPushStatus,
  categoryPushSubscribe,
  categoryPushUnsubscribe,
  parseSubscribedStatus,
  parseSuccess,
} from '../utils/categoryPush.js';

const isNew = (neu) => neu && (new Date().getTime() - new Date(neu).getTime() < 30 * 24 * 60 * 60 * 1000);

/** Category push subscribe UI only when the category has more than this many articles. */
const MIN_ARTICLES_FOR_CATEGORY_PUSH = 10;

// HOC to provide router props to class components
const withRouter = (ClassComponent) => {
  return (props) => {
    const params = useParams();
    const [searchParams] = useSearchParams();
    const navigate = useNavigate();
    const location = useLocation();
    return <ClassComponent 
      {...props} 
      params={params} 
      searchParams={searchParams}
      navigate={navigate}
      location={location} 
    />;
  };
};

class ProductFilters extends Component {
  constructor(props) {
    super(props);

    const uniqueManufacturerArray = this._getUniqueManufacturers(this.props.products);
    const attributeGroups = this._getAttributeGroups(this.props.attributes);
    const availabilityValues = this._getAvailabilityValues(this.props.products);

    this.state = {
      availabilityValues,
      uniqueManufacturerArray,
      attributeGroups,
      manufacturerImages: new Map(), // id (number) → object URL
      pushInteractive: false,
      pushSubscribed: false,
      pushBusy: false,
      pushError: null,
    };

    this._manufacturerImageUrls = []; // track for cleanup
  }

  componentDidMount() {
    this.onPushSubscriptionsChanged = () => {
      this.refreshCategoryPushStatus();
    };
    this.adjustPaperHeight();
    window.addEventListener('resize', this.adjustPaperHeight);
    window.addEventListener(
      PUSH_SUBSCRIPTIONS_CHANGED_EVENT,
      this.onPushSubscriptionsChanged
    );
    this._loadManufacturerImages();
    this.refreshCategoryPushStatus();
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.adjustPaperHeight);
    window.removeEventListener(
      PUSH_SUBSCRIPTIONS_CHANGED_EVENT,
      this.onPushSubscriptionsChanged
    );
    this._manufacturerImageUrls.forEach(url => URL.revokeObjectURL(url));
  }

  _loadManufacturerImages = () => {
    window.socketManager.emit('getHerstellerImages', {}, (res) => {
      if (!res?.success || !res.manufacturers?.length) return;
      const map = new Map();
      for (const m of res.manufacturers) {
        if (!m.imageBuffer) continue;
        const blob = new Blob([m.imageBuffer], { type: 'image/avif' });
        const url = URL.createObjectURL(blob);
        map.set(m.id, url);
        this._manufacturerImageUrls.push(url);
      }
      this.setState({ manufacturerImages: map });
    });
  };

  componentDidUpdate(prevProps) {
    // Regenerate values when products, attributes, or language changes
    const productsChanged = this.props.products !== prevProps.products;
    const attributesChanged = this.props.attributes !== prevProps.attributes;
    const languageChanged = this.props.i18n && prevProps.i18n && this.props.i18n.language !== prevProps.i18n.language;
    const tFunctionChanged = this.props.t !== prevProps.t;
    
    if(languageChanged) {
      console.log('ProductFilters: Language changed, will update when new data arrives');
    }
    
    if(productsChanged || languageChanged || tFunctionChanged) {
      console.log('ProductFilters: Updating manufacturers and availability', {
        productsChanged,
        languageChanged,
        tFunctionChanged,
        productCount: this.props.products?.length
      });
      const uniqueManufacturerArray = this._getUniqueManufacturers(this.props.products);
      const availabilityValues = this._getAvailabilityValues(this.props.products);
      this.setState({uniqueManufacturerArray, availabilityValues});
    }
    
    if(attributesChanged || (languageChanged && this.props.attributes)) {
      console.log('ProductFilters: Updating attributes', {
        attributesChanged,
        languageChanged,
        attributeCount: this.props.attributes?.length,
        firstAttribute: this.props.attributes?.[0]
      });
      const attributeGroups = this._getAttributeGroups(this.props.attributes);
      this.setState({attributeGroups});
    }

    const prevCount = prevProps.products?.length || 0;
    const nextCount = this.props.products?.length || 0;
    if (
      prevProps.dataParam !== this.props.dataParam ||
      prevProps.dataType !== this.props.dataType ||
      prevProps.params?.categoryId !== this.props.params?.categoryId ||
      prevCount !== nextCount
    ) {
      this.refreshCategoryPushStatus();
    }
  }

  kKategorieNumber = () => {
    const { dataParam, dataType } = this.props;
    if (dataType !== 'category') return null;
    if (dataParam == null || dataParam === '') return null;
    const n = typeof dataParam === 'number' ? dataParam : parseInt(String(dataParam), 10);
    return Number.isFinite(n) && n > 0 ? n : null;
  };

  shouldShowCategoryPush = () =>
    (this.props.products?.length || 0) > MIN_ARTICLES_FOR_CATEGORY_PUSH;

  refreshCategoryPushStatus = async () => {
    const kKat = this.kKategorieNumber();
    if (!kKat || !this.shouldShowCategoryPush() || !isPushApiSupported()) {
      this.setState({
        pushInteractive: false,
        pushSubscribed: false,
        pushError: null,
      });
      return;
    }
    try {
      const cfg = await fetchPushConfiguration();
      if (!cfg.configured || !cfg.publicKey) {
        this.setState({ pushInteractive: false });
        return;
      }
      await registerPushServiceWorker();
      const registration = await navigator.serviceWorker.ready;
      const subscription = await registration.pushManager.getSubscription();
      if (!subscription) {
        this.setState({
          pushInteractive: true,
          pushSubscribed: false,
          pushError: null,
        });
        return;
      }
      const statusData = await categoryPushStatus(kKat, subscription.endpoint);
      this.setState({
        pushInteractive: true,
        pushSubscribed: parseSubscribedStatus(statusData),
        pushError: null,
      });
    } catch (e) {
      console.warn('ProductFilters: category push init failed', e);
      this.setState({ pushInteractive: false });
    }
  };

  handleCategoryPushClick = async () => {
    const t = this.props.t;
    if (!this.state.pushInteractive || this.state.pushBusy) return;
    const kKat = this.kKategorieNumber();
    if (!kKat || !this.shouldShowCategoryPush()) return;
    this.setState({ pushBusy: true, pushError: null });
    try {
      if (this.state.pushSubscribed) {
        const registration = await navigator.serviceWorker.ready;
        const subscription = await registration.pushManager.getSubscription();
        if (!subscription) {
          this.setState({ pushSubscribed: false, pushBusy: false });
          return;
        }
        const res = await categoryPushUnsubscribe(subscription.endpoint, kKat);
        if (parseSuccess(res)) {
          this.setState({ pushSubscribed: false });
          emitPushSubscriptionsChanged();
        } else {
          this.setState({
            pushError:
              res?.message ||
              res?.error ||
              (t ? t('productDialogs.pushNotifyError') : ''),
          });
        }
      } else {
        const perm = await Notification.requestPermission();
        if (perm !== 'granted') {
          this.setState({
            pushError: t ? t('productDialogs.pushNotifyPermissionDenied') : '',
            pushBusy: false,
          });
          return;
        }
        const cfg = await fetchPushConfiguration();
        if (!cfg.configured || !cfg.publicKey) {
          this.setState({
            pushError: t ? t('productDialogs.pushNotifyServerDisabled') : '',
            pushBusy: false,
          });
          return;
        }
        await registerPushServiceWorker();
        const subscription = await ensurePushSubscription(cfg.publicKey);
        const res = await categoryPushSubscribe(kKat, subscription);
        if (parseSuccess(res)) {
          this.setState({ pushSubscribed: true });
          emitPushSubscriptionsChanged();
        } else {
          this.setState({
            pushError:
              res?.message ||
              res?.error ||
              (t ? t('productDialogs.pushNotifyError') : ''),
          });
        }
      }
    } catch (e) {
      console.error('ProductFilters: category push', e);
      this.setState({
        pushError: e.message || (t ? t('productDialogs.pushNotifyError') : ''),
      });
    } finally {
      this.setState({ pushBusy: false });
    }
  };


  adjustPaperHeight = () => {
    const paperEl = document.getElementById('filters-paper');
    if (!paperEl) return;

    // No min-height on mobile — also clears inline style after resize from desktop
    if (window.innerWidth < 600) {
      paperEl.style.minHeight = '';
      return;
    }

    // Get viewport height
    const viewportHeight = window.innerHeight;
    
    // Get the offset top position of our paper element
    const paperTop = paperEl.getBoundingClientRect().top;
    
    // Estimate footer height (adjust as needed)
    const footerHeight = 80; // Reduce from 150px
    
    // Calculate available space and set height
    const availableHeight = viewportHeight - paperTop - footerHeight;
    // Add a smaller buffer margin to prevent scrolling but get closer to footer
    const heightWithBuffer = availableHeight - 20; // Reduce buffer from 50px to 20px
    paperEl.style.minHeight = `${heightWithBuffer}px`;
  }

  _getUniqueManufacturers = (products) => {
    const manufacturers = {};

    for (const product of products)
      if (!manufacturers[product.manufacturerId])
        manufacturers[product.manufacturerId] = product.manufacturer;

    const uniqueManufacturerArray = Object.entries(manufacturers)
      .filter(([_id, name]) => name !== null) // Filter out null names
      .map(([id, name]) => ({
        id: parseInt(id),
        name: name
      }))
      .sort((a, b) => a.name.localeCompare(b.name));
    return uniqueManufacturerArray;
  }

  _getAvailabilityValues = (products) => {
    const filters = [{id:1,name: this.props.t ? this.props.t('product.inStock') : 'auf Lager'}];
    
    for(const product of products){
      if(isNew(product.neu)){
        if(!filters.find(filter => filter.id == 2)) filters.push({id:2,name: this.props.t ? this.props.t('product.new') : 'Neu'});
      }
      if(!product.available && product.incomingDate){
        if(!filters.find(filter => filter.id == 3)) filters.push({id:3,name: this.props.t ? this.props.t('product.comingSoon') : 'Bald verfügbar'});       
      }
    }
    return filters
  }

  _getAttributeGroups = (attributes) => {
    const attributeGroups = {};
    if(attributes) for(const attribute of attributes) {
      if(!attributeGroups[attribute.cName]) attributeGroups[attribute.cName] = {name:attribute.cName, values:{}};
      attributeGroups[attribute.cName].values[attribute.kMerkmalWert] = {id:attribute.kMerkmalWert, name:attribute.cWert};
    }
    return attributeGroups;
  }

  generateAttributeFilters = () => {
    const filters = [];
    const sortedAttributeGroups = Object.values(this.state.attributeGroups)
      .sort((a, b) => a.name.localeCompare(b.name));

    for(const attributeGroup of sortedAttributeGroups) {
      const filter = (
        <Filter
          key={`attr-filter-${attributeGroup.name}`}
          title={attributeGroup.name}
          options={Object.values(attributeGroup.values)}
          filterType="attribute"
          products={this.props.products}
          filteredProducts={this.props.filteredProducts}
          attributes={this.props.attributes}
          onFilterChange={(msg)=>{
            if(msg.value) {
              setSessionSetting(`filter_${msg.type}_${msg.name}`, 'true');
            } else {
              removeSessionSetting(`filter_${msg.type}_${msg.name}`);
            }
            this.props.onFilterChange();
          }}
        />
      )
      filters.push(filter);
    }
    return filters;
  }

  render() {
    const kKategorie = this.kKategorieNumber();
    const showCategoryPush = kKategorie && this.shouldShowCategoryPush();
    const {
      pushInteractive,
      pushSubscribed,
      pushBusy,
      pushError,
    } = this.state;
    const pushDisabledHint =
      showCategoryPush && !pushInteractive && !pushBusy
        ? isPushApiSupported()
          ? this.props.t
            ? this.props.t('productDialogs.pushNotifyServerDisabled')
            : ''
          : this.props.t
            ? this.props.t('filters.notifyNewArticlesBrowserUnsupported')
            : 'Ihr Browser unterstützt keine Push-Benachrichtigungen.'
        : '';

    return (
      <Box
        sx={{
          px: { xs: 2, sm: 0 },
          pt: { xs: 2, sm: 0 },
          /* Room below Paper so elevation shadow isn’t clipped by grid/parent */
          pb: { xs: 2, sm: 2 },
          overflow: 'visible',
          /* Same green as ProductList / product strip mobile (#e8f5e8), not theme background.default (#C8E6C9) */
          bgcolor: { xs: '#e8f5e8', sm: 'transparent' },
        }}
      >
      <Paper 
        id="filters-paper"
        elevation={1}
        sx={{ 
          p: { xs: 2.5, sm: 2.5 }, 
          mx: { sm: 'auto' },
          maxWidth: '100%',
          borderRadius: 2,
          bgcolor: 'background.paper',
          display: 'flex',
          flexDirection: 'column',
          border: { xs: 'none', sm: 'inherit' },
          boxSizing: 'border-box',
          overflow: 'visible',
        }}
      >

{this.props.dataType == 'category' && (
            <Box sx={{ mb: 4 }}>
              <Typography
                variant="h3"
                component="h1"
                sx={{
                  mb: showCategoryPush ? 1.5 : 4,
                  fontFamily: 'SwashingtonCP',
                  color: 'primary.main',
                }}
              >
                {this.props.categoryName}
              </Typography>
              {showCategoryPush && (
                <Box sx={{ width: '100%' }}>
                  <Tooltip title={pushDisabledHint} arrow>
                    <span style={{ display: 'block', width: '100%' }}>
                      <Button
                        fullWidth
                        variant="outlined"
                        color="inherit"
                        size="small"
                        onClick={this.handleCategoryPushClick}
                        disabled={!pushInteractive || pushBusy}
                        startIcon={
                          pushBusy ? (
                            <CircularProgress size={14} sx={{ color: 'inherit' }} />
                          ) : pushSubscribed ? (
                            <NotificationsActiveIcon sx={{ fontSize: 18, color: '#2e7d32' }} />
                          ) : (
                            <NotificationsIcon sx={{ fontSize: 18, color: 'rgba(0,0,0,0.65)' }} />
                          )
                        }
                        sx={{
                          borderRadius: 1,
                          fontWeight: 600,
                          fontSize: '0.7rem',
                          lineHeight: 1.2,
                          backgroundColor: '#fff',
                          color: 'text.primary',
                          border: '1px solid',
                          borderColor: 'divider',
                          boxShadow: 'none',
                          whiteSpace: 'normal',
                          textAlign: 'center',
                          py: 0.4,
                          px: 0.75,
                          minHeight: 28,
                          '& .MuiButton-label': {
                            whiteSpace: 'normal',
                            lineHeight: 1.2,
                          },
                          '& .MuiButton-startIcon': {
                            mr: 0.5,
                            '& > *:nth-of-type(1)': { fontSize: 18 },
                          },
                          '&:hover': {
                            backgroundColor: 'grey.50',
                            borderColor: 'divider',
                            boxShadow: 'none',
                          },
                          '&.Mui-disabled': {
                            backgroundColor: '#fff',
                            color: 'action.disabled',
                            borderColor: 'action.disabledBackground',
                          },
                        }}
                      >
                        {this.props.t
                          ? this.props.t('filters.notifyNewArticles')
                          : 'Bei neuen Artikeln benachrichtigen'}
                      </Button>
                    </span>
                  </Tooltip>
                  {pushError && (
                    <Typography
                      variant="caption"
                      color="error"
                      sx={{ display: 'block', mt: 0.5, textAlign: 'center' }}
                    >
                      {pushError}
                    </Typography>
                  )}
                </Box>
              )}
            </Box>
          )}


        {this.props.products.length > 0 && (
          <><Filter 
          title={this.props.t ? this.props.t('filters.availability') : 'Verfügbarkeit'}
          options={this.state.availabilityValues}
          searchParams={this.props.searchParams}
          products={this.props.products}
          filteredProducts={this.props.filteredProducts}
          attributes={this.props.attributes}
          filterType="availability"
          onFilterChange={(msg)=>{
            
            if(msg.resetAll) {
              sessionStorage.removeItem('filter_availability');
              clearAllSessionSettings();
              this.props.onFilterChange();
              return;
            }

            if(!msg.value) {
              console.log('msg',msg);
              if(msg.name == '1') sessionStorage.setItem('filter_availability', msg.name);
              if(msg.name != '1') removeSessionSetting(`filter_${msg.type}_${msg.name}`);
              //this.props.navigate({
              //  pathname: this.props.location.pathname,
              //  search: `?inStock=${msg.name}`
              //}); 
            } else {
              if(msg.name == '1') sessionStorage.removeItem('filter_availability');
              if(msg.name != '1') setSessionSetting(`filter_${msg.type}_${msg.name}`, 'true');
              console.log('msg',msg);
              //this.props.navigate({
              //  pathname: this.props.location.pathname,
              //  search: this.props.location.search.replace(/inStock=[^&]*/, '')
              //});
            }
            
            this.props.onFilterChange();
          
          
          }}
        />

        {this.generateAttributeFilters()}

        <Filter 
          title={this.props.t ? this.props.t('filters.manufacturer') : 'Hersteller'}
          options={this.state.uniqueManufacturerArray}
          filterType="manufacturer"
          products={this.props.products}
          filteredProducts={this.props.filteredProducts}
          attributes={this.props.attributes}
          manufacturerImages={this.state.manufacturerImages}
          onFilterChange={(msg)=>{ 
            if(msg.value) {
              setSessionSetting(`filter_${msg.type}_${msg.name}`, 'true');
            } else {
              removeSessionSetting(`filter_${msg.type}_${msg.name}`);
            }
            this.props.onFilterChange();
          }}
        />
        </>)}
      </Paper>
      </Box>
    );
  }
}

export default withRouter(withI18n()(ProductFilters)); 