import { useState, useEffect, useRef } from 'react';
import { useParams } from 'react-router-dom';
import { Spin, Result } from 'antd';
import { createRoot } from 'react-dom/client';
import axios from 'axios';
import type { LandingPage as LandingPageType } from '@/types/api';
import { VideoPlayer } from '@/components/media/VideoPlayer';
import { AdvancedVideoPlayer } from '@/components/media/AdvancedVideoPlayer';
import { DonationWidget } from '@/components/payments/DonationWidget';
import { PricingWidget } from '@/components/payments/PricingWidget';
import { ProductWidget } from '@/components/payments/ProductWidget';
import { CampaignFormWidget } from '@/components/influence/CampaignFormWidget';
import { SchedulingPollWidget } from '@/components/scheduling/SchedulingPollWidget';
import GalleryAdCard from '@/components/media/GalleryAdCard';
import type { GalleryAd } from '@/types/gallery-ads';
import { sanitizeLandingHtml, sanitizeLandingCss } from '@/utils/sanitize';

export default function PublicLandingPage() {
  const { slug } = useParams<{ slug: string }>();
  const [page, setPage] = useState<LandingPageType | null>(null);
  const [loading, setLoading] = useState(true);
  const [notFound, setNotFound] = useState(false);
  const contentRef = useRef<HTMLDivElement>(null);
  const videoRootsRef = useRef<Array<ReturnType<typeof createRoot>>>([]);
  const paymentRootsRef = useRef<Array<ReturnType<typeof createRoot>>>([]);
  const campaignFormRootsRef = useRef<Array<ReturnType<typeof createRoot>>>([]);
  const adRootsRef = useRef<Array<ReturnType<typeof createRoot>>>([]);
  const pollRootsRef = useRef<Array<ReturnType<typeof createRoot>>>([]);

  // Track page view
  useEffect(() => {
    if (!slug) return;
    const sessionHash = sessionStorage.getItem('cm_session') ||
      Math.random().toString(36).slice(2) + Date.now().toString(36);
    sessionStorage.setItem('cm_session', sessionHash);

    axios.post('/api/docs-analytics/track', {
      path: `/p/${slug}`,
      referrer: document.referrer || null,
      sessionHash,
    }).catch(() => {}); // fire-and-forget
  }, [slug]);

  useEffect(() => {
    const fetchPage = async () => {
      try {
        const { data } = await axios.get<LandingPageType>(`/api/pages/${slug}/view`);
        setPage(data);

        // Set SEO meta
        document.title = data.seoTitle || data.title;
        const metaDesc = document.querySelector('meta[name="description"]');
        if (metaDesc && data.seoDescription) {
          metaDesc.setAttribute('content', data.seoDescription);
        }
        const metaOgImage = document.querySelector('meta[property="og:image"]');
        if (metaOgImage && data.seoImage) {
          metaOgImage.setAttribute('content', data.seoImage);
        }
      } catch {
        setNotFound(true);
      } finally {
        setLoading(false);
      }
    };
    fetchPage();
  }, [slug]);

  // Hydrate video blocks after page renders
  useEffect(() => {
    if (!page || !contentRef.current) return;

    const hydrateVideoBlocks = () => {
      const videoBlocks = contentRef.current?.querySelectorAll('.video-block');
      if (!videoBlocks) return;

      // Clean up previous roots
      videoRootsRef.current.forEach((root) => {
        try {
          root.unmount();
        } catch (err) {
          console.error('Failed to unmount video root:', err);
        }
      });
      videoRootsRef.current = [];

      videoBlocks.forEach((blockEl) => {
        const videoIdStr = blockEl.getAttribute('data-video-id');
        const playerType = blockEl.getAttribute('data-player-type') || 'standard';
        const width = blockEl.getAttribute('data-width') || '100%';
        const height = blockEl.getAttribute('data-height') || 'auto';
        const autoplay = blockEl.getAttribute('data-autoplay') === 'true';
        const controls = blockEl.getAttribute('data-controls') !== 'false';
        const showReactions = blockEl.getAttribute('data-show-reactions') !== 'false';

        if (!videoIdStr || videoIdStr === 'PLACEHOLDER') {
          return; // Skip placeholder videos
        }

        const videoId = parseInt(videoIdStr, 10);
        if (isNaN(videoId)) {
          console.error('Invalid video ID:', videoIdStr);
          return;
        }

        // Find the placeholder div to replace
        const placeholder = blockEl.querySelector('.video-placeholder');
        if (!placeholder) {
          console.error('Video placeholder not found');
          return;
        }

        // Create a new container for React
        const container = document.createElement('div');
        placeholder.replaceWith(container);

        try {
          const root = createRoot(container);
          videoRootsRef.current.push(root);

          // Render appropriate player
          if (playerType === 'advanced') {
            root.render(
              <AdvancedVideoPlayer
                videoId={videoId}
                width={width}
                height={height}
                autoplay={autoplay}
                controls={controls}
                showReactions={showReactions}
              />
            );
          } else {
            root.render(
              <VideoPlayer
                videoId={videoId}
                width={width}
                height={height}
                autoplay={autoplay}
                controls={controls}
              />
            );
          }
        } catch (err) {
          console.error('Failed to render video player:', err);
        }
      });
    };

    // Hydrate video cards (static HTML, just refresh metadata)
    const hydrateVideoCards = async () => {
      const cards = contentRef.current?.querySelectorAll('.video-card-block');
      if (!cards) return;

      const mediaApiUrl = import.meta.env.VITE_MEDIA_API_URL || 'http://localhost:4100';

      for (const card of Array.from(cards)) {
        const videoId = card.getAttribute('data-video-id');
        if (!videoId || videoId === 'PLACEHOLDER') continue;

        try {
          const res = await fetch(`${mediaApiUrl}/api/videos/${videoId}/metadata`);
          if (!res.ok) continue;
          const meta = await res.json();

          // Update thumbnail
          const img = card.querySelector('img');
          if (img && meta.thumbnailUrl) {
            img.src = meta.thumbnailUrl;
          }

          // Update title text (first white text div in card body)
          const titleEl = card.querySelector('div[style*="font-weight: 600"][style*="color: #fff"]') as HTMLElement | null;
          if (titleEl && meta.title) {
            titleEl.textContent = meta.title;
          }
        } catch {
          // Silently skip — card keeps its static content
        }
      }
    };

    // Hydrate payment blocks (donate, pricing, product)
    const hydratePaymentBlocks = () => {
      const paymentBlocks = contentRef.current?.querySelectorAll('.payment-block');
      if (!paymentBlocks) return;

      // Clean up previous roots
      paymentRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount payment root:', err); }
      });
      paymentRootsRef.current = [];

      paymentBlocks.forEach((blockEl) => {
        const paymentType = blockEl.getAttribute('data-payment-type');
        if (!paymentType) return;

        // Create a container to replace block inner content
        const container = document.createElement('div');
        blockEl.innerHTML = '';
        blockEl.appendChild(container);

        try {
          const root = createRoot(container);
          paymentRootsRef.current.push(root);

          switch (paymentType) {
            case 'donate': {
              const buttonText = blockEl.getAttribute('data-button-text') || 'Donate Now';
              const showAmounts = blockEl.getAttribute('data-show-amounts') !== 'false';
              root.render(<DonationWidget buttonText={buttonText} showAmounts={showAmounts} />);
              break;
            }
            case 'pricing': {
              const showYearly = blockEl.getAttribute('data-show-yearly') !== 'false';
              root.render(<PricingWidget showYearlyToggle={showYearly} />);
              break;
            }
            case 'product': {
              const productSlug = blockEl.getAttribute('data-product-slug') || '';
              const buttonText = blockEl.getAttribute('data-button-text') || 'Buy Now';
              root.render(<ProductWidget productSlug={productSlug} buttonText={buttonText} />);
              break;
            }
          }
        } catch (err) {
          console.error('Failed to render payment widget:', err);
        }
      });
    };

    // Hydrate campaign form blocks
    const hydrateCampaignFormBlocks = () => {
      const formBlocks = contentRef.current?.querySelectorAll('.campaign-form-block');
      if (!formBlocks) return;

      // Clean up previous roots
      campaignFormRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount campaign form root:', err); }
      });
      campaignFormRootsRef.current = [];

      formBlocks.forEach((blockEl) => {
        const campaignSlug = blockEl.getAttribute('data-campaign-slug');
        if (!campaignSlug) return;

        const compact = blockEl.getAttribute('data-compact') === 'true';

        const container = document.createElement('div');
        blockEl.innerHTML = '';
        blockEl.appendChild(container);

        try {
          const root = createRoot(container);
          campaignFormRootsRef.current.push(root);
          root.render(<CampaignFormWidget campaignSlug={campaignSlug} compact={compact} />);
        } catch (err) {
          console.error('Failed to render campaign form widget:', err);
        }
      });
    };

    // Hydrate ad blocks (specific ad by ID + dynamic ad slot)
    const hydrateAdBlocks = async () => {
      const container = contentRef.current;
      if (!container) return;

      // Clean up previous roots
      adRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount ad root:', err); }
      });
      adRootsRef.current = [];

      // Hydrate specific ads (by ID)
      const specificBlocks = container.querySelectorAll('.ad-specific-block');
      for (const blockEl of Array.from(specificBlocks)) {
        const adIdStr = blockEl.getAttribute('data-ad-id');
        if (!adIdStr || adIdStr === '0') continue;

        try {
          const res = await axios.get<GalleryAd[]>('/api/gallery-ads');
          const ad = res.data.find((a: GalleryAd) => a.id === parseInt(adIdStr, 10));
          if (!ad) continue;

          const el = document.createElement('div');
          blockEl.innerHTML = '';
          blockEl.appendChild(el);

          const root = createRoot(el);
          adRootsRef.current.push(root);
          root.render(<GalleryAdCard ad={ad} />);
        } catch {
          // Silent fail
        }
      }

      // Hydrate dynamic ad slots
      const slotBlocks = container.querySelectorAll('.ad-slot-block');
      if (slotBlocks.length === 0) return;

      try {
        const { data: allAds } = await axios.get<GalleryAd[]>('/api/gallery-ads', {
          params: { placement: 'landing_page' },
        });
        if (allAds.length === 0) return;

        let adIndex = 0;
        for (const blockEl of Array.from(slotBlocks)) {
          const variant = blockEl.getAttribute('data-variant') || 'standard';
          // Pick an ad matching the variant, or fall back to any
          const matchingAd = allAds.find((a) => a.variant === variant) || allAds[adIndex % allAds.length];
          adIndex++;
          if (!matchingAd) continue;

          const el = document.createElement('div');
          blockEl.innerHTML = '';
          blockEl.appendChild(el);

          const root = createRoot(el);
          adRootsRef.current.push(root);
          root.render(<GalleryAdCard ad={matchingAd} />);
        }
      } catch {
        // Silent fail
      }
    };

    // Hydrate scheduling poll blocks
    const hydratePollBlocks = () => {
      const pollBlocks = contentRef.current?.querySelectorAll('.scheduling-poll-block');
      if (!pollBlocks) return;

      pollRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount poll root:', err); }
      });
      pollRootsRef.current = [];

      pollBlocks.forEach((blockEl) => {
        const pollSlug = blockEl.getAttribute('data-poll-slug');
        if (!pollSlug) return;

        const showComments = blockEl.getAttribute('data-show-comments') !== 'false';
        const title = blockEl.getAttribute('data-title') || undefined;

        const container = document.createElement('div');
        blockEl.innerHTML = '';
        blockEl.appendChild(container);

        try {
          const root = createRoot(container);
          pollRootsRef.current.push(root);
          root.render(<SchedulingPollWidget pollSlug={pollSlug} showComments={showComments} title={title} />);
        } catch (err) {
          console.error('Failed to render scheduling poll widget:', err);
        }
      });
    };

    // Hydrate after DOM is ready
    setTimeout(hydrateVideoBlocks, 100);
    setTimeout(hydrateVideoCards, 200);
    setTimeout(hydratePaymentBlocks, 150);
    setTimeout(hydrateCampaignFormBlocks, 175);
    setTimeout(hydrateAdBlocks, 200);
    setTimeout(hydratePollBlocks, 180);

    // Cleanup on unmount
    return () => {
      videoRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount video root on cleanup:', err); }
      });
      videoRootsRef.current = [];

      paymentRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount payment root on cleanup:', err); }
      });
      paymentRootsRef.current = [];

      campaignFormRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount campaign form root on cleanup:', err); }
      });
      campaignFormRootsRef.current = [];

      adRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount ad root on cleanup:', err); }
      });
      adRootsRef.current = [];

      pollRootsRef.current.forEach((root) => {
        try { root.unmount(); } catch (err) { console.error('Failed to unmount poll root on cleanup:', err); }
      });
      pollRootsRef.current = [];
    };
  }, [page]);

  if (loading) {
    return (
      <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#0d1b2a' }}>
        <Spin size="large" />
      </div>
    );
  }

  if (notFound || !page) {
    return (
      <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#0d1b2a' }}>
        <Result
          status="404"
          title="Page Not Found"
          subTitle="The page you're looking for doesn't exist or hasn't been published yet."
          style={{ color: '#fff' }}
        />
      </div>
    );
  }

  // HTML/CSS is admin-authored via GrapesJS, but we still DOMPurify-sanitize as
  // defense-in-depth (2026-04-12): compromised admin accounts / stored XSS via
  // embeddable widgets would otherwise reach every public visitor.
  return (
    <>
      {page.cssOutput && (
        <style dangerouslySetInnerHTML={{ __html: sanitizeLandingCss(page.cssOutput) }} />
      )}
      <div
        ref={contentRef}
        dangerouslySetInnerHTML={{ __html: sanitizeLandingHtml(page.htmlOutput || '') }}
      />
    </>
  );
}
