import './index.css';
import { MOVIES_DATA, NEWS_DATA, TEAM_MEMBERS, HISTORY_EVENTS } from './data';
import { Movie, TeamMember, HistoryEvent } from './types';

// ==================== STATE MANAGEMENT ====================
let currentTab: string = 'home';
let searchQuery: string = '';
let filterType: string = '全部';
let filterRegion: string = '全部';
let filterYear: string = '全部';
let filterSort: string = '最热点击';

// Timeline active index
let selectedTimelineIndex: number = HISTORY_EVENTS.length - 1;

// Map States
let mapZoom: number = 1.0;
let mapOffsetX: number = 0;
let mapOffsetY: number = 0;
let isDraggingMap: boolean = false;
let startDragX: number = 0;
let startDragY: number = 0;
let selectedPoiIndex: number = 0;

// Player Simulation State inside modal
let isPlayerPlaying: boolean = true;
let playerProgress: number = 38; // initial progress %
let playerVolume: number = 80;
let selectedPlaybackLine: string = '北京电信专线 4K';
let playerTimerInterval: any = null;

// ==================== DOM ELEMENTS CACHE ====================
const elements = {
  // Navigation elements
  logoBtn: document.getElementById('logo-btn'),
  searchShortcutBtn: document.getElementById('search-shortcut-btn'),
  headerContactBtn: document.getElementById('header-contact-btn'),
  mobileMenuToggle: document.getElementById('mobile-menu-toggle'),
  mobileDrawer: document.getElementById('mobile-drawer'),
  mobileSearchTrigger: document.getElementById('mobile-search-trigger'),
  mobileContactTrigger: document.getElementById('mobile-contact-trigger'),
  footerLogo: document.getElementById('footer-logo'),
  
  // Tab container
  tabHome: document.getElementById('tab-content-home'),
  tabProducts: document.getElementById('tab-content-products'),
  tabAbout: document.getElementById('tab-content-about'),
  tabContact: document.getElementById('tab-content-contact'),
  
  // Home Grids
  popularMoviesGrid: document.getElementById('popular-movies-grid'),
  latestMoviesGrid: document.getElementById('latest-movies-grid'),
  homeNewsGrid: document.getElementById('home-news-grid'),
  homeViewMorePopularBtn: document.getElementById('home-view-more-popular-btn'),
  heroPlayBtn: document.getElementById('hero-play-btn'),
  heroFilterBtn: document.getElementById('hero-filter-btn'),
  adContactTriggerBtn: document.getElementById('ad-contact-trigger-btn'),
  
  // Products/Filters Tab
  movieSearchInput: document.getElementById('movie-search-input') as HTMLInputElement,
  searchClearBtn: document.getElementById('search-clear-btn'),
  catalogMoviesGrid: document.getElementById('catalog-movies-grid'),
  catalogEmptyState: document.getElementById('catalog-empty-state'),
  emptyStateResetBtn: document.getElementById('empty-state-reset-btn'),
  resultsCount: document.getElementById('results-count'),
  filterSort: document.getElementById('filter-sort') as HTMLSelectElement,
  
  // Timeline Displays
  timelineYearDisplay: document.getElementById('timeline-year-display'),
  timelineTitleDisplay: document.getElementById('timeline-title-display'),
  timelineDescDisplay: document.getElementById('timeline-desc-display'),
  
  // Team grid
  aboutTeamGrid: document.getElementById('about-team-grid'),
  
  // Contact View
  contactForm: document.getElementById('contact-form') as HTMLFormElement,
  formSubmitBtn: document.getElementById('form-submit-btn') as HTMLButtonElement,
  formBtnText: document.getElementById('form-btn-text'),
  
  // Canvas Map
  mapCanvas: document.getElementById('interactive-map-canvas') as HTMLCanvasElement,
  mapZoomIn: document.getElementById('map-zoom-in'),
  mapZoomOut: document.getElementById('map-zoom-out'),
  mapReset: document.getElementById('map-reset'),
  poiInfoPanel: document.getElementById('poi-info-panel'),
  poiDistDisplay: document.getElementById('poi-dist-display'),
  poiTitleDisplay: document.getElementById('poi-title-display'),
  poiDescDisplay: document.getElementById('poi-desc-display'),
  
  // Dialog modal
  movieDetailDialog: document.getElementById('movie-detail-dialog'),
  modalCloseBtn: document.getElementById('modal-close-btn'),
  modalDynamicContent: document.getElementById('modal-dynamic-content'),
  
  // Chat Simulator
  liveChatTrigger: document.getElementById('live-chat-trigger'),
  liveChatWindow: document.getElementById('live-chat-window'),
  liveChatCloseBtn: document.getElementById('live-chat-close-btn'),
  chatMessagesContainer: document.getElementById('chat-messages-container'),
  chatInputForm: document.getElementById('chat-input-form') as HTMLFormElement,
  chatUserInput: document.getElementById('chat-user-input') as HTMLInputElement,
  
  // Toast
  successToast: document.getElementById('success-toast'),
  toastMessageBody: document.getElementById('toast-message-body'),
  toastTicketId: document.getElementById('toast-ticket-id'),
  toastCloseBtn: document.getElementById('toast-close-btn')
};

// ==================== INLINE MAP POIS DATA ====================
interface MapPoi {
  title: string;
  desc: string;
  x: number; // local schematic coordinate inside 800x500 sandbox
  y: number;
  distance: string;
}

const MAP_POIS: MapPoi[] = [
  {
    title: "7788研发与管理总部",
    desc: "北京中关村高科技标杆大厦C座18层。配备100G专属直联主干网，全天候维护流媒体播放节点，确保不卡顿、秒加载、秒播放。",
    x: 400,
    y: 250,
    distance: "0米"
  },
  {
    title: "7788高带宽汇聚机房",
    desc: "多线千兆BGP对等流媒体互联中心，直达电信、联通、移动、广电网等运营商骨干枢纽，让最新手机电影免VIP极速缓冲。",
    x: 520,
    y: 160,
    distance: "320米"
  },
  {
    title: "中关村地铁站 C口",
    desc: "北京地铁4号线重要交通枢纽。员工日常通勤直达、高科技人才引进和政企商务洽谈极其便利。",
    x: 320,
    y: 340,
    distance: "145米"
  }
];

// ==================== RENDERING UTILITIES ====================

// Switch Active Navigation Tabs
function switchTab(tabName: string) {
  currentTab = tabName;
  
  // Hide all tab views
  const tabViews = document.querySelectorAll('.tab-view');
  tabViews.forEach(view => {
    view.classList.add('hidden');
    view.classList.remove('block');
  });

  // Show active tab view
  const targetView = document.getElementById(`tab-content-${tabName}`);
  if (targetView) {
    targetView.classList.remove('hidden');
    targetView.classList.add('block');
  }

  // Update navigation button active state (Desktop Nav)
  const navTabs = document.querySelectorAll('.nav-tab');
  navTabs.forEach(tab => {
    const btnTab = tab.getAttribute('data-tab');
    if (btnTab === tabName) {
      tab.className = "nav-tab px-5 py-2.5 rounded-xl text-xs font-bold font-sans tracking-wide transition duration-200 cursor-pointer text-white bg-gradient-to-r from-neutral-800 to-neutral-850 border border-neutral-800/80 shadow";
    } else {
      tab.className = "nav-tab px-5 py-2.5 rounded-xl text-xs font-bold font-sans tracking-wide transition duration-200 cursor-pointer text-neutral-400 hover:text-white hover:bg-neutral-900";
    }
  });

  // Update mobile drawer active state
  const mobileTabBtns = document.querySelectorAll('.mobile-tab-btn');
  mobileTabBtns.forEach(btn => {
    const btnTab = btn.getAttribute('data-tab');
    if (btnTab === tabName) {
      btn.className = "mobile-tab-btn text-left px-4 py-3 rounded-xl text-sm font-bold text-white bg-neutral-900";
    } else {
      btn.className = "mobile-tab-btn text-left px-4 py-3 rounded-xl text-sm font-bold text-neutral-400 hover:text-white";
    }
  });

  // Close mobile drawer if open
  if (elements.mobileDrawer) {
    elements.mobileDrawer.classList.add('hidden');
  }

  // Scroll to top with micro-animation
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

// Generate Rating Stars HTML
function getRatingStars(rating: number): string {
  const fullStars = Math.floor(rating / 2);
  const halfStar = rating % 2 >= 1 ? 1 : 0;
  let starsHtml = '';
  for (let i = 0; i < 5; i++) {
    if (i < fullStars) {
      starsHtml += '<span class="text-amber-400">★</span>';
    } else if (i === fullStars && halfStar === 1) {
      starsHtml += '<span class="text-amber-400/80">★</span>';
    } else {
      starsHtml += '<span class="text-neutral-600">★</span>';
    }
  }
  return starsHtml;
}

// Render Movies Grid (Popular / Latest)
function renderHomeMovies() {
  if (!elements.popularMoviesGrid || !elements.latestMoviesGrid) return;

  const popularMovies = MOVIES_DATA.filter(m => m.isPopular);
  const latestMovies = MOVIES_DATA.filter(m => m.isLatest);

  // Render Popular grid
  elements.popularMoviesGrid.innerHTML = popularMovies.map(movie => createMovieCardHTML(movie)).join('');
  // Render Latest grid
  elements.latestMoviesGrid.innerHTML = latestMovies.map(movie => createMovieCardHTML(movie)).join('');

  // Re-bind click event to all cards
  bindMovieCardClicks();
}

// Create Card HTML for Movie Card
function createMovieCardHTML(movie: Movie): string {
  return `
    <div class="movie-card relative bg-neutral-900 border border-neutral-850 hover:border-amber-500/30 rounded-2xl overflow-hidden shadow-md cursor-pointer group flex flex-col justify-between transition-all duration-300 transform hover:-translate-y-1.5" data-movie-id="${movie.id}">
      <div class="relative aspect-[3/4] w-full overflow-hidden bg-neutral-950">
        <img 
          src="${movie.imageUrl}" 
          alt="${movie.title}" 
          class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
          referrerPolicy="no-referrer"
        />
        <div class="absolute inset-0 bg-gradient-to-t from-neutral-950 via-neutral-950/20 to-transparent"></div>
        
        <!-- Hot indicator -->
        <div class="absolute top-3 left-3 flex flex-col gap-1 z-10 font-mono">
          <span class="bg-black/70 backdrop-blur-md text-[9px] font-extrabold text-amber-500 border border-amber-500/20 px-2 py-0.5 rounded shadow">
            ${movie.type}
          </span>
          ${movie.isFeatured ? '<span class="bg-red-600 text-[8px] font-extrabold text-white px-2 py-0.5 rounded shadow tracking-wider">RECOM</span>' : ''}
        </div>

        <!-- Rating overlay -->
        <div class="absolute top-3 right-3 bg-neutral-950/80 backdrop-blur-md px-2 py-0.5 rounded-lg border border-neutral-850 shadow flex items-center gap-0.5 text-[9px] font-mono text-amber-400 font-bold">
          <span>★</span>
          <span>${movie.rating.toFixed(1)}</span>
        </div>

        <!-- Status Tag bottom left -->
        <div class="absolute bottom-3 left-3 bg-neutral-950/80 backdrop-blur-md px-2 py-0.5 rounded border border-neutral-800 text-[9px] text-neutral-300 font-mono">
          ${movie.updateStatus}
        </div>

        <!-- Play overlay hover ring -->
        <div class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition duration-300 bg-black/40">
          <div class="w-12 h-12 rounded-full bg-amber-500 flex items-center justify-center text-black shadow-lg shadow-amber-500/20 transform scale-90 group-hover:scale-100 transition duration-300">
            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>
          </div>
        </div>

      </div>

      <div class="p-3.5 space-y-1 bg-neutral-900/80">
        <h4 class="text-white text-xs sm:text-sm font-black tracking-tight leading-tight truncate group-hover:text-amber-500 transition duration-150">
          ${movie.title}
        </h4>
        <div class="flex items-center justify-between text-[10px] text-neutral-500 font-mono">
          <span>${movie.region} · ${movie.year}</span>
          <span>${movie.playCount}次</span>
        </div>
      </div>
    </div>
  `;
}

// Render News items inside Home tab
function renderHomeNews() {
  if (!elements.homeNewsGrid) return;

  elements.homeNewsGrid.innerHTML = NEWS_DATA.map(news => {
    return `
      <div class="bg-neutral-900 border border-neutral-850 p-5 rounded-3xl space-y-3 shadow-lg hover:border-neutral-800 transition duration-300 flex flex-col justify-between group cursor-pointer">
        <div class="space-y-2.5">
          <div class="flex items-center justify-between text-[10px] font-mono font-bold">
            <span class="bg-amber-500/10 text-amber-500 border border-amber-500/25 px-2.5 py-0.5 rounded">${news.category}</span>
            <span class="text-neutral-500">${news.date}</span>
          </div>
          <h4 class="text-white font-extrabold text-sm sm:text-base leading-snug group-hover:text-amber-500 transition duration-150">
            ${news.title}
          </h4>
          <p class="text-xs text-neutral-400 font-sans leading-relaxed line-clamp-3">
            ${news.content}
          </p>
        </div>
        <div class="pt-4 border-t border-neutral-950 mt-4 flex items-center justify-between text-[10px] text-neutral-500 font-mono">
          <span>来源: 7788官方编辑</span>
          <span class="text-amber-500 flex items-center gap-0.5 group-hover:translate-x-1 transition-transform">
            阅读全文 &rarr;
          </span>
        </div>
      </div>
    `;
  }).join('');
}

// Render About Team Grid
function renderAboutTeam() {
  if (!elements.aboutTeamGrid) return;

  elements.aboutTeamGrid.innerHTML = TEAM_MEMBERS.map(member => {
    return `
      <div class="bg-neutral-900 border border-neutral-850 hover:border-neutral-700 p-6 rounded-3xl shadow-lg transition duration-300 flex flex-col justify-between group">
        <div class="space-y-4">
          
          <!-- Avatar wrapper -->
          <div class="relative rounded-2xl overflow-hidden aspect-[4/5] bg-neutral-950 border border-neutral-950">
            <img 
              src="${member.imageUrl}" 
              alt="${member.name}"
              class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
              referrerPolicy="no-referrer"
            />
            <div class="absolute inset-0 bg-gradient-to-t from-neutral-950 via-transparent to-transparent opacity-80" />
            <div class="absolute bottom-4 left-4 right-4">
              <span class="text-xs text-amber-400 font-semibold font-mono tracking-wider block">
                ${member.role}
              </span>
              <h4 class="text-white font-black text-lg">
                ${member.name}
              </h4>
            </div>
          </div>

          <p class="text-xs text-neutral-400 leading-relaxed font-sans">
            ${member.bio}
          </p>
        </div>

        <div class="pt-4 border-t border-neutral-950 mt-4 text-[10px] text-neutral-500 flex items-center justify-between font-mono">
          <span>邮箱: hr@7788movie.com</span>
          <span class="text-amber-500 flex items-center gap-0.5">
            ★ 已认证高管
          </span>
        </div>
      </div>
    `;
  }).join('');
}

// Render Catalog Grid inside Products Tab (Filtered & Sorted)
function renderCatalog() {
  if (!elements.catalogMoviesGrid || !elements.catalogEmptyState) return;

  // Filter movies
  let filtered = MOVIES_DATA.filter(movie => {
    // 1. Search Query filter (matches Title, Cast, or Director)
    if (searchQuery.trim() !== '') {
      const q = searchQuery.toLowerCase().trim();
      const matchTitle = movie.title.toLowerCase().includes(q);
      const matchActors = movie.actors.toLowerCase().includes(q);
      const matchDirector = movie.director.toLowerCase().includes(q);
      const matchGenre = movie.genre.toLowerCase().includes(q);
      if (!matchTitle && !matchActors && !matchDirector && !matchGenre) {
        return false;
      }
    }

    // 2. Type Filter
    if (filterType !== '全部' && movie.type !== filterType) {
      return false;
    }

    // 3. Region Filter
    if (filterRegion !== '全部' && movie.region !== filterRegion) {
      return false;
    }

    // 4. Year Filter
    if (filterYear !== '全部' && movie.year !== filterYear) {
      return false;
    }

    return true;
  });

  // Sort movies
  filtered.sort((a, b) => {
    if (filterSort === '最热点击') {
      // playCount is formatted as "1,284,500" - let's parse numbers
      const pA = parseInt(a.playCount.replace(/,/g, ''), 10);
      const pB = parseInt(b.playCount.replace(/,/g, ''), 10);
      return pB - pA;
    } else if (filterSort === '最新上线') {
      return parseInt(b.year, 10) - parseInt(a.year, 10);
    } else if (filterSort === '评分最高') {
      return b.rating - a.rating;
    }
    return 0;
  });

  // Render results
  if (elements.resultsCount) {
    elements.resultsCount.innerText = filtered.length.toString();
  }

  if (filtered.length === 0) {
    elements.catalogMoviesGrid.classList.add('hidden');
    elements.catalogEmptyState.classList.remove('hidden');
  } else {
    elements.catalogEmptyState.classList.add('hidden');
    elements.catalogMoviesGrid.classList.remove('hidden');
    
    // Inject movies HTML with slight staggered entry classes if needed
    elements.catalogMoviesGrid.innerHTML = filtered.map(movie => createMovieCardHTML(movie)).join('');
    
    // Bind click handlers to newly created catalog cards
    bindMovieCardClicks();
  }
}

// Bind Clicks to movie cards
function bindMovieCardClicks() {
  const cards = document.querySelectorAll('.movie-card, [data-movie-id]');
  cards.forEach(card => {
    card.addEventListener('click', (e) => {
      // Prevent bubble if clicking inner buttons
      const target = e.currentTarget as HTMLElement;
      const movieId = target.getAttribute('data-movie-id');
      if (movieId) {
        openMovieDetailModal(movieId);
      }
    });
  });
}


// ==================== DIALOG MOVIE MODAL PLAYBACK ====================

function openMovieDetailModal(movieId: string) {
  const movie = MOVIES_DATA.find(m => m.id === movieId);
  if (!movie || !elements.movieDetailDialog || !elements.modalDynamicContent) return;

  // Cache/Initialize Modal state
  isPlayerPlaying = true;
  playerProgress = 38;
  selectedPlaybackLine = '北京电信专线 4K';

  // Render content
  renderModalContent(movie);

  // Show modal
  elements.movieDetailDialog.classList.remove('hidden');
  document.body.style.overflow = 'hidden'; // block scrolling

  // Launch simulated video progression interval
  if (playerTimerInterval) clearInterval(playerTimerInterval);
  playerTimerInterval = setInterval(() => {
    if (isPlayerPlaying) {
      playerProgress += 0.2;
      if (playerProgress >= 100) {
        playerProgress = 0;
      }
      // Update progress bar width and counter in DOM if elements exist
      const fillBar = document.getElementById('player-progress-fill');
      const handlerDot = document.getElementById('player-progress-handle');
      if (fillBar) fillBar.style.width = `${playerProgress}%`;
      if (handlerDot) handlerDot.style.left = `${playerProgress}%`;

      // Tick times
      const curTimeDisplay = document.getElementById('player-current-time');
      if (curTimeDisplay) {
        // Calculate dynamic current time based on progress of duration
        const durationSec = movie.type === '电影' ? 120 * 60 : 45 * 60; // 120 mins or 45 mins
        const currentSec = Math.floor((playerProgress / 100) * durationSec);
        curTimeDisplay.innerText = formatTime(currentSec);
      }
    }
  }, 1000);
}

function formatTime(secs: number): string {
  const h = Math.floor(secs / 3600);
  const m = Math.floor((secs % 3600) / 60);
  const s = secs % 60;
  
  const hh = h > 0 ? `${h.toString().padStart(2, '0')}:` : '';
  const mm = `${m.toString().padStart(2, '0')}:`;
  const ss = s.toString().padStart(2, '0');
  return `${hh}${mm}${ss}`;
}

function closeMovieDetailModal() {
  if (elements.movieDetailDialog) {
    elements.movieDetailDialog.classList.add('hidden');
  }
  document.body.style.overflow = ''; // restore scrolling
  if (playerTimerInterval) {
    clearInterval(playerTimerInterval);
    playerTimerInterval = null;
  }
}

// Render dynamic modal inner layout with real simulated player & volume & line toggles!
function renderModalContent(movie: Movie) {
  if (!elements.modalDynamicContent) return;

  // Pick some related recommendations (any other movies of same type or genre)
  const related = MOVIES_DATA.filter(m => m.id !== movie.id && (m.type === movie.type || m.genre.includes(movie.genre.split(' / ')[0]))).slice(0, 4);
  const relatedHtml = related.map(rel => {
    return `
      <div class="modal-related-card flex gap-3.5 bg-neutral-950/60 hover:bg-neutral-950 p-2.5 rounded-2xl border border-neutral-900/80 cursor-pointer transition group" data-movie-id="${rel.id}">
        <div class="relative w-16 aspect-[3/4] rounded-lg overflow-hidden shrink-0 bg-neutral-900">
          <img src="${rel.imageUrl}" alt="${rel.title}" class="w-full h-full object-cover group-hover:scale-105 transition" referrerPolicy="no-referrer">
          <div class="absolute bottom-1 right-1 bg-black/80 px-1 py-0.2 rounded text-[8px] font-mono text-neutral-400">
            ${rel.rating.toFixed(1)}
          </div>
        </div>
        <div class="space-y-0.5 flex flex-col justify-center min-w-0">
          <h5 class="text-white text-xs font-bold truncate group-hover:text-amber-500 transition">${rel.title}</h5>
          <p class="text-[9px] text-neutral-500 font-mono">${rel.genre}</p>
          <p class="text-[10px] text-amber-500/80 font-mono font-bold mt-1">${rel.updateStatus}</p>
        </div>
      </div>
    `;
  }).join('');

  const starsHtml = getRatingStars(movie.rating);

  elements.modalDynamicContent.innerHTML = `
    <!-- Top wide backdrop and core details -->
    <div class="relative h-[180px] sm:h-[300px] w-full bg-neutral-950 overflow-hidden flex items-end">
      <!-- Background wide image -->
      <div class="absolute inset-0">
        <img src="${movie.imageUrl}" alt="Backdrop" class="w-full h-full object-cover opacity-20 filter blur-sm scale-110" referrerPolicy="no-referrer">
        <div class="absolute inset-0 bg-gradient-to-t from-neutral-900 via-neutral-900/50 to-transparent"></div>
      </div>

      <div class="max-w-7xl mx-auto px-6 sm:px-10 pb-6 w-full relative z-10 flex flex-col sm:flex-row items-end gap-5">
        
        <!-- Absolute overlapping poster on desktop -->
        <div class="hidden sm:block w-36 aspect-[3/4] rounded-2xl overflow-hidden border-2 border-neutral-800 shadow-2xl relative bg-neutral-900 shrink-0 transform translate-y-12">
          <img src="${movie.imageUrl}" alt="Poster" class="w-full h-full object-cover" referrerPolicy="no-referrer">
        </div>

        <div class="space-y-2 text-left min-w-0">
          <div class="flex flex-wrap items-center gap-2">
            <span class="bg-amber-500 text-black font-black text-[9px] px-2 py-0.5 rounded font-mono">${movie.type}</span>
            <span class="text-xs text-neutral-400 font-mono">${movie.region} · ${movie.year} · ${movie.durationOrEpisodes}</span>
          </div>
          
          <h2 class="text-xl sm:text-3xl font-black text-white tracking-tight truncate leading-none">
            ${movie.title}
          </h2>

          <div class="flex items-center gap-2 text-xs font-mono">
            <div class="flex text-amber-400">${starsHtml}</div>
            <span class="text-amber-500 font-bold">${movie.rating.toFixed(1)}分</span>
            <span class="text-neutral-500">(${movie.playCount}次手机极速播放)</span>
          </div>
        </div>

      </div>
    </div>

    <!-- Main grid layout of detail view -->
    <div class="px-6 sm:px-10 py-8 sm:py-12 grid grid-cols-1 lg:grid-cols-12 gap-10">
      
      <!-- Left Column: Core interactive player and specification -->
      <div class="lg:col-span-8 space-y-6">
        
        <!-- 7788 DYNAMIC PLAY ZONE (HIGH FIDELITY STREAMING BOX) -->
        <div class="space-y-3">
          <div class="flex items-center justify-between text-xs font-mono text-neutral-400">
            <span class="flex items-center gap-1">
              <span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
              流媒体就绪：<strong class="text-amber-500" id="current-line-display">${selectedPlaybackLine}</strong>
            </span>
            <span>画质: <strong class="text-amber-500">4K超清(原画)</strong></span>
          </div>

          <!-- Sandbox Player Area -->
          <div class="relative w-full aspect-video rounded-3xl overflow-hidden border border-neutral-850 bg-neutral-950 group">
            
            <!-- Simulated video background screen -->
            <div class="absolute inset-0 flex items-center justify-center">
              <img src="${movie.imageUrl}" alt="Video Backdrop" class="w-full h-full object-cover opacity-10 filter blur-xs" referrerPolicy="no-referrer">
              
              <!-- Static custom design overlay representing playback state -->
              <div class="absolute inset-0 bg-neutral-950/40 flex flex-col items-center justify-center space-y-3">
                <div class="relative">
                  <!-- Radar ring -->
                  <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-500/10 opacity-75"></span>
                  <div class="w-16 h-16 rounded-full bg-neutral-900/90 border border-neutral-800 flex items-center justify-center text-amber-500 shadow-xl" id="player-screen-play-btn">
                    <span id="player-center-icon" class="text-2xl">${isPlayerPlaying ? '⏸️' : '▶️'}</span>
                  </div>
                </div>
                <div class="text-center space-y-1">
                  <p class="text-xs font-bold text-white tracking-wide font-mono" id="player-screen-status">正在解码专线高壓縮流媒体...</p>
                  <p class="text-[9px] text-neutral-500 font-mono">P2P高速共享网联 · 延迟 &lt; 15ms · 零缓冲</p>
                </div>
              </div>
            </div>

            <!-- Floating Video Header (appears on hover) -->
            <div class="absolute top-0 left-0 right-0 p-4 bg-gradient-to-b from-neutral-950 via-neutral-950/70 to-transparent flex items-center justify-between opacity-0 group-hover:opacity-100 transition duration-300">
              <div class="flex items-center gap-2 text-xs text-white font-bold">
                <span>7788 高清极速解码器 v4.0</span>
                <span class="bg-red-600 px-1.5 py-0.2 rounded text-[8px] font-mono uppercase tracking-wider">SECURE</span>
              </div>
              <div class="text-[10px] text-neutral-400 font-mono" id="playback-line-overlay">线路: ${selectedPlaybackLine}</div>
            </div>

            <!-- Controller Bar -->
            <div class="absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-neutral-950 via-neutral-950/90 to-transparent space-y-3">
              
              <!-- Custom interactive progress line -->
              <div class="relative w-full h-1.5 bg-neutral-800 rounded-full cursor-pointer group/progress" id="player-progress-bar">
                <div id="player-progress-fill" class="absolute top-0 left-0 h-full bg-gradient-to-r from-red-600 to-amber-500 rounded-full transition-all duration-300" style="width: ${playerProgress}%"></div>
                <div id="player-progress-handle" class="absolute top-1/2 -translate-y-1/2 w-3.5 h-3.5 bg-white border-2 border-red-600 rounded-full shadow cursor-grab active:cursor-grabbing transform -translate-x-1/2" style="left: ${playerProgress}%"></div>
              </div>

              <!-- Controls row -->
              <div class="flex items-center justify-between text-xs font-mono text-neutral-300">
                <div class="flex items-center gap-4">
                  <!-- Play/Pause Button -->
                  <button id="player-toggle-btn" class="hover:text-white transition cursor-pointer text-sm">
                    ${isPlayerPlaying ? '⏸️' : '▶️'}
                  </button>
                  
                  <!-- Volume control block -->
                  <div class="flex items-center gap-1.5">
                    <span id="volume-icon">🔊</span>
                    <input type="range" id="volume-range" min="0" max="100" value="${playerVolume}" class="w-16 h-1 bg-neutral-800 rounded-lg appearance-none cursor-pointer accent-amber-500">
                  </div>

                  <!-- Time Counters -->
                  <div class="text-[10px] text-neutral-400">
                    <span id="player-current-time">00:45:30</span> / <span id="player-total-time">${movie.durationOrEpisodes}</span>
                  </div>
                </div>

                <div class="flex items-center gap-3">
                  <button id="player-cast-btn" class="bg-amber-500/10 border border-amber-500/20 text-amber-500 hover:bg-amber-500 hover:text-black font-extrabold text-[10px] px-2.5 py-1 rounded-lg transition cursor-pointer flex items-center gap-1">
                    📶 投屏 TV
                  </button>
                  <span class="text-[10px] text-neutral-500 font-mono select-none">CDN 加速开启</span>
                </div>
              </div>

            </div>

          </div>
        </div>

        <!-- LINE CHANGER & TV PROJECTION GUIDELINES -->
        <div class="bg-neutral-900 border border-neutral-850 p-5 rounded-3xl space-y-4">
          <div class="flex items-center justify-between">
            <span class="text-[11px] font-mono text-amber-500 font-bold block uppercase tracking-wider">MULTIPLE HIGH-SPEED CHANNELS</span>
            <span class="text-[10px] text-neutral-500 font-mono">若播放失败或卡顿，请切换备用线路</span>
          </div>

          <div class="grid grid-cols-2 sm:grid-cols-4 gap-2.5">
            <button class="line-btn px-4 py-2.5 text-xs font-bold rounded-xl border transition text-center cursor-pointer bg-neutral-950 border-amber-500 text-amber-400" data-line-name="北京电信专线 4K">
              <div>北京电信专线</div>
              <div class="text-[8px] opacity-60 font-mono mt-0.5">时延: 12ms (推荐)</div>
            </button>
            <button class="line-btn px-4 py-2.5 text-xs font-bold rounded-xl border transition text-center cursor-pointer bg-neutral-950 border-neutral-850 text-neutral-400 hover:border-neutral-700" data-line-name="上海联通专线 HD">
              <div>上海联通专线</div>
              <div class="text-[8px] opacity-60 font-mono mt-0.5">时延: 18ms</div>
            </button>
            <button class="line-btn px-4 py-2.5 text-xs font-bold rounded-xl border transition text-center cursor-pointer bg-neutral-950 border-neutral-850 text-neutral-400 hover:border-neutral-700" data-line-name="香港BGP多线 蓝光">
              <div>香港BGP多线</div>
              <div class="text-[8px] opacity-60 font-mono mt-0.5">时延: 22ms (海外)</div>
            </button>
            <button class="line-btn px-4 py-2.5 text-xs font-bold rounded-xl border transition text-center cursor-pointer bg-neutral-950 border-neutral-850 text-neutral-400 hover:border-neutral-700" data-line-name="腾讯云全球加速">
              <div>腾讯CDN专线</div>
              <div class="text-[8px] opacity-60 font-mono mt-0.5">时延: 15ms (云主干)</div>
            </button>
          </div>
        </div>

        <!-- Specifications / Description Segment -->
        <div class="space-y-4">
          <div class="border-b border-neutral-900 pb-3">
            <h3 class="text-lg font-extrabold text-white">影视基本详情公示</h3>
            <p class="text-[10px] text-neutral-500 font-mono">以下数据及版权信息由北京七七八八网络科技公司核实公示</p>
          </div>

          <p class="text-xs sm:text-sm text-neutral-400 leading-relaxed font-sans">
            ${movie.description}
          </p>

          <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 bg-neutral-950/60 p-5 rounded-2xl border border-neutral-900 text-xs font-mono">
            <div class="space-y-1.5">
              <div>导演: <strong class="text-neutral-200 font-sans font-normal">${movie.director}</strong></div>
              <div>主演: <strong class="text-neutral-200 font-sans font-normal">${movie.actors}</strong></div>
              <div>地区: <strong class="text-neutral-200">${movie.region}</strong></div>
            </div>
            <div class="space-y-1.5">
              <div>更新状态: <strong class="text-amber-500 font-bold">${movie.updateStatus}</strong></div>
              <div>上映年份: <strong class="text-neutral-200">${movie.year}年</strong></div>
              <div>版权属性: <strong class="text-green-500 font-bold">正版授权合作播放</strong></div>
            </div>
          </div>
        </div>

      </div>

      <!-- Right Column: Related Movies Recommendations -->
      <div class="lg:col-span-4 space-y-6">
        <div class="border-b border-neutral-900 pb-3">
          <h3 class="text-base font-extrabold text-white flex items-center gap-1.5">
            🔥 <span>相关推荐 · 大家都在看</span>
          </h3>
          <p class="text-[10px] text-neutral-500 font-mono">根据您的偏好和播放历史推荐</p>
        </div>

        <div class="space-y-3" id="modal-related-list">
          ${relatedHtml}
        </div>

        <div class="p-5 bg-gradient-to-tr from-neutral-900/60 to-neutral-950/80 border border-neutral-850 rounded-3xl space-y-3.5">
          <h4 class="text-white text-xs font-black font-sans flex items-center gap-1">
            📱 智能TV一键投屏指南
          </h4>
          <p class="text-[11px] text-neutral-400 leading-relaxed">
            7788电影网自主研发的“AirCast投屏模块”已部署于播放器内部。当您在手机浏览器中点击【投屏 TV】时，解码引擎会自动在局域网内搜寻并激活电视端播放器，无需安装任何第3方APP，彻底让您回归客厅大屏高清快感。
          </p>
        </div>
      </div>

    </div>
  `;

  // Dynamic Bindings within modal
  const playBtn = document.getElementById('player-toggle-btn');
  const screenPlayBtn = document.getElementById('player-screen-play-btn');
  const centerIcon = document.getElementById('player-center-icon');
  const screenStatus = document.getElementById('player-screen-status');
  const progressBar = document.getElementById('player-progress-bar');
  const volumeRange = document.getElementById('volume-range') as HTMLInputElement;
  const volumeIcon = document.getElementById('volume-icon');
  const castBtn = document.getElementById('player-cast-btn');

  const togglePlay = () => {
    isPlayerPlaying = !isPlayerPlaying;
    if (playBtn) playBtn.innerText = isPlayerPlaying ? '⏸️' : '▶️';
    if (centerIcon) centerIcon.innerText = isPlayerPlaying ? '⏸️' : '▶️';
    if (screenStatus) screenStatus.innerText = isPlayerPlaying ? '正在解码专线高壓縮流媒体...' : '已暂停播放';
  };

  if (playBtn) playBtn.addEventListener('click', togglePlay);
  if (screenPlayBtn) screenPlayBtn.addEventListener('click', togglePlay);

  // Volume slider
  if (volumeRange) {
    volumeRange.addEventListener('input', (e) => {
      const val = parseInt((e.target as HTMLInputElement).value, 10);
      playerVolume = val;
      if (volumeIcon) {
        if (val === 0) volumeIcon.innerText = '🔇';
        else if (val < 40) volumeIcon.innerText = '🔈';
        else if (val < 80) volumeIcon.innerText = '🔉';
        else volumeIcon.innerText = '🔊';
      }
    });
  }

  // Progress Bar click to seek
  if (progressBar) {
    progressBar.addEventListener('click', (e) => {
      const rect = progressBar.getBoundingClientRect();
      const clickX = e.clientX - rect.left;
      const pct = Math.min(Math.max((clickX / rect.width) * 100, 0), 100);
      playerProgress = pct;
      
      const fillBar = document.getElementById('player-progress-fill');
      const handlerDot = document.getElementById('player-progress-handle');
      if (fillBar) fillBar.style.width = `${pct}%`;
      if (handlerDot) handlerDot.style.left = `${pct}%`;
    });
  }

  // Cast Overlay Click
  if (castBtn) {
    castBtn.addEventListener('click', () => {
      alert(`📶 正在扫描局域网投屏终端...\n\n找到以下设备：\n1. [客厅小米电视4K电视] - 信号良好\n2. [主卧华为智能屏] - 信号较弱\n\n已成功连接“客厅小米电视4K电视”！高清大屏全集投射中，请拿起您的电视遥控器观赏！`);
    });
  }

  // Line buttons
  const lineBtns = document.querySelectorAll('.line-btn');
  lineBtns.forEach(btn => {
    btn.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const lineName = target.getAttribute('data-line-name') || '';
      selectedPlaybackLine = lineName;

      // Update state in UI
      const currentLineDisp = document.getElementById('current-line-display');
      const overlayDisp = document.getElementById('playback-line-overlay');
      if (currentLineDisp) currentLineDisp.innerText = lineName;
      if (overlayDisp) overlayDisp.innerText = `线路: ${lineName}`;

      // Reset active button border class
      lineBtns.forEach(b => {
        b.className = "line-btn px-4 py-2.5 text-xs font-bold rounded-xl border transition text-center cursor-pointer bg-neutral-950 border-neutral-850 text-neutral-400 hover:border-neutral-700";
      });
      target.className = "line-btn px-4 py-2.5 text-xs font-bold rounded-xl border transition text-center cursor-pointer bg-neutral-950 border-amber-500 text-amber-400";

      // Brief alert
      const popupToast = document.createElement('div');
      popupToast.className = "fixed bottom-10 left-1/2 -translate-x-1/2 z-50 bg-amber-500 text-black text-xs font-black px-4.5 py-2.5 rounded-xl shadow-xl animate-bounce";
      popupToast.innerText = `已成功切换到 ${lineName}，视频无缝连接！`;
      document.body.appendChild(popupToast);
      setTimeout(() => popupToast.remove(), 2500);
    });
  });

  // Re-bind click to related suggestions within the modal (so modal updates to the selected recommendation)
  const relCards = document.querySelectorAll('.modal-related-card');
  relCards.forEach(card => {
    card.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const id = target.getAttribute('data-movie-id');
      if (id) {
        // Switch dialog data
        openMovieDetailModal(id);
        // Scroll modal top if it overflowed
        const dialogContainer = elements.movieDetailDialog?.querySelector('.bg-neutral-900');
        if (dialogContainer) dialogContainer.scrollTo({ top: 0, behavior: 'smooth' });
      }
    });
  });
}


// ==================== INTERACTIVE CANVAS MAP ENGINE ====================

function initMapEngine() {
  const canvas = elements.mapCanvas;
  if (!canvas) return;

  // Set canvas physical width based on container bounding box
  const resizeCanvas = () => {
    const parent = canvas.parentElement;
    if (parent) {
      canvas.width = parent.clientWidth;
      canvas.height = parent.clientHeight;
      drawMap();
    }
  };

  resizeCanvas();
  window.addEventListener('resize', resizeCanvas);

  // Redraw loop
  function drawMap() {
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const width = canvas.width;
    const height = canvas.height;

    // Clear background
    ctx.fillStyle = "#0c0c0e";
    ctx.fillRect(0, 0, width, height);

    ctx.save();
    // Apply panning and zooming translations
    ctx.translate(width / 2 + mapOffsetX, height / 2 + mapOffsetY);
    ctx.scale(mapZoom, mapZoom);
    // Move center of local coordinate system 800x500 to origin
    ctx.translate(-400, -250);

    // 1. Draw subtle grid grid lines
    ctx.strokeStyle = "#16161a";
    ctx.lineWidth = 1;
    for (let x = -400; x < 1200; x += 50) {
      ctx.beginPath();
      ctx.moveTo(x, -200);
      ctx.lineTo(x, 700);
      ctx.stroke();
    }
    for (let y = -200; y < 700; y += 50) {
      ctx.beginPath();
      ctx.moveTo(-400, y);
      ctx.lineTo(1200, y);
      ctx.stroke();
    }

    // 2. Draw roads / avenues
    ctx.fillStyle = "#141416";
    // Zhongguancun South Road (Horizontal)
    ctx.fillRect(-200, 230, 1200, 40);
    // Zhongguancun East Road (Vertical)
    ctx.fillRect(380, -100, 40, 700);

    // Road labels
    ctx.fillStyle = "#2e2e36";
    ctx.font = "bold 10px font-sans";
    ctx.fillText("中 关 村 南 路", 150, 254);
    ctx.fillText("中 关 村 东 路", 395, 80);

    // 3. Draw fiber connections (pulsing lines from Headquarters to high bandwidth BGP room)
    const hq = MAP_POIS[0];
    const bgp = MAP_POIS[1];
    
    ctx.strokeStyle = "rgba(245, 158, 11, 0.25)";
    ctx.lineWidth = 2.5;
    ctx.beginPath();
    ctx.moveTo(hq.x, hq.y);
    ctx.lineTo(bgp.x, bgp.y);
    ctx.stroke();

    // Pulsing data beam particles
    const time = Date.now() * 0.003;
    const progress = (time % 1);
    const beamX = hq.x + (bgp.x - hq.x) * progress;
    const beamY = hq.y + (bgp.y - hq.y) * progress;

    ctx.fillStyle = "#f59e0b";
    ctx.beginPath();
    ctx.arc(beamX, beamY, 4, 0, Math.PI * 2);
    ctx.fill();

    // 4. Draw markers
    MAP_POIS.forEach((poi, index) => {
      const isSelected = selectedPoiIndex === index;
      
      // Draw outer halos
      if (isSelected) {
        ctx.fillStyle = index === 0 ? "rgba(239, 68, 68, 0.15)" : "rgba(245, 158, 11, 0.15)";
        ctx.beginPath();
        ctx.arc(poi.x, poi.y, 25 + Math.sin(Date.now() * 0.005) * 4, 0, Math.PI * 2);
        ctx.fill();

        ctx.strokeStyle = index === 0 ? "rgba(239, 68, 68, 0.4)" : "rgba(245, 158, 11, 0.4)";
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        ctx.arc(poi.x, poi.y, 20 + Math.sin(Date.now() * 0.005) * 3, 0, Math.PI * 2);
        ctx.stroke();
      }

      // Draw main pin anchor dot
      ctx.fillStyle = index === 0 ? "#ef4444" : (index === 1 ? "#f59e0b" : "#3b82f6");
      ctx.beginPath();
      ctx.arc(poi.x, poi.y, 8, 0, Math.PI * 2);
      ctx.fill();

      // White inner core
      ctx.fillStyle = "#ffffff";
      ctx.beginPath();
      ctx.arc(poi.x, poi.y, 3.5, 0, Math.PI * 2);
      ctx.fill();

      // Text Labels
      ctx.fillStyle = isSelected ? "#ffffff" : "#8e8e93";
      ctx.font = isSelected ? "bold 11px font-sans" : "9px font-sans";
      ctx.fillText(poi.title, poi.x - 50, poi.y - 15);
    });

    ctx.restore();
  }

  // Panning & Clicking Event Listeners
  canvas.addEventListener('mousedown', (e) => {
    isDraggingMap = true;
    startDragX = e.clientX - mapOffsetX;
    startDragY = e.clientY - mapOffsetY;
    canvas.style.cursor = 'grabbing';
  });

  window.addEventListener('mousemove', (e) => {
    if (!isDraggingMap) return;
    mapOffsetX = e.clientX - startDragX;
    mapOffsetY = e.clientY - startDragY;
    drawMap();
  });

  window.addEventListener('mouseup', () => {
    isDraggingMap = false;
    canvas.style.cursor = 'grab';
  });

  // Wheel zoom
  canvas.addEventListener('wheel', (e) => {
    e.preventDefault();
    const zoomFactor = e.deltaY < 0 ? 1.08 : 0.92;
    mapZoom = Math.min(Math.max(mapZoom * zoomFactor, 0.5), 3.0);
    drawMap();
  });

  // Click on map to detect marker hits
  canvas.addEventListener('click', (e) => {
    const rect = canvas.getBoundingClientRect();
    const clickX = e.clientX - rect.left;
    const clickY = e.clientY - rect.top;

    // Convert screen coordinates back to local coordinate system (inverse translate & scale)
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const localX = (clickX - centerX - mapOffsetX) / mapZoom + 400;
    const localY = (clickY - centerY - mapOffsetY) / mapZoom + 250;

    // Find nearest POI
    let hitIndex = -1;
    let minDist = 30; // hit tolerance in local pixels
    MAP_POIS.forEach((poi, index) => {
      const d = Math.sqrt((poi.x - localX) ** 2 + (poi.y - localY) ** 2);
      if (d < minDist) {
        minDist = d;
        hitIndex = index;
      }
    });

    if (hitIndex !== -1) {
      selectPoi(hitIndex);
    }
  });

  // Trigger continuous rendering for beam pulse animations
  let animId: any = null;
  function animate() {
    drawMap();
    animId = requestAnimationFrame(animate);
  }
  animate();

  // Handle zooming buttons
  elements.mapZoomIn?.addEventListener('click', () => {
    mapZoom = Math.min(mapZoom * 1.15, 3.0);
    drawMap();
  });

  elements.mapZoomOut?.addEventListener('click', () => {
    mapZoom = Math.max(mapZoom * 0.85, 0.5);
    drawMap();
  });

  elements.mapReset?.addEventListener('click', () => {
    mapZoom = 1.0;
    mapOffsetX = 0;
    mapOffsetY = 0;
    drawMap();
  });
}

function selectPoi(index: number) {
  selectedPoiIndex = index;
  const poi = MAP_POIS[index];
  if (!poi) return;

  // Center view on this POI coordinates
  mapOffsetX = 0;
  mapOffsetY = 0;
  mapZoom = 1.2; // slight zoom in

  // Slide-offset to center
  const canvas = elements.mapCanvas;
  if (canvas) {
    // We want the POI to land exactly in the center of the viewport
    // local coordinates: x, y
    // center of canvas: width/2, height/2
    // formula: localCoord = (screenCoord - halfSize - offset) / zoom + localCenter
    // therefore to land local POI on screen center (screenCoord = halfSize):
    // offset = localCenter - localCoord * zoom?
    // Actually simply centering:
    mapOffsetX = (400 - poi.x) * mapZoom;
    mapOffsetY = (250 - poi.y) * mapZoom;
  }

  // Update POI Details card
  if (elements.poiTitleDisplay) elements.poiTitleDisplay.innerText = poi.title;
  if (elements.poiDescDisplay) elements.poiDescDisplay.innerText = poi.desc;
  if (elements.poiDistDisplay) elements.poiDistDisplay.innerText = `DISTANCE: ${poi.distance}`;

  // Style the list buttons
  const rows = document.querySelectorAll('.poi-row-btn');
  rows.forEach(row => {
    row.className = "poi-row-btn w-full text-left p-3.5 rounded-2xl bg-neutral-950/60 border border-neutral-850 hover:border-neutral-800 transition flex items-center justify-between group cursor-pointer";
  });
  const activeRow = document.querySelector(`[data-poi-idx="${index}"]`);
  if (activeRow) {
    activeRow.className = "poi-row-btn w-full text-left p-3.5 rounded-2xl bg-neutral-900 border border-amber-500/40 hover:border-amber-500/50 transition flex items-center justify-between group cursor-pointer shadow-lg";
  }
}


// ==================== LIVE CUSTOMER ROBOT CHAT SIMULATOR ====================

function handleChatSubmit(e: Event) {
  e.preventDefault();
  if (!elements.chatUserInput || !elements.chatMessagesContainer) return;

  const msg = elements.chatUserInput.value.trim();
  if (msg === '') return;

  appendChatMessage('user', msg);
  elements.chatUserInput.value = '';

  // Trigger simulated typing bubble
  const typingId = 'typing-' + Date.now();
  appendTypingIndicator(typingId);

  // Scroll bottom
  elements.chatMessagesContainer.scrollTop = elements.chatMessagesContainer.scrollHeight;

  // Delay automated reply
  setTimeout(() => {
    removeTypingIndicator(typingId);
    const reply = generateBotReply(msg);
    appendChatMessage('bot', reply);
    elements.chatMessagesContainer!.scrollTop = elements.chatMessagesContainer!.scrollHeight;
    
    // Bind click handlers inside the newly created chat text triggers (like [立即播放])
    bindChatTriggers();
  }, 950);
}

function appendChatMessage(sender: 'user' | 'bot', text: string) {
  const container = elements.chatMessagesContainer;
  if (!container) return;

  const row = document.createElement('div');
  row.className = "flex items-start gap-2.5 animate-in slide-in-from-bottom-2 duration-200";

  if (sender === 'user') {
    row.classList.add('justify-end');
    row.innerHTML = `
      <div class="bg-gradient-to-r from-red-600 to-amber-600 text-[11px] text-white px-3.5 py-2.5 rounded-2xl rounded-tr-none max-w-[85%] leading-relaxed shadow-lg font-medium">
        ${text}
      </div>
      <div class="w-7 h-7 rounded-lg bg-neutral-800 text-neutral-300 text-[10px] font-bold flex items-center justify-center shrink-0">您</div>
    `;
  } else {
    row.innerHTML = `
      <div class="w-7 h-7 rounded-lg bg-amber-500/10 text-amber-500 border border-amber-500/20 text-xs flex items-center justify-center shrink-0">🤖</div>
      <div class="bg-neutral-900 border border-neutral-850 text-[11px] text-neutral-300 px-3.5 py-2.5 rounded-2xl rounded-tl-none max-w-[85%] leading-relaxed">
        ${text}
      </div>
    `;
  }

  container.appendChild(row);
}

function appendTypingIndicator(id: string) {
  const container = elements.chatMessagesContainer;
  if (!container) return;

  const row = document.createElement('div');
  row.id = id;
  row.className = "flex items-start gap-2.5 animate-in fade-in";
  row.innerHTML = `
    <div class="w-7 h-7 rounded-lg bg-amber-500/10 text-amber-500 border border-amber-500/20 text-xs flex items-center justify-center shrink-0">🤖</div>
    <div class="bg-neutral-900 border border-neutral-850 text-[10px] text-neutral-500 px-3.5 py-2.5 rounded-2xl rounded-tl-none flex items-center gap-1.5">
      <span class="w-1.5 h-1.5 rounded-full bg-neutral-600 animate-bounce" style="animation-delay: 0ms"></span>
      <span class="w-1.5 h-1.5 rounded-full bg-neutral-600 animate-bounce" style="animation-delay: 150ms"></span>
      <span class="w-1.5 h-1.5 rounded-full bg-neutral-600 animate-bounce" style="animation-delay: 300ms"></span>
      <span class="font-mono">7788搜片助理正在计算输入...</span>
    </div>
  `;
  container.appendChild(row);
}

function removeTypingIndicator(id: string) {
  const el = document.getElementById(id);
  if (el) el.remove();
}

function generateBotReply(msg: string): string {
  const q = msg.toLowerCase().trim();

  if (q.includes('流浪星河') || q.includes('宇宙') || q.includes('吴京')) {
    return `为您定位到2026年独创科幻片首选《流浪星河：地球重置计划》！本站已自动为您匹配5G/BGP高速专用电信原画专线。点击这里：<span class="text-amber-400 font-black underline cursor-pointer chat-play-trigger" data-id="m1">[立即高清免VIP播放 4K]</span>`;
  }
  if (q.includes('长安') || q.includes('梦华录') || q.includes('电视剧') || q.includes('金吾卫')) {
    return `为您推荐电视剧频道冠军大作《长安梦华录：金吾卫之谜》！最新手机在线追剧全集，已更新至28集。点击这里：<span class="text-amber-400 font-black underline cursor-pointer chat-play-trigger" data-id="m2">[立即高清播放最新集]</span>`;
  }
  if (q.includes('卡顿') || q.includes('播放失败') || q.includes('无法播放') || q.includes('慢')) {
    return `7788播放流畅度排查法：\n\n1. 点击播放器左下的【更换线路】选项，推荐首选【北京电信专线】或【上海联通专线】，时延低至12ms。\n2. 请检查手机浏览器是否开启了默认的'极速/省流模式'，部分浏览器省流会过滤高画质流媒体包。\n3. 清理手机系统浏览器缓存在线再次刷新，即可完美秒开4K画质！`;
  }
  if (q.includes('投屏') || q.includes('电视') || q.includes('盒子')) {
    return `7788电影网TV智能投屏指南：\n\n1. 请确保您的手机与智能电视连接在【同个WiFi局域网】下。\n2. 手机打开7788任意视频，在播放器控制栏右下角点击【📶 投屏 TV】按钮。\n3. 视频流媒体分发中心将自动探测嗅探DLNA设备，在列表中选择您的电视名称，即可秒速投射大屏免费观看全集！`;
  }
  if (q.includes('动漫') || q.includes('九天') || q.includes('凡人')) {
    return `7788精品动漫频道为您全力奉献《九天神域：凡人成仙传》与《幻兽之境：启示录》。全集高清3D无广告弹窗干扰，每周六零点准时更新上线！`;
  }
  if (q.includes('求片') || q.includes('上架') || q.includes('资源') || q.includes('片源')) {
    return `求片工单已收悉！我已经将您的需求【"${msg}"】实时推送到版权库自动检索队列。请留下您的邮箱或QQ号码，一旦捕获到高清可用免VIP源，我们将立刻短信/邮件通知您，最快只需2小时！`;
  }

  return `收到您的留言！关于“${msg}”的技术或片源问题，我已经记录并同步发送给7788技术总监李秋泽先生团队，我们将在24小时内安排版权专员与您对接核对！\n\n您也可以通过【快速快捷频道】标签直接筛选电影或电视剧全集。`;
}

function bindChatTriggers() {
  const triggers = document.querySelectorAll('.chat-play-trigger');
  triggers.forEach(trig => {
    trig.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const movieId = target.getAttribute('data-id');
      if (movieId) {
        openMovieDetailModal(movieId);
      }
    });
  });
}


// ==================== INITIAL EVENT BINDINGS ====================

function bindCoreEvents() {
  
  // Tab links clicks (Header, Footer, Mobile)
  const tabTriggers = document.querySelectorAll('[data-tab]');
  tabTriggers.forEach(trig => {
    trig.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const tabName = target.getAttribute('data-tab') || 'home';
      switchTab(tabName);
    });
  });

  // Logo button click (returns Home)
  elements.logoBtn?.addEventListener('click', () => switchTab('home'));
  elements.footerLogo?.addEventListener('click', () => switchTab('home'));

  // Mobile drawer trigger
  elements.mobileMenuToggle?.addEventListener('click', () => {
    if (elements.mobileDrawer) {
      elements.mobileDrawer.classList.toggle('hidden');
    }
  });

  // Header quick search button
  elements.searchShortcutBtn?.addEventListener('click', () => {
    switchTab('products');
    setTimeout(() => {
      elements.movieSearchInput?.focus();
    }, 150);
  });

  // Mobile actions redirect
  elements.mobileSearchTrigger?.addEventListener('click', () => {
    switchTab('products');
    setTimeout(() => {
      elements.movieSearchInput?.focus();
    }, 150);
  });

  elements.mobileContactTrigger?.addEventListener('click', () => {
    switchTab('contact');
  });

  elements.headerContactBtn?.addEventListener('click', () => {
    switchTab('contact');
  });

  // Ad contact button
  elements.adContactTriggerBtn?.addEventListener('click', () => {
    switchTab('contact');
  });

  // View more popular buttons
  elements.homeViewMorePopularBtn?.addEventListener('click', () => {
    filterType = '电视剧';
    
    // Switch the filter pill active states
    const pills = document.querySelectorAll('#filter-type .filter-pill');
    pills.forEach(p => {
      const v = p.getAttribute('data-value');
      if (v === '电视剧') {
        p.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-amber-500 border-amber-500 text-black";
      } else {
        bSetInactivePill(p as HTMLElement);
      }
    });

    switchTab('products');
    renderCatalog();
  });

  function bSetInactivePill(p: HTMLElement) {
    p.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-neutral-950 border-neutral-850 text-neutral-400 hover:text-white hover:border-neutral-700";
  }

  // Hero section interactions
  elements.heroPlayBtn?.addEventListener('click', () => {
    openMovieDetailModal('m1');
  });

  elements.heroFilterBtn?.addEventListener('click', () => {
    filterType = '电视剧';
    
    const pills = document.querySelectorAll('#filter-type .filter-pill');
    pills.forEach(p => {
      const v = p.getAttribute('data-value');
      if (v === '电视剧') {
        p.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-amber-500 border-amber-500 text-black";
      } else {
        bSetInactivePill(p as HTMLElement);
      }
    });

    switchTab('products');
    renderCatalog();
  });

  // Category Quick shortcut Cards on Home tab
  const catShortcutCards = document.querySelectorAll('.category-shortcut-card');
  catShortcutCards.forEach(card => {
    card.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const type = target.getAttribute('data-type');
      const region = target.getAttribute('data-region');

      if (type) {
        filterType = type;
        const pills = document.querySelectorAll('#filter-type .filter-pill');
        pills.forEach(p => {
          const v = p.getAttribute('data-value');
          if (v === type) {
            p.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-amber-500 border-amber-500 text-black";
          } else {
            bSetInactivePill(p as HTMLElement);
          }
        });
      }

      if (region) {
        filterRegion = region;
        const pills = document.querySelectorAll('#filter-region .filter-pill');
        pills.forEach(p => {
          const v = p.getAttribute('data-value');
          if (v === region) {
            p.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-amber-500 border-amber-500 text-black";
          } else {
            bSetInactivePill(p as HTMLElement);
          }
        });
      }

      switchTab('products');
      renderCatalog();
    });
  });

  // Global Ctrl+K Search hotkey
  window.addEventListener('keydown', (e) => {
    if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
      e.preventDefault();
      switchTab('products');
      setTimeout(() => {
        elements.movieSearchInput?.focus();
      }, 150);
    }
  });


  // ==================== PRODUCTS TAB LISTENERS ====================

  // Input Search
  elements.movieSearchInput?.addEventListener('input', (e) => {
    const val = (e.target as HTMLInputElement).value;
    searchQuery = val;
    
    if (val.trim() !== '') {
      elements.searchClearBtn?.classList.remove('hidden');
    } else {
      elements.searchClearBtn?.classList.add('hidden');
    }
    
    renderCatalog();
  });

  // Clear search input
  elements.searchClearBtn?.addEventListener('click', () => {
    elements.movieSearchInput.value = '';
    searchQuery = '';
    elements.searchClearBtn?.classList.add('hidden');
    renderCatalog();
  });

  // Filter Pills setup (Type, Region, Year)
  setupPillGroup('filter-type', (val) => {
    filterType = val;
    renderCatalog();
  });

  setupPillGroup('filter-region', (val) => {
    filterRegion = val;
    renderCatalog();
  });

  setupPillGroup('filter-year', (val) => {
    filterYear = val;
    renderCatalog();
  });

  // Sorting Selector
  elements.filterSort?.addEventListener('change', (e) => {
    filterSort = (e.target as HTMLSelectElement).value;
    renderCatalog();
  });

  // Empty state reset button
  elements.emptyStateResetBtn?.addEventListener('click', () => {
    resetAllFilters();
  });

  function setupPillGroup(containerId: string, callback: (v: string) => void) {
    const container = document.getElementById(containerId);
    if (!container) return;

    const pills = container.querySelectorAll('.filter-pill');
    pills.forEach(pill => {
      pill.addEventListener('click', (e) => {
        const target = e.currentTarget as HTMLElement;
        const val = target.getAttribute('data-value') || '全部';
        
        pills.forEach(p => bSetInactivePill(p as HTMLElement));
        target.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-amber-500 border-amber-500 text-black";

        callback(val);
      });
    });
  }

  function resetAllFilters() {
    searchQuery = '';
    filterType = '全部';
    filterRegion = '全部';
    filterYear = '全部';
    filterSort = '最热点击';

    if (elements.movieSearchInput) elements.movieSearchInput.value = '';
    elements.searchClearBtn?.classList.add('hidden');
    
    if (elements.filterSort) elements.filterSort.value = '最热点击';

    // Reset pills in UI
    const pillGroups = ['filter-type', 'filter-region', 'filter-year'];
    pillGroups.forEach(gId => {
      const container = document.getElementById(gId);
      if (container) {
        const pills = container.querySelectorAll('.filter-pill');
        pills.forEach((p, idx) => {
          if (idx === 0) {
            p.className = "filter-pill px-3.5 py-1.5 rounded-xl font-bold font-sans tracking-wide border transition cursor-pointer bg-amber-500 border-amber-500 text-black";
          } else {
            bSetInactivePill(p as HTMLElement);
          }
        });
      }
    });

    renderCatalog();
  }


  // ==================== TIMELINE EVENT SELECTION ====================

  const timelineBtns = document.querySelectorAll('.timeline-btn');
  timelineBtns.forEach(btn => {
    btn.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const idx = parseInt(target.getAttribute('data-timeline-idx') || '0', 10);
      selectedTimelineIndex = idx;

      // Update pill classes
      timelineBtns.forEach(b => {
        b.className = "timeline-btn px-4 py-2 text-xs font-bold rounded-xl transition text-neutral-500 hover:text-white";
      });
      target.className = "timeline-btn px-4 py-2 text-xs font-bold rounded-xl transition bg-gradient-to-r from-amber-500 to-red-600 text-white shadow-md";

      // Render content details
      const evt = HISTORY_EVENTS[idx];
      if (evt) {
        if (elements.timelineYearDisplay) elements.timelineYearDisplay.innerText = evt.year;
        if (elements.timelineTitleDisplay) elements.timelineTitleDisplay.innerText = evt.title;
        if (elements.timelineDescDisplay) elements.timelineDescDisplay.innerText = evt.description;
      }
    });
  });


  // ==================== POIS LIST SELECTORS ====================

  const poiBtns = document.querySelectorAll('.poi-row-btn');
  poiBtns.forEach(btn => {
    btn.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const idx = parseInt(target.getAttribute('data-poi-idx') || '0', 10);
      selectPoi(idx);
    });
  });


  // ==================== CONTACT FORM SUBMISSION ====================

  elements.contactForm?.addEventListener('submit', (e) => {
    e.preventDefault();
    const nameInput = document.getElementById('form-name') as HTMLInputElement;
    const phoneInput = document.getElementById('form-phone') as HTMLInputElement;
    const emailInput = document.getElementById('form-email') as HTMLInputElement;
    const typeSelect = document.getElementById('form-type') as HTMLSelectElement;
    const contentText = document.getElementById('form-content') as HTMLTextAreaElement;

    if (!nameInput.value || !contentText.value) return;

    // Simulate submission progress
    elements.formSubmitBtn.disabled = true;
    if (elements.formBtnText) elements.formBtnText.innerText = "正在提交加密通道中...";

    setTimeout(() => {
      // Restore form button
      elements.formSubmitBtn.disabled = false;
      if (elements.formBtnText) elements.formBtnText.innerText = "提交合作与反馈方案";

      // Populate success toast details
      if (elements.toastMessageBody) {
        elements.toastMessageBody.innerHTML = `感谢您的合作与反馈，<strong>${nameInput.value}</strong> 先生/女士。我们已将您关于“<strong>${typeSelect.value}</strong>”的申诉与描述成功记录在7788流媒体工单池中。`;
      }
      if (elements.toastTicketId) {
        elements.toastTicketId.innerText = `工单流水号: 7788-TKT-${Math.floor(100000 + Math.random() * 900000)}`;
      }

      // Show toast
      elements.successToast?.classList.remove('hidden');
      
      // Auto-dismiss toast in 8 seconds
      setTimeout(() => {
        elements.successToast?.classList.add('hidden');
      }, 8000);

      // Clear Form
      elements.contactForm.reset();

    }, 1200);
  });

  // Close toast button
  elements.toastCloseBtn?.addEventListener('click', () => {
    elements.successToast?.classList.add('hidden');
  });


  // ==================== PLAYBACK DETAIL DIALOG ====================

  elements.modalCloseBtn?.addEventListener('click', () => {
    closeMovieDetailModal();
  });

  elements.movieDetailDialog?.addEventListener('click', (e) => {
    // Click on overlay background closes dialog
    if (e.target === elements.movieDetailDialog) {
      closeMovieDetailModal();
    }
  });


  // ==================== REALTIME CHAT INTERACTS ====================

  elements.liveChatTrigger?.addEventListener('click', () => {
    elements.liveChatWindow?.classList.toggle('hidden');
  });

  elements.liveChatCloseBtn?.addEventListener('click', () => {
    elements.liveChatWindow?.classList.add('hidden');
  });

  elements.chatInputForm?.addEventListener('submit', handleChatSubmit);

  // Quick Chat Pills Clicking
  const quickPills = document.querySelectorAll('.chat-quick-pill');
  quickPills.forEach(pill => {
    pill.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const text = target.innerText;
      if (elements.chatUserInput) {
        elements.chatUserInput.value = text;
        // submit
        elements.chatInputForm.dispatchEvent(new Event('submit'));
      }
    });
  });

  // Click on keyword inside chat bubbles
  const quickKeywords = document.querySelectorAll('.chat-quick-keyword');
  quickKeywords.forEach(word => {
    word.addEventListener('click', (e) => {
      const target = e.currentTarget as HTMLElement;
      const text = target.innerText;
      if (elements.chatUserInput) {
        elements.chatUserInput.value = text;
        elements.chatInputForm.dispatchEvent(new Event('submit'));
      }
    });
  });
}

// ==================== APP INITIALIZATION ====================
function init() {
  // Render Home lists initially
  renderHomeMovies();
  renderHomeNews();
  renderAboutTeam();
  renderCatalog();

  // Attach all event listeners
  bindCoreEvents();

  // Initialize Map Engine
  initMapEngine();

  // Set default centered POI details
  selectPoi(0);
}

// Ensure DOM loaded before executing core code
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', init);
} else {
  init();
}
