import React from 'react';
import { Link } from "react-router-dom";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import ChevronLeft from "@mui/icons-material/ChevronLeft";
import ChevronRight from "@mui/icons-material/ChevronRight";
import Product from "./Product.js";
import { withTranslation } from 'react-i18next';
import { withLanguage } from '../i18n/withTranslation.js';
import {
  getProductCarouselItemStridePx,
  PRODUCT_CARD_WIDTH_SM_PX,
  PRODUCT_CARD_WIDTH_XS_PX,
} from "../utils/productCardLayout.js";
const AUTO_SCROLL_SPEED = 0.5; // px per frame (~60fps, so ~30px/sec)
const AUTOSCROLL_RESTART_DELAY = 5000; // 5 seconds of inactivity before restarting autoscroll
const SCROLLBAR_FLASH_DURATION = 3000; // 3 seconds to show the virtual scrollbar

const CAROUSEL_LOG = "[ProductCarousel]";

function logCarousel(phase, detail) {
  try {
    console.log(CAROUSEL_LOG, phase, detail != null ? detail : "");
  } catch {
    /* ignore */
  }
}

/** Debug summary of getCategoryProducts callback / socket payload. */
function summarizeResponse(response, maxProducts = 8) {
  if (response == null) {
    return { type: "null" };
  }
  if (typeof response !== "object") {
    return { type: typeof response, value: response };
  }
  const keys = Object.keys(response);
  const products = response.products;
  const n = Array.isArray(products) ? products.length : null;
  const sample =
    Array.isArray(products) && products.length > 0
      ? products.slice(0, maxProducts).map((p) => ({
          id: p?.id,
          seoName: p?.seoName,
          available: p?.available,
          availableSupplier: p?.availableSupplier,
          hasPictureList: Boolean(
            p?.pictureList &&
              (typeof p.pictureList === "string"
                ? p.pictureList.trim().length > 0
                : Array.isArray(p.pictureList)
                  ? p.pictureList.length > 0
                  : false)
          ),
        }))
      : [];
  return { keys, productsLength: n, sample };
}

function productHasImage(p) {
  const pl = p?.pictureList;
  if (!pl) return false;
  if (typeof pl === "string") return pl.trim().length > 0;
  if (Array.isArray(pl)) return pl.length > 0;
  return false;
}

class ProductCarousel extends React.Component {
  _isMounted = false;
  products = [];
  originalProducts = [];
  animationFrame = null;
  autoScrollActive = true;
  translateX = 0;
  inactivityTimer = null;
  scrollbarTimer = null;

  constructor(props) {
    super(props);
    const { i18n } = props;

    this.state = {
      products: [],
      currentLanguage: (i18n && i18n.language) || 'de',
      showScrollbar: false,
      itemStride:
        typeof window !== "undefined"
          ? getProductCarouselItemStridePx()
          : PRODUCT_CARD_WIDTH_SM_PX + 16,
    };

    this.carouselTrackRef = React.createRef();
  }

  handleCarouselResize = () => {
    if (!this._isMounted) return;
    const next = getProductCarouselItemStridePx();
    if (next !== this.state.itemStride) {
      this.translateX = 0;
      this.updateTrackTransform();
      this.setState({ itemStride: next });
    }
  };

  componentDidMount() {
    this._isMounted = true;
    if (typeof window !== "undefined") {
      window.addEventListener("resize", this.handleCarouselResize);
      this.setState({ itemStride: getProductCarouselItemStridePx() });
    }
    const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n.language;

    logCarousel("mount", {
      categoryId: this.props.categoryId,
      language: currentLanguage,
      filter_availability:
        typeof sessionStorage !== "undefined"
          ? sessionStorage.getItem("filter_availability")
          : "(no sessionStorage)",
    });
    this.loadProducts(currentLanguage);
  }

  categoryIdsEqual(a, b) {
    if (Array.isArray(a) && Array.isArray(b)) {
      return a.length === b.length && a.every((v, i) => v === b[i]);
    }
    return a === b;
  }

  componentDidUpdate(prevProps) {
    const lang = this.props.languageContext?.currentLanguage || this.props.i18n.language;
    const langChanged =
      prevProps.languageContext?.currentLanguage !==
      this.props.languageContext?.currentLanguage;
    const catChanged = !this.categoryIdsEqual(
      prevProps.categoryId,
      this.props.categoryId
    );
    if (langChanged || catChanged) {
      logCarousel("didUpdate:reload", {
        langChanged,
        catChanged,
        prevCategoryId: prevProps.categoryId,
        categoryId: this.props.categoryId,
        language: lang,
      });
    }
    if (langChanged) {
      this.setState({ products: [] }, () => {
        this.loadProducts(lang);
      });
      return;
    }
    if (catChanged) {
      this.setState({ products: [] }, () => {
        this.loadProducts(lang);
      });
    }
  }

  /** Virtual slugs go to the socket as strings; other ids pass through. */
  normalizeSocketCategoryId(id) {
    if (id === "neu" || id === "bald") return id;
    return id;
  }

  /**
   * neu: stub only (no `full`). bald: `full: true` — one emit ack with the full list.
   * Carousel does not subscribe to `productList:*` (no second update).
   */
  buildGetCategoryProductsPayload(id, language) {
    const slug = this.normalizeSocketCategoryId(id);
    const payload = {
      categoryId: slug,
      language,
      requestTranslation: language === "de" ? false : true,
    };
    if (slug === "bald") {
      payload.full = true;
    }
    return payload;
  }

  /** Single getCategoryProducts response (emit ack only). */
  emitGetCategoryProductsOnce = (rawId, language, onAck) => {
    const slug = this.normalizeSocketCategoryId(rawId);
    const payload = this.buildGetCategoryProductsPayload(rawId, language);
    logCarousel("emit getCategoryProducts (ack only)", { slug, payload });
    window.socketManager.emit("getCategoryProducts", payload, (response) => {
      logCarousel("getCategoryProducts CALLBACK", {
        slug,
        summary: summarizeResponse(response),
      });
      onAck(response);
    });
  };

  finalizeCarouselList = (products) => {
    if (!this._isMounted) {
      logCarousel("finalizeCarouselList:skip (unmounted)", {
        incomingLen: products?.length,
      });
      return;
    }
    if (!products || products.length === 0) {
      logCarousel("finalizeCarouselList:skip (empty)", {});
      return;
    }
    const shuffledProducts = this.shuffleArray(products).slice(0, 15);
    logCarousel("finalizeCarouselList:ok", {
      inputCount: products.length,
      afterShuffleCap15: shuffledProducts.length,
      ids: shuffledProducts.map((p) => p?.id),
    });

    this.originalProducts = shuffledProducts;
    this.products = [...shuffledProducts, ...shuffledProducts];
    this.setState({ products: this.products });
    this.startAutoScroll();
  };

  processLoadedProducts = (rawProducts, sourceTag = "processLoadedProducts") => {
    if (!this._isMounted) {
      logCarousel(`${sourceTag}:skip (unmounted)`, {
        rawLen: rawProducts?.length,
      });
      return;
    }
    if (!rawProducts || rawProducts.length === 0) {
      logCarousel(`${sourceTag}:skip (empty products)`, {});
      return;
    }
    logCarousel(`${sourceTag}:incoming`, {
      count: rawProducts.length,
      idsSample: rawProducts.slice(0, 12).map((p) => p?.id),
    });
    this.finalizeCarouselList(rawProducts.slice());
  };

  /** Merge neu + bald; neu ids win on duplicate. */
  processNeuAndBaldMerged = (neuRaw, baldRaw) => {
    const neuList = neuRaw || [];
    const baldList = baldRaw || [];

    const seen = new Set();
    const merged = [];
    for (const p of neuList) {
      if (p && p.id != null && !seen.has(p.id)) {
        seen.add(p.id);
        merged.push(p);
      }
    }
    let baldWithImage = 0;
    for (const p of baldList) {
      if (!p || p.id == null || seen.has(p.id)) continue;
      if (!productHasImage(p)) continue;
      baldWithImage += 1;
      seen.add(p.id);
      merged.push(p);
    }

    logCarousel("processNeuAndBaldMerged:counts", {
      neu: neuList.length,
      bald: baldList.length,
      baldWithImage,
      mergedUnique: merged.length,
      neuIdsSample: neuList.slice(0, 8).map((p) => p?.id),
      baldIdsSample: baldList.slice(0, 8).map((p) => p?.id),
    });

    if (merged.length === 0) {
      logCarousel("processNeuAndBaldMerged:skip (merged empty)", {});
      return;
    }
    this.finalizeCarouselList(merged);
  };

  loadProducts = (language) => {
    const { categoryId } = this.props;
    const ids = Array.isArray(categoryId) ? categoryId : [categoryId];
    const filterAvailability =
      typeof sessionStorage !== "undefined"
        ? sessionStorage.getItem("filter_availability")
        : null;

    logCarousel("loadProducts:start", {
      language,
      categoryId,
      ids,
      filter_availability: filterAvailability,
    });

    if (ids.length === 1) {
      const slug = this.normalizeSocketCategoryId(ids[0]);
      this.emitGetCategoryProductsOnce(ids[0], language, (response) => {
        let products = response?.products ?? [];
        if (slug === "bald") {
          const before = products.length;
          products = products.filter(productHasImage);
          logCarousel("loadProducts:single:bald filter image", {
            before,
            after: products.length,
          });
        }
        if (products.length > 0) {
          this.processLoadedProducts(products, "single");
        } else {
          logCarousel("loadProducts:single: empty", { slug });
        }
      });
      return;
    }

    const neuBaldMode =
      ids.length === 2 &&
      ids.map((x) => this.normalizeSocketCategoryId(x)).sort().join(",") ===
        "bald,neu";

    if (neuBaldMode) {
      logCarousel("loadProducts:mode neu+bald (stub neu + full bald → merge → shuffle → max 15)", {
        ids,
      });

      let neuProducts = null;
      let baldProducts = null;

      const tryMerge = () => {
        if (neuProducts === null || baldProducts === null) {
          return;
        }
        logCarousel("loadProducts:neu+bald merge inputs", {
          neuLen: neuProducts.length,
          baldLen: baldProducts.length,
        });
        this.processNeuAndBaldMerged(neuProducts, baldProducts);
      };

      this.emitGetCategoryProductsOnce("neu", language, (response) => {
        neuProducts = response?.products ?? [];
        tryMerge();
      });
      this.emitGetCategoryProductsOnce("bald", language, (response) => {
        baldProducts = response?.products ?? [];
        tryMerge();
      });
      return;
    }

    logCarousel("loadProducts:mode generic merge", { ids });

    const mergedById = new Map();
    let remaining = ids.length;

    const onResponse = (response, idForLog) => {
      logCarousel("loadProducts:merge CALLBACK", {
        id: idForLog,
        summary: summarizeResponse(response),
      });
      let products = response?.products ?? [];
      if (this.normalizeSocketCategoryId(idForLog) === "bald") {
        products = products.filter(productHasImage);
      }
      if (products.length > 0) {
        for (const p of products) {
          if (p && p.id != null && !mergedById.has(p.id)) {
            mergedById.set(p.id, p);
          }
        }
      }
      remaining -= 1;
      if (remaining === 0) {
        logCarousel("loadProducts:merge complete", {
          unique: mergedById.size,
          idsSample: Array.from(mergedById.keys()).slice(0, 15),
        });
        this.processLoadedProducts(
          Array.from(mergedById.values()),
          "genericMerge"
        );
      }
    };

    ids.forEach((id) => {
      this.emitGetCategoryProductsOnce(id, language, (response) => {
        onResponse(response, id);
      });
    });
  }

  componentWillUnmount() {
    this._isMounted = false;
    if (typeof window !== "undefined") {
      window.removeEventListener("resize", this.handleCarouselResize);
    }
    this.stopAutoScroll();
    this.clearInactivityTimer();
    this.clearScrollbarTimer();
  }

  startAutoScroll = () => {
    this.autoScrollActive = true;
    if (!this.animationFrame) {
      this.animationFrame = requestAnimationFrame(this.handleAutoScroll);
    }
  };

  stopAutoScroll = () => {
    this.autoScrollActive = false;
    if (this.animationFrame) {
      cancelAnimationFrame(this.animationFrame);
      this.animationFrame = null;
    }
  };

  clearInactivityTimer = () => {
    if (this.inactivityTimer) {
      clearTimeout(this.inactivityTimer);
      this.inactivityTimer = null;
    }
  };

  clearScrollbarTimer = () => {
    if (this.scrollbarTimer) {
      clearTimeout(this.scrollbarTimer);
      this.scrollbarTimer = null;
    }
  };

  startInactivityTimer = () => {
    this.clearInactivityTimer();
    this.inactivityTimer = setTimeout(() => {
      if (this._isMounted) {
        this.startAutoScroll();
      }
    }, AUTOSCROLL_RESTART_DELAY);
  };

  showScrollbarFlash = () => {
    this.clearScrollbarTimer();
    this.setState({ showScrollbar: true });

    this.scrollbarTimer = setTimeout(() => {
      if (this._isMounted) {
        this.setState({ showScrollbar: false });
      }
    }, SCROLLBAR_FLASH_DURATION);
  };

  handleAutoScroll = () => {
    if (!this.autoScrollActive || this.originalProducts.length === 0) return;

    this.translateX -= AUTO_SCROLL_SPEED;
    this.updateTrackTransform();

    const { itemStride } = this.state;
    const originalItemCount = this.originalProducts.length;
    const maxScroll = itemStride * originalItemCount;

    // Check if we've scrolled past the first set of items
    if (Math.abs(this.translateX) >= maxScroll) {
      // Reset to beginning seamlessly
      this.translateX = 0;
      this.updateTrackTransform();
    }

    this.animationFrame = requestAnimationFrame(this.handleAutoScroll);
  };

  updateTrackTransform = () => {
    if (this.carouselTrackRef.current) {
      this.carouselTrackRef.current.style.transform = `translateX(${this.translateX}px)`;
    }
  };

  handleLeftClick = () => {
    this.stopAutoScroll();
    this.scrollBy(1);
    this.showScrollbarFlash();
    this.startInactivityTimer();
  };

  handleRightClick = () => {
    this.stopAutoScroll();
    this.scrollBy(-1);
    this.showScrollbarFlash();
    this.startInactivityTimer();
  };

  scrollBy = (direction) => {
    if (this.originalProducts.length === 0) return;

    // direction: 1 = left (scroll content right), -1 = right (scroll content left)
    const { itemStride } = this.state;
    const originalItemCount = this.originalProducts.length;
    const maxScroll = itemStride * originalItemCount;

    this.translateX += direction * itemStride;

    // Handle wrap-around when scrolling left (positive translateX)
    if (this.translateX > 0) {
      this.translateX = -(maxScroll - itemStride);
    }
    // Handle wrap-around when scrolling right (negative translateX beyond limit)
    else if (Math.abs(this.translateX) >= maxScroll) {
      this.translateX = 0;
    }

    this.updateTrackTransform();

    // Force scrollbar to update immediately after wrap-around
    if (this.state.showScrollbar) {
      this.forceUpdate();
    }
  };

  renderVirtualScrollbar = () => {
    if (!this.state.showScrollbar || this.originalProducts.length === 0) {
      return null;
    }

    const { itemStride } = this.state;
    const originalItemCount = this.originalProducts.length;
    const viewportWidth =
      typeof window !== "undefined"
        ? Math.min(1080, Math.max(0, window.innerWidth - 56))
        : 1080;
    const itemsInView = Math.max(1, Math.floor(viewportWidth / itemStride));

    // Calculate which item is currently at the left edge (first visible)
    let currentItemIndex;

    if (this.translateX === 0) {
      currentItemIndex = 0;
    } else if (this.translateX > 0) {
      const maxScroll = itemStride * originalItemCount;
      const effectivePosition = maxScroll + this.translateX;
      currentItemIndex = Math.floor(effectivePosition / itemStride);
    } else {
      currentItemIndex = Math.floor(Math.abs(this.translateX) / itemStride);
    }

    // Ensure we stay within bounds
    currentItemIndex = Math.max(0, Math.min(currentItemIndex, originalItemCount - 1));

    // Calculate scrollbar position
    const lastPossibleFirstItem = Math.max(0, originalItemCount - itemsInView);
    const thumbPosition = lastPossibleFirstItem > 0 ? Math.min((currentItemIndex / lastPossibleFirstItem) * 100, 100) : 0;

    return (
      <div
        className="virtual-scrollbar"
        style={{
          position: 'absolute',
          bottom: '5px',
          left: '50%',
          transform: 'translateX(-50%)',
          width: '200px',
          height: '4px',
          backgroundColor: 'rgba(0, 0, 0, 0.1)',
          borderRadius: '2px',
          zIndex: 1000,
          opacity: this.state.showScrollbar ? 1 : 0,
          transition: 'opacity 0.3s ease-in-out'
        }}
      >
        <div
          className="scrollbar-thumb"
          style={{
            position: 'absolute',
            top: '0',
            left: `${thumbPosition}%`,
            width: '20px',
            height: '4px',
            backgroundColor: 'rgba(0, 0, 0, 0.5)',
            borderRadius: '2px',
            transform: 'translateX(-50%)',
            transition: 'left 0.2s ease-out'
          }}
        />
      </div>
    );
  };

  render() {
    const { t, title } = this.props;
    const { products } = this.state;

    if (!products || products.length === 0) {
      return null;
    }

    return (
      <Box sx={{ mt: 3 }}>
        <Box
          component={Link}
          to="/Kategorie/neu"
          sx={{
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            textDecoration: "none",
            color: "primary.main",
            mb: 2,
            transition: "all 0.3s ease",
            "&:hover": {
              transform: "translateX(5px)",
              color: "primary.dark"
            }
          }}
        >
          <Typography
            variant="h4"
            component="span"
            sx={{
              fontFamily: "SwashingtonCP",
              textShadow: "3px 3px 10px rgba(0, 0, 0, 0.4)"
            }}
          >
            {title || t('product.new')}
          </Typography>
          <ChevronRight sx={{ fontSize: "2.5rem", ml: 1 }} />
        </Box>

        <div
          className="product-carousel-wrapper"
          style={{
            position: 'relative',
            overflowX: 'hidden',
            overflowY: 'visible',
            width: '100%',
            maxWidth: '1200px',
            margin: '0 auto',
            padding: '0 20px',
            boxSizing: 'border-box'
          }}
        >
          {/* Left Arrow */}
          <IconButton
            aria-label="Vorherige Produkte anzeigen"
            onClick={this.handleLeftClick}
            style={{
              position: 'absolute',
              top: '50%',
              left: '8px',
              transform: 'translateY(-50%)',
              zIndex: 1000,
              backgroundColor: 'rgba(255, 255, 255, 0.9)',
              boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
              width: '48px',
              height: '48px',
              borderRadius: '50%'
            }}
          >
            <ChevronLeft />
          </IconButton>

          {/* Right Arrow */}
          <IconButton
            aria-label="Nächste Produkte anzeigen"
            onClick={this.handleRightClick}
            style={{
              position: 'absolute',
              top: '50%',
              right: '8px',
              transform: 'translateY(-50%)',
              zIndex: 1000,
              backgroundColor: 'rgba(255, 255, 255, 0.9)',
              boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
              width: '48px',
              height: '48px',
              borderRadius: '50%'
            }}
          >
            <ChevronRight />
          </IconButton>

          <div
            className="product-carousel-container"
            style={{
              position: 'relative',
              overflowX: 'hidden',
              overflowY: 'visible',
              padding: '20px 0',
              width: '100%',
              maxWidth: '1080px',
              margin: '0 auto',
              zIndex: 1,
              boxSizing: 'border-box'
            }}
          >
            <div
              className="product-carousel-track"
              ref={this.carouselTrackRef}
              style={{
                display: 'flex',
                gap: '16px',
                transition: 'none',
                alignItems: 'flex-start',
                width: 'fit-content',
                overflow: 'visible',
                position: 'relative',
                transform: 'translateX(0px)',
                margin: '0 auto'
              }}
            >
              {products.map((product, index) => (
                <Box
                  key={`${product.id}-${index}`}
                  className="product-carousel-item"
                  sx={{
                    flex: {
                      xs: `0 0 ${PRODUCT_CARD_WIDTH_XS_PX}px`,
                      sm: `0 0 ${PRODUCT_CARD_WIDTH_SM_PX}px`,
                    },
                    width: { xs: PRODUCT_CARD_WIDTH_XS_PX, sm: PRODUCT_CARD_WIDTH_SM_PX },
                    maxWidth: { xs: PRODUCT_CARD_WIDTH_XS_PX, sm: PRODUCT_CARD_WIDTH_SM_PX },
                    minWidth: { xs: PRODUCT_CARD_WIDTH_XS_PX, sm: PRODUCT_CARD_WIDTH_SM_PX },
                    boxSizing: "border-box",
                    position: "relative",
                  }}
                >
                  <Product
                    id={product.id}
                    name={product.name}
                    seoName={product.seoName}
                    price={product.price}
                    currency={product.currency}
                    available={product.available}
                    manufacturer={product.manufacturer}
                    vat={product.vat}
                    cGrundEinheit={product.cGrundEinheit}
                    fGrundPreis={product.fGrundPreis}
                    incoming={product.incomingDate}
                    neu={product.neu}
                    thc={product.thc}
                    floweringWeeks={product.floweringWeeks}
                    versandklasse={product.versandklasse}
                    weight={product.weight}
                    pictureList={product.pictureList}
                    availableSupplier={product.availableSupplier}
                    komponenten={product.komponenten}
                    rebate={product.rebate}
                    categoryId={product.kategorien ? product.kategorien.split(',')[0] : undefined}
                    priority={index < 6 ? 'high' : 'auto'}
                    t={t}
                  />
                </Box>
              ))}
            </div>

            {/* Virtual Scrollbar */}
            {this.renderVirtualScrollbar()}
          </div>
        </div>
      </Box>
    );
  }

  // Shuffle array using Fisher-Yates algorithm
  shuffleArray(array) {
    const shuffled = [...array];
    for (let i = shuffled.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
    }
    return shuffled;
  }
}

export default withTranslation()(withLanguage(ProductCarousel));

