'use client';

import { useEffect, useState, useMemo, useRef } from 'react';
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/components/ui/accordion';
import { fetchMarketIndices } from '@/app/api/fund';
import { ChevronRightIcon } from 'lucide-react';
import { SettingsIcon } from './Icons';
import { cn } from '@/lib/utils';
import MarketSettingModal from './MarketSettingModal';

/** 简单伪随机，用于稳定迷你图形状 */
function seeded(seed) {
  return () => {
    seed = (seed * 9301 + 49297) % 233280;
    return seed / 233280;
  };
}

/** 迷你走势：优先展示当日分时数据，失败时退回占位折线 */
function MiniTrendLine({ changePercent, code, className }) {
  const isDown = changePercent <= 0;
  const width = 80;
  const height = 28;
  const pad = 3;
  const innerH = height - 2 * pad;
  const innerW = width - 2 * pad;

  // 占位伪走势（无真实历史数据）
  const fallbackPath = useMemo(() => {
    const points = 12;
    const rnd = seeded(Math.abs(Math.floor(changePercent * 100)) + 1);
    const arr = Array.from({ length: points }, (_, i) => {
      const t = i / (points - 1);
      const x = pad + t * innerW;
      const y = isDown
        ? pad + innerH * (1 - t * 0.6) - (rnd() * 4 - 2)
        : pad + innerH * (0.4 + t * 0.6) + (rnd() * 4 - 2);
      return [x, Math.max(pad, Math.min(height - pad, y))];
    });
    return arr.map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x} ${y}`).join(' ');
  }, [changePercent, isDown, innerH, innerW, pad, height]);

  // 当日分时真实走势 path
  const [realPath, setRealPath] = useState(null);

  useEffect(() => {
    if (!code || typeof window === 'undefined' || typeof document === 'undefined') {
      setRealPath(null);
      return;
    }

    let cancelled = false;
    const varName = `min_data_${code}`;
    const url = `https://web.ifzq.gtimg.cn/appstock/app/minute/query?_var=${varName}&code=${code}&_=${Date.now()}`;

    const script = document.createElement('script');
    script.src = url;
    script.async = true;

    const cleanup = () => {
      if (document.body && document.body.contains(script)) {
        document.body.removeChild(script);
      }
      try {
        if (window[varName]) {
          delete window[varName];
        }
      } catch (e) {
        // ignore
      }
    };

    script.onload = () => {
      if (cancelled) {
        cleanup();
        return;
      }
      try {
        const raw = window[varName];
        const series =
          raw &&
          raw.data &&
          raw.data[code] &&
          raw.data[code].data &&
          Array.isArray(raw.data[code].data.data)
            ? raw.data[code].data.data
            : null;
        if (!series || !series.length) {
          setRealPath(null);
          return;
        }

        // 解析 "HHMM price volume amount" 行，只关心 price
        const points = series
          .map((row) => {
            const parts = String(row).split(' ');
            const price = parseFloat(parts[1]);
            if (!Number.isFinite(price)) return null;
            return { price };
          })
          .filter(Boolean);

        if (!points.length) {
          setRealPath(null);
          return;
        }

        const minP = points.reduce((m, p) => (p.price < m ? p.price : m), points[0].price);
        const maxP = points.reduce((m, p) => (p.price > m ? p.price : m), points[0].price);
        const span = maxP - minP || 1;

        const n = points.length;
        const pathPoints = points.map((p, idx) => {
          const t = n > 1 ? idx / (n - 1) : 0;
          const x = pad + t * innerW;
          const norm = (p.price - minP) / span;
          const y = pad + (1 - norm) * innerH;
          return [x, Math.max(pad, Math.min(height - pad, y))];
        });

        const d = pathPoints
          .map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x} ${y}`)
          .join(' ');
        setRealPath(d);
      } finally {
        cleanup();
      }
    };

    script.onerror = () => {
      if (!cancelled) {
        setRealPath(null);
      }
      cleanup();
    };

    document.body.appendChild(script);

    return () => {
      cancelled = true;
      cleanup();
    };
  }, [code, height, innerH, innerW, pad]);

  const d = realPath || fallbackPath;
  return (
    <svg
      width={width}
      height={height}
      className={cn('overflow-visible', className)}
      aria-hidden
    >
      <path
        d={d}
        fill="none"
        stroke="currentColor"
        strokeWidth="1.5"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={isDown ? 'text-[var(--success)]' : 'text-[var(--danger)]'}
      />
    </svg>
  );
}

function IndexCard({ item }) {
  const isUp = item.change >= 0;
  const colorClass = isUp ? 'text-[var(--danger)]' : 'text-[var(--success)]';
  return (
    <div
      className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-1.5 flex flex-col gap-0.5 w-full"
    >
      <div className="text-xs font-medium text-[var(--foreground)] truncate">{item.name}</div>
      <div className={cn('text-sm font-semibold tabular-nums', colorClass)}>
        {item.price.toFixed(2)}
      </div>
      <div className={cn('text-xs tabular-nums', colorClass)}>
        {(item.change >= 0 ? '+' : '') + item.change.toFixed(2)}{' '}
        {(item.changePercent >= 0 ? '+' : '') + item.changePercent.toFixed(2)}%
      </div>
      <div className="mt-0.5 flex items-center justify-center opacity-80">
        <MiniTrendLine changePercent={item.changePercent} code={item.code} />
      </div>
    </div>
  );
}

// 默认展示：上证指数、深证成指、创业板指
const DEFAULT_SELECTED_CODES = ['sh000001', 'sz399001', 'sz399006'];

export default function MarketIndexAccordion({
  navbarHeight = 0,
  onHeightChange,
  isMobile,
  onCustomSettingsChange,
}) {
  const [indices, setIndices] = useState([]);
  const [loading, setLoading] = useState(true);
  const [openValue, setOpenValue] = useState('');
  const [selectedCodes, setSelectedCodes] = useState([]);
  const [settingOpen, setSettingOpen] = useState(false);
  const [tickerIndex, setTickerIndex] = useState(0);
  const rootRef = useRef(null);

  useEffect(() => {
    const el = rootRef.current;
    if (!el || typeof onHeightChange !== 'function') return;
    const ro = new ResizeObserver((entries) => {
      const entry = entries[0];
      if (entry) onHeightChange(entry.contentRect.height);
    });
    ro.observe(el);
    onHeightChange(el.getBoundingClientRect().height);
    return () => {
      ro.disconnect();
      onHeightChange(0);
    };
  }, [onHeightChange, loading, indices.length]);

  useEffect(() => {
    let cancelled = false;
    fetchMarketIndices()
      .then((data) => {
        if (!cancelled) setIndices(Array.isArray(data) ? data : []);
      })
      .catch(() => {
        if (!cancelled) setIndices([]);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => { cancelled = true; };
  }, []);

  // 初始化选中指数（本地偏好 > 默认集合）
  useEffect(() => {
    if (!indices.length || typeof window === 'undefined') return;
    try {
      const stored = window.localStorage.getItem('marketIndexSelected');
      const availableCodes = new Set(indices.map((it) => it.code));
      if (stored) {
        const parsed = JSON.parse(stored);
        if (Array.isArray(parsed)) {
          const filtered = parsed.filter((c) => availableCodes.has(c));
          if (filtered.length) {
            setSelectedCodes(filtered);
            return;
          }
        }
      }
      const defaults = DEFAULT_SELECTED_CODES.filter((c) => availableCodes.has(c));
      setSelectedCodes(defaults.length ? defaults : indices.map((it) => it.code).slice(0, 3));
    } catch {
      setSelectedCodes(indices.map((it) => it.code).slice(0, 3));
    }
  }, [indices]);

  // 持久化用户选择
  useEffect(() => {
    if (typeof window === 'undefined') return;
    if (!selectedCodes.length) return;
    try {
      // 本地首选 key：独立存储，便于快速读取
      window.localStorage.setItem('marketIndexSelected', JSON.stringify(selectedCodes));

      // 同步到 customSettings，便于云端同步
      const raw = window.localStorage.getItem('customSettings');
      const parsed = raw ? JSON.parse(raw) : {};
      const next = parsed && typeof parsed === 'object' ? { ...parsed, marketIndexSelected: selectedCodes } : { marketIndexSelected: selectedCodes };
      window.localStorage.setItem('customSettings', JSON.stringify(next));
      onCustomSettingsChange?.();
    } catch {
      // ignore
    }
  }, [selectedCodes]);
  // 用户已选择的指数列表（按 selectedCodes 顺序）
  const visibleIndices = selectedCodes.length
    ? selectedCodes
        .map((code) => indices.find((it) => it.code === code))
        .filter(Boolean)
    : indices;

  // 重置 tickerIndex 确保索引合法
  useEffect(() => {
    if (tickerIndex >= visibleIndices.length) {
      setTickerIndex(0);
    }
  }, [visibleIndices.length, tickerIndex]);

  // 收起状态下轮播展示指数
  useEffect(() => {
    if (!visibleIndices.length) return;
    if (openValue === 'indices') return;
    if (visibleIndices.length <= 1) return;
    const timer = setInterval(() => {
      setTickerIndex((prev) => (prev + 1) % visibleIndices.length);
    }, 4000);
    return () => clearInterval(timer);
  }, [visibleIndices.length, openValue]);

  const current =
    visibleIndices.length === 0
      ? null
      : visibleIndices[openValue === 'indices' ? 0 : tickerIndex];

  const isUp = current ? current.change >= 0 : false;
  const colorClass = isUp ? 'text-[var(--danger)]' : 'text-[var(--success)]';

  const topMargin = Number(navbarHeight) || 0;
  const stickyStyle = {
    marginTop: topMargin,
    position: 'sticky',
    top: topMargin,
    zIndex: 10,
    width: isMobile ? 'calc(100% + 24px)' : '100%',
    marginLeft: isMobile ? -12 : 0,
  };

  if (loading && indices.length === 0) {
    return (
      <div
        ref={rootRef}
        className="market-index-accordion-root mt-2 mb-2 rounded-lg border border-[var(--border)] bg-[var(--card)] px-4 py-3 flex items-center justify-between"
        style={stickyStyle}
      >
        <span className="text-sm text-[var(--muted-foreground)]">加载大盘指数…</span>
      </div>
    );
  }

  return (
    <div
      ref={rootRef}
      className="market-index-accordion-root mt-2 mb-2 rounded-lg border border-[var(--border)] bg-[var(--card)] market-index-accordion"
      style={stickyStyle}
    >
      <style jsx>{`
        .market-index-accordion :global([data-slot="accordion-trigger"] > svg:last-of-type) {
          display: none;
        }
        :global([data-theme='dark'] .market-index-accordion-root) {
          background-color: rgba(15, 23, 42, 0.9);
        }
        .market-index-ticker {
          overflow: hidden;
        }
        .market-index-ticker-item {
          display: inline-flex;
          align-items: center;
          gap: 0.75rem;
          animation: market-index-ticker-slide 0.35s ease-out;
        }
        @keyframes market-index-ticker-slide {
          0% {
            transform: translateY(100%);
            opacity: 0;
          }
          100% {
            transform: translateY(0);
            opacity: 1;
          }
        }
      `}</style>
      <Accordion
        type="single"
        collapsible
        value={openValue}
        onValueChange={setOpenValue}
      >
        <AccordionItem value="indices" className="border-b-0">
          <AccordionTrigger
            className="py-3 px-4 hover:no-underline hover:bg-[var(--card)] [&[data-state=open]>svg]:rotate-90"
            style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}
          >
            <div className="flex flex-1 items-center gap-3 min-w-0">
              {current ? (
                <div className="market-index-ticker">
                  <div
                    key={current.code || current.name}
                    className="market-index-ticker-item"
                  >
                    <span className="text-sm font-medium text-[var(--foreground)] shrink-0">
                      {current.name}
                    </span>
                    <span className={cn('tabular-nums font-medium', colorClass)}>
                      {current.price.toFixed(2)}
                    </span>
                    <span className={cn('tabular-nums text-sm', colorClass)}>
                      {(current.change >= 0 ? '+' : '') + current.change.toFixed(2)}
                    </span>
                    <span className={cn('tabular-nums text-sm', colorClass)}>
                      {(current.changePercent >= 0 ? '+' : '') + current.changePercent.toFixed(2)}%
                    </span>
                  </div>
                </div>
              ) : (
                <span className="text-sm text-[var(--muted-foreground)]">暂无指数数据</span>
              )}
            </div>
            <div className="flex items-center gap-4 shrink-0 pl-3">
              <div
                role="button"
                tabIndex={openValue === 'indices' ? 0 : -1}
                className="icon-button"
                style={{
                  border: 'none',
                  width: '28px',
                  height: '28px',
                  minWidth: '28px',
                  backgroundColor: 'transparent',
                  color: 'var(--text)',
                  flexShrink: 0,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  opacity: openValue === 'indices' ? 1 : 0,
                  pointerEvents: openValue === 'indices' ? 'auto' : 'none',
                  transition: 'opacity 0.2s ease',
                }}
                onClick={(e) => {
                  e.stopPropagation();
                  setSettingOpen(true);
                }}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' || e.key === ' ') {
                    e.preventDefault();
                    e.stopPropagation();
                    setSettingOpen(true);
                  }
                }}
                aria-label="指数个性化设置"
              >
                <SettingsIcon width="18" height="18" />
              </div>
              <ChevronRightIcon
                className={cn(
                  'w-4 h-4 text-[var(--muted-foreground)] transition-transform',
                  openValue === 'indices' ? 'rotate-90' : ''
                )}
                aria-hidden="true"
              />
            </div>
          </AccordionTrigger>
          <AccordionContent className="px-3 pb-4 pt-0">
            <div
              className="flex flex-wrap w-full min-w-0"
              style={{ gap: 12 }}
            >
              {visibleIndices.map((item, i) => (
                <div
                  key={item.code || i}
                  style={{
                    flex: isMobile
                      ? '0 0 calc((100% - 24px) / 3)'
                      : '0 0 calc((100% - 48px) / 5)',
                  }}
                >
                  <IndexCard item={item} />
                </div>
              ))}
            </div>
          </AccordionContent>
        </AccordionItem>
      </Accordion>
      <MarketSettingModal
        open={settingOpen}
        onClose={() => setSettingOpen(false)}
        isMobile={isMobile}
        indices={indices}
        selectedCodes={selectedCodes}
        onChangeSelected={setSelectedCodes}
        onResetDefault={() => {
          const availableCodes = new Set(indices.map((it) => it.code));
          const defaults = DEFAULT_SELECTED_CODES.filter((c) => availableCodes.has(c));
          setSelectedCodes(defaults.length ? defaults : indices.map((it) => it.code).slice(0, 3));
        }}
      />
    </div>
  );
}
