import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { CSSProperties } from 'react';
import { useNavigate } from 'react-router-dom';
import { fetchSites, postSiteClick, authLogin } from '../api/client';
import { SiteCard } from '../components/SiteCard';
import { Toast } from '../components/Toast';
import { SITE_NAME } from '../config/site';
import { useInstallPrompt } from '../hooks/useInstallPrompt';
import { useServiceWorker } from '../hooks/useServiceWorker';
import type { Site } from '../types/site';

const ADMIN_SESSION_STORAGE_KEY = 'mengya_nav_admin_session';
const ADMIN_UNLOCK_CLICKS = 5;
const ADMIN_UNLOCK_RESET_MS = 2800;

function performWebSearch(query: string, engine: string) {
  const encodedQuery = encodeURIComponent(query);
  const urls: Record<string, string> = {
    google: `https://www.google.com/search?q=${encodedQuery}`,
    baidu: `https://www.baidu.com/s?wd=${encodedQuery}`,
    bing: `https://www.bing.com/search?q=${encodedQuery}`,
    duckduckgo: `https://duckduckgo.com/?q=${encodedQuery}`,
    yandex: `https://yandex.com/search/?text=${encodedQuery}`,
  };
  window.open(urls[engine] || urls.google, '_blank');
}

/** body 上切换 class，复用原侧边栏 CSS */
function BodyClassWhen({ open, className }: { open: boolean; className: string }) {
  useEffect(() => {
    if (open) document.body.classList.add(className);
    else document.body.classList.remove(className);
    return () => document.body.classList.remove(className);
  }, [open, className]);
  return null;
}

const installBtnStyle: CSSProperties = {
  position: 'fixed',
  bottom: 20,
  right: 20,
  background: 'linear-gradient(145deg, #ea580c, #c2410c)',
  color: '#fff',
  border: 'none',
  padding: '12px 24px',
  borderRadius: '10px',
  cursor: 'pointer',
  fontWeight: 600,
  fontSize: '0.95rem',
  boxShadow: '0 4px 14px rgba(234, 88, 12, 0.28)',
  zIndex: 1000,
};

export default function Home() {
  useServiceWorker();
  const navigate = useNavigate();

  const [sites, setSites] = useState<Site[]>([]);
  const [searchInput, setSearchInput] = useState('');
  const [activeCategory, setActiveCategory] = useState('all');
  const [sidebarOpen, setSidebarOpen] = useState(false);

  const [toast, setToast] = useState<{ message: string; type: 'success' | 'error'; visible: boolean }>({
    message: '',
    type: 'success',
    visible: false,
  });

  const showToast = useCallback((message: string, type: 'success' | 'error' = 'success') => {
    setToast({ message, type, visible: true });
    window.setTimeout(() => setToast((t) => ({ ...t, visible: false })), 3000);
  }, []);

  const { installVisible, triggerInstall } = useInstallPrompt(showToast);

  const [adminModalOpen, setAdminModalOpen] = useState(false);
  const [adminPassword, setAdminPassword] = useState('');
  const [adminUnlockError, setAdminUnlockError] = useState('');
  const logoClickRef = useRef(0);
  const logoResetTimerRef = useRef<number | null>(null);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const data = await fetchSites();
        if (!cancelled) setSites(data);
      } catch {
        if (!cancelled) showToast('加载网站数据失败', 'error');
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [showToast]);

  const categoriesList = useMemo(
    () => ['all', ...new Set(sites.map((s) => s.category).filter(Boolean))] as string[],
    [sites]
  );

  const stats = useMemo(() => {
    const totalSites = sites.length;
    const cats = [...new Set(sites.map((s) => s.category).filter(Boolean))];
    const allTags = sites.flatMap((s) => s.tags || []);
    const uniqueTags = [...new Set(allTags)];
    return { totalSites, categoriesCount: cats.length, tagsCount: uniqueTags.length };
  }, [sites]);

  const filteredGrouped = useMemo(() => {
    let list = sites;
    if (searchInput.trim()) {
      const q = searchInput.toLowerCase();
      list = list.filter(
        (site) =>
          site.name.toLowerCase().includes(q) ||
          (site.description && site.description.toLowerCase().includes(q)) ||
          (site.tags && site.tags.some((tag) => tag.toLowerCase().includes(q)))
      );
    }
    if (activeCategory !== 'all') {
      list = list.filter((s) => s.category === activeCategory);
    }
    const map: Record<string, Site[]> = {};
    list.forEach((site) => {
      const c = site.category || '未分类';
      if (!map[c]) map[c] = [];
      map[c].push(site);
    });
    return map;
  }, [sites, searchInput, activeCategory]);

  function onLogoClick(e: React.MouseEvent) {
    e.preventDefault();
    logoClickRef.current += 1;
    if (logoResetTimerRef.current) window.clearTimeout(logoResetTimerRef.current);
    logoResetTimerRef.current = window.setTimeout(() => {
      logoClickRef.current = 0;
      logoResetTimerRef.current = null;
    }, ADMIN_UNLOCK_RESET_MS);
    if (logoClickRef.current >= ADMIN_UNLOCK_CLICKS) {
      logoClickRef.current = 0;
      if (logoResetTimerRef.current) window.clearTimeout(logoResetTimerRef.current);
      setAdminPassword('');
      setAdminUnlockError('');
      setAdminModalOpen(true);
    }
  }

  async function submitAdminUnlock() {
    setAdminUnlockError('');
    try {
      const data = await authLogin(adminPassword);
      if (!data.ok || !data.sessionId) {
        setAdminUnlockError('密码错误或无法登录');
        return;
      }
      try {
        sessionStorage.setItem(ADMIN_SESSION_STORAGE_KEY, data.sessionId);
      } catch (_) {}
      setAdminModalOpen(false);
      navigate('/admin');
    } catch {
      setAdminUnlockError('网络错误，请稍后重试');
    }
  }

  function onContainerClick(e: React.MouseEvent<HTMLDivElement>) {
    const card = (e.target as HTMLElement).closest('.site-card') as HTMLElement | null;
    if (!card) return;
    const id = card.dataset.siteId;
    if (id) void postSiteClick(id);
  }

  return (
    <>
      <BodyClassWhen open={sidebarOpen} className="category-sidebar-open" />

      <div className="container">
        <header className="main-header">
          <button type="button" className="site-logo-mark" id="site-logo-mark" aria-label="站点图标" onClick={onLogoClick}>
            <img src="/logo.png" alt="" width={44} height={44} decoding="async" />
          </button>
          <h1 id="site-title">{SITE_NAME}</h1>
        </header>

        <div className="web-search-box">
          <form
            id="web-search-form"
            autoComplete="off"
            onSubmit={(e) => {
              e.preventDefault();
              const fd = new FormData(e.currentTarget);
              const q = String(fd.get('q') || '').trim();
              const engine = String(fd.get('engine') || 'google');
              if (q) {
                performWebSearch(q, engine);
                e.currentTarget.reset();
              }
            }}
          >
            <div className="search-wrapper">
              <span className="search-icon">🔍</span>
              <input
                type="search"
                id="web-search-input"
                name="q"
                placeholder="搜索网页..."
                autoComplete="off"
                spellCheck={false}
              />
              <select id="search-engine" name="engine" className="search-select" defaultValue="google">
                <option value="google">Google</option>
                <option value="baidu">百度</option>
                <option value="bing">Bing</option>
                <option value="duckduckgo">DuckDuckGo</option>
                <option value="yandex">Yandex</option>
              </select>
            </div>
          </form>
        </div>

        <div className="top-bar">
          <div className="stats-group">
            <div className="stats-item">
              📚 网站总数: <span id="total-sites">{stats.totalSites}</span>
            </div>
            <div className="stats-item">
              📁 分类数量: <span id="total-categories">{stats.categoriesCount}</span>
            </div>
            <div className="stats-item">
              🏷️ 标签数量: <span id="total-tags">{stats.tagsCount}</span>
            </div>
          </div>
          <div className="search-container compact">
            <span className="search-icon">🔍</span>
            <input
              type="search"
              id="search-input"
              name="site-filter"
              placeholder="搜索网站、描述或标签..."
              autoComplete="off"
              spellCheck={false}
              value={searchInput}
              onChange={(e) => setSearchInput(e.target.value)}
            />
          </div>
        </div>

        <div className="categories-container" id="categories-container" onClick={onContainerClick}>
          {sites.length === 0 ? (
            <div className="empty-state">
              <div style={{ fontSize: '4rem', marginBottom: '15px' }}>📭</div>
              <h2>暂无网站</h2>
              <p>请在后台管理中添加网站</p>
            </div>
          ) : Object.keys(filteredGrouped).length === 0 ? (
            <div className="empty-state">
              <div style={{ fontSize: '4rem', marginBottom: '15px' }}>🔍</div>
              <h2>没有找到匹配的网站</h2>
              <p>尝试调整搜索关键词或分类筛选条件</p>
            </div>
          ) : (
            Object.keys(filteredGrouped)
              .sort()
              .map((category) => (
                <div key={category} className="category-section">
                  <h2 className="category-title">{category}</h2>
                  <div className="sites-grid">
                    {filteredGrouped[category].map((site) => (
                      <SiteCard key={site.id} site={site} />
                    ))}
                  </div>
                </div>
              ))
          )}
        </div>
      </div>

      <Toast message={toast.message} type={toast.type} visible={toast.visible} />

      <button
        type="button"
        id="category-sidebar-toggle"
        className="category-toggle-btn category-toggle-fixed"
        aria-label="打开分类"
        onClick={() => setSidebarOpen(true)}
      >
        📁 分类
      </button>
      <div
        id="category-sidebar-backdrop"
        className="category-sidebar-backdrop"
        aria-hidden={!sidebarOpen}
        onClick={() => setSidebarOpen(false)}
      />
      <aside id="category-sidebar" className="category-sidebar" aria-label="分类筛选">
        <div className="category-sidebar-header">
          <h2>分类</h2>
          <button type="button" className="category-sidebar-close" id="category-sidebar-close" aria-label="关闭" onClick={() => setSidebarOpen(false)}>
            &times;
          </button>
        </div>
        <div className="category-sidebar-list" id="category-filters">
          {categoriesList.map((cat) => (
            <button
              key={cat}
              type="button"
              className={`category-filter${activeCategory === cat ? ' active' : ''}`}
              data-category={cat}
              onClick={() => {
                setActiveCategory(cat);
                setSidebarOpen(false);
              }}
            >
              {cat === 'all' ? '全部' : cat}
            </button>
          ))}
        </div>
      </aside>

      {installVisible ? (
        <button type="button" className="install-btn" style={installBtnStyle} onClick={() => void triggerInstall()}>
          📲 安装应用
        </button>
      ) : null}

      <div className={`admin-unlock-modal${adminModalOpen ? ' is-open' : ''}`} id="admin-unlock-modal" aria-hidden={!adminModalOpen}>
        <div className="admin-unlock-backdrop" id="admin-unlock-backdrop" onClick={() => setAdminModalOpen(false)} />
        <div className="admin-unlock-dialog" role="dialog" aria-labelledby="admin-unlock-title">
          <h3 id="admin-unlock-title">管理入口</h3>
          {adminUnlockError ? (
            <p className="admin-unlock-error" id="admin-unlock-error" role="alert">
              {adminUnlockError}
            </p>
          ) : null}
          <input
            type="password"
            id="admin-unlock-input"
            className="admin-unlock-input"
            placeholder="管理密码"
            autoComplete="current-password"
            value={adminPassword}
            onChange={(e) => setAdminPassword(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') void submitAdminUnlock();
            }}
          />
          <div className="admin-unlock-actions">
            <button type="button" className="admin-unlock-btn primary" id="admin-unlock-submit" onClick={() => void submitAdminUnlock()}>
              进入后台
            </button>
            <button type="button" className="admin-unlock-btn" id="admin-unlock-cancel" onClick={() => setAdminModalOpen(false)}>
              取消
            </button>
          </div>
        </div>
      </div>
    </>
  );
}
