import { ArrowLeft, ArrowRight, Calendar, Clock, User } from 'lucide-react';

import { useMemo, useRef } from 'react';

import { Head, Link, usePage } from '@inertiajs/react';

import {
  BlogComponentInjector,
  type BlogComponentMount,
} from '@/Components/blog/BlogComponentInjector';
import { BlogProductCta } from '@/Components/marketing/BlogProductCta';
import { MarketingFooter } from '@/Components/marketing/MarketingFooter';
import { MarketingNav } from '@/Components/marketing/MarketingNav';
import { TableOfContents } from '@/Components/marketing/TableOfContents';
import { ShareButtons } from '@/Components/ShareButtons';
import { Button } from '@/Components/ui/button';
import { formatDateOnly } from '@/lib/format';
import { sanitizeHtml } from '@/lib/sanitize';
import { type PageProps } from '@/types';

interface BlogPost {
  id: number;
  title: string;
  slug: string;
  excerpt: string;
  content: string;
  author: string;
  published_at: string;
  updated_at: string;
  meta_title: string | null;
  meta_description: string | null;
  og_image: string | null;
  canonical_url: string | null;
  category: string | null;
  estimated_reading_time: number;
  keywords?: string[] | null;
  author_title: string | null;
  author_bio: string | null;
  author_url?: string | null;
  author_avatar?: string | null;
}

interface RelatedPost {
  id: number;
  title: string;
  slug: string;
  excerpt: string;
  author: string;
  published_at: string;
  category: string | null;
}

interface BlogShowProps {
  canLogin: boolean;
  canRegister: boolean;
  post: BlogPost;
  relatedPosts: RelatedPost[];
}

type BlogShowComponent = ((props: BlogShowProps) => JSX.Element) & {
  disableGlobalUi?: boolean;
};

const safeUrl = (u?: string | null): string | undefined =>
  u && /^https:\/\//.test(u) ? u : undefined;

const BlogShow: BlogShowComponent = ({ canLogin, canRegister, post, relatedPosts }) => {
  const appName = import.meta.env.VITE_APP_NAME || 'RankWiz';
  const { app_url } = usePage<PageProps>().props;
  const contentRef = useRef<HTMLDivElement>(null);
  const pageTitle = post.meta_title || post.title;
  const pageDescription = post.meta_description || post.excerpt;
  const ogImage = post.og_image || `/og/blog/${post.slug}.svg`;
  // Parse blog component mounts from raw HTML before sanitization.
  // Extracts structured {id, name, props} from data-component markers so that
  // BlogComponentInjector receives safe structured props instead of reading
  // data-* attributes from the DOM (which would require allowing them in the sanitizer).
  const componentMounts = useMemo<BlogComponentMount[]>(() => {
    const mounts: BlogComponentMount[] = [];
    const regex = /<[^>]+\s+data-component="([^"]+)"[^>]*(?:\s+data-props="([^"]*)")?[^>]*>/gi;
    let match;
    let idx = 0;
    while ((match = regex.exec(post.content)) !== null) {
      const name = match[1];
      let props: Record<string, unknown> = {};
      if (match[2]) {
        try {
          props = JSON.parse(match[2].replace(/&quot;/g, '"')) as Record<string, unknown>;
        } catch {
          // Invalid JSON — render component with no props
        }
      }
      mounts.push({ id: `blog-component-${idx}`, name, props });
      idx++;
    }
    return mounts;
  }, [post.content]);

  // Pre-processes raw content: replaces component markers and injects heading IDs.
  // Sanitization happens at render via sanitizeHtml() so the XSS guard sees a single call site.
  // Heading injection runs before sanitization because `id` is in ALLOWED_ATTR and survives DOMPurify.
  const preprocessedContent = useMemo(() => {
    // Replace data-component markers with id-based placeholders so BlogComponentInjector
    // can portal into them without requiring data-* attrs in the sanitizer allowlist.
    let raw = post.content;
    let idx = 0;
    raw = raw.replace(
      /<([a-z][a-z0-9]*)\b[^>]*\s+data-component="[^"]*"[^>]*>/gi,
      (_match, tag: string) => `<${tag} id="blog-component-${idx++}">`,
    );
    // Inject id attributes on h2/h3 headings so TableOfContents anchor links work.
    return raw.replace(/<(h[23])>(.*?)<\/\1>/gi, (_match, tag: string, text: string) => {
      const id = text
        .replace(/<[^>]*>/g, '')
        .toLowerCase()
        .replace(/[^\w\s-]/g, '')
        .replace(/\s+/g, '-')
        .replace(/-+/g, '-')
        .trim();
      return `<${tag} id="${id}">${text}</${tag}>`;
    });
  }, [post.content]);

  const formattedDate = new Date(post.published_at).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });

  const authorUrl = safeUrl(post.author_url);
  const authorAvatar = safeUrl(post.author_avatar);

  return (
    <>
      <Head title={pageTitle}>
        <link rel="canonical" href={post.canonical_url || `${app_url}/blog/${post.slug}`} />
        <link
          rel="alternate"
          type="application/rss+xml"
          title="RankWiz Blog RSS Feed"
          href="/blog/feed.xml"
        />
        <meta name="description" content={pageDescription} />
        <meta property="og:title" content={`${pageTitle} — ${appName}`} />
        <meta property="og:description" content={pageDescription} />
        <meta property="og:type" content="article" />
        <meta property="og:url" content={`${app_url}/blog/${post.slug}`} />
        <meta property="og:image" content={ogImage} />
        <meta property="og:image:alt" content={pageTitle} />
        <meta property="article:published_time" content={post.published_at} />
        <meta property="article:modified_time" content={post.updated_at || post.published_at} />
        <meta property="article:author" content={post.author} />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:site" content="@rankwiz_ai" />
        <meta name="twitter:title" content={`${pageTitle} — ${appName}`} />
        <meta name="twitter:description" content={pageDescription} />
        <meta name="twitter:image" content={ogImage} />
        <meta name="twitter:image:width" content="1200" />
        <meta name="twitter:image:height" content="630" />
        <meta property="og:image:width" content="1200" />
        <meta property="og:image:height" content="630" />
        <script type="application/ld+json">
          {JSON.stringify({
            '@context': 'https://schema.org',
            '@type': 'BlogPosting',
            headline: post.title,
            description: post.excerpt,
            image: {
              '@type': 'ImageObject',
              url: ogImage.startsWith('http') ? ogImage : `${app_url}${ogImage}`,
              width: 1200,
              height: 630,
            },
            wordCount: post.content
              .replace(/<[^>]*>/g, '')
              .split(/\s+/)
              .filter(Boolean).length,
            author: {
              '@type': 'Person',
              name: post.author,
              ...(authorUrl ? { url: authorUrl } : {}),
              ...(authorAvatar
                ? {
                    image: {
                      '@type': 'ImageObject',
                      url: authorAvatar,
                    },
                  }
                : {}),
            },
            datePublished: post.published_at,
            dateModified: post.updated_at || post.published_at,
            publisher: {
              '@type': 'Organization',
              name: appName,
              logo: {
                '@type': 'ImageObject',
                url: `${app_url}/logo.svg`,
              },
            },
            mainEntityOfPage: {
              '@type': 'WebPage',
              '@id': `${app_url}/blog/${post.slug}`,
            },
            ...(post.keywords && post.keywords.length > 0
              ? { keywords: post.keywords.join(', ') }
              : {}),
          })}
        </script>
        <script type="application/ld+json">
          {JSON.stringify({
            '@context': 'https://schema.org',
            '@type': 'BreadcrumbList',
            itemListElement: [
              {
                '@type': 'ListItem',
                position: 1,
                name: 'Home',
                item: `${app_url}/`,
              },
              {
                '@type': 'ListItem',
                position: 2,
                name: 'Blog',
                item: `${app_url}/blog`,
              },
              {
                '@type': 'ListItem',
                position: 3,
                name: post.title,
                item: `${app_url}/blog/${post.slug}`,
              },
            ],
          })}
        </script>
      </Head>

      <div className="min-h-screen bg-linear-to-b from-background to-muted/30">
        <MarketingNav canLogin={canLogin} canRegister={canRegister} />

        <main id="main-content">
          {/* Back to Blog */}
          <section className="container py-8">
            <Button variant="ghost" asChild>
              <Link href={route('blog.index')}>
                <ArrowLeft className="mr-2 h-4 w-4" aria-hidden="true" />
                Back to Blog
              </Link>
            </Button>
          </section>

          {/* Article Header */}
          <article className="container pb-24" itemScope itemType="https://schema.org/BlogPosting">
            <header className="mx-auto mb-12 max-w-3xl">
              <h1
                className="animate-fade-in-up mb-6 text-4xl font-bold tracking-tight sm:text-5xl"
                itemProp="headline"
              >
                {post.title}
              </h1>
              <div className="animate-fade-in-up animate-delay-100 flex flex-wrap items-center gap-6 text-muted-foreground">
                <div className="flex items-center gap-2">
                  <User className="h-4 w-4" aria-hidden="true" />
                  <span itemProp="author">{post.author}</span>
                </div>
                <div className="flex items-center gap-2">
                  <Calendar className="h-4 w-4" aria-hidden="true" />
                  <time dateTime={post.published_at} itemProp="datePublished">
                    {formattedDate}
                  </time>
                </div>
                <div className="flex items-center gap-2">
                  <Clock className="h-4 w-4" aria-hidden="true" />
                  <span>{post.estimated_reading_time} min read</span>
                </div>
              </div>
              {post.keywords && post.keywords.length > 0 && (
                <div
                  className="animate-fade-in-up animate-delay-200 mt-4 flex flex-wrap gap-2"
                  aria-label="Topic tags"
                >
                  {post.keywords.map((keyword) => (
                    <span
                      key={keyword}
                      className="inline-flex items-center rounded-full border bg-muted px-3 py-0.5 text-xs font-medium text-muted-foreground"
                    >
                      {keyword}
                    </span>
                  ))}
                </div>
              )}
            </header>

            <TableOfContents html={preprocessedContent} />

            {/* Article Content */}
            <div className="mx-auto max-w-3xl">
              {post.excerpt && (
                <p className="article-bluf mx-auto mb-8 max-w-3xl border-l-4 bg-muted/40 px-5 py-4 text-base text-muted-foreground rounded-lg">
                  {post.excerpt}
                </p>
              )}
              <div
                ref={contentRef}
                className="animate-fade-in-up animate-delay-200 prose prose-neutral dark:prose-invert mx-auto max-w-none"
                itemProp="articleBody"
                dangerouslySetInnerHTML={{ __html: sanitizeHtml(preprocessedContent) }}
              />
              <BlogComponentInjector contentRef={contentRef} components={componentMounts} />

              {/* Share Buttons */}
              <div className="mt-10 border-t pt-6">
                <ShareButtons
                  url={`${app_url}/blog/${post.slug}`}
                  title={post.title}
                  description={post.excerpt}
                />
              </div>
            </div>
          </article>

          {/* Fix 5 (SEO-002): Contextual product CTA — category-mapped to relevant feature */}
          <section className="container pb-8">
            <div className="mx-auto max-w-3xl">
              <BlogProductCta category={post.category} blogSlug={post.slug} variant="bottom" />
            </div>
          </section>

          {/* Contextual Resource Links */}
          <section className="container pb-8" aria-label="Explore RankWiz">
            <div className="mx-auto max-w-3xl rounded-lg border bg-muted/30 p-6">
              <p className="mb-3 text-base font-semibold">Explore RankWiz</p>
              <ul className="flex flex-wrap gap-x-6 gap-y-2 text-sm">
                <li>
                  <Link
                    href={route('features')}
                    className="text-primary underline-offset-4 hover:underline"
                  >
                    See all RankWiz features
                  </Link>
                </li>
                <li>
                  <Link
                    href={route('comparison', { competitor: 'surfer-seo' })}
                    className="text-primary underline-offset-4 hover:underline"
                  >
                    RankWiz vs Surfer SEO
                  </Link>
                </li>
                <li>
                  <Link
                    href={route('comparison', { competitor: 'ahrefs' })}
                    className="text-primary underline-offset-4 hover:underline"
                  >
                    RankWiz vs Ahrefs
                  </Link>
                </li>
                <li>
                  <Link
                    href={route('comparison', { competitor: 'semrush' })}
                    className="text-primary underline-offset-4 hover:underline"
                  >
                    RankWiz vs Semrush
                  </Link>
                </li>
                <li>
                  <Link
                    href={route('pricing')}
                    className="text-primary underline-offset-4 hover:underline"
                  >
                    Pricing — free to start
                  </Link>
                </li>
              </ul>
            </div>
          </section>

          {/* Related Posts */}
          {relatedPosts.length > 0 && (
            <section className="container py-16">
              <h2 className="mb-8 text-2xl font-bold tracking-tight">Continue reading</h2>
              <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
                {relatedPosts.map((related) => (
                  <Link
                    key={related.id}
                    href={route('blog.show', related.slug)}
                    className="group rounded-xl border bg-card p-6 transition-shadow hover:shadow-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                  >
                    <h3 className="mb-2 text-lg font-semibold group-hover:text-primary transition-colors">
                      {related.title}
                    </h3>
                    <p className="mb-4 line-clamp-2 text-sm text-muted-foreground">
                      {related.excerpt}
                    </p>
                    <div className="flex items-center gap-4 text-xs text-muted-foreground">
                      <span>{related.author}</span>
                      <time dateTime={related.published_at}>
                        {formatDateOnly(related.published_at)}
                      </time>
                    </div>
                  </Link>
                ))}
              </div>
            </section>
          )}

          {/* CTA Section */}
          <section className="container py-24">
            <div className="rounded-2xl bg-linear-to-r from-primary/10 via-primary/5 to-background p-6 text-center sm:p-12">
              <h2 className="mb-4 text-2xl font-bold tracking-tight sm:text-3xl">
                Ready to Optimize Your WordPress Site?
              </h2>
              <p className="mb-8 text-base text-muted-foreground sm:text-lg">
                Connect your Google Search Console and start analyzing your traffic in minutes.
              </p>
              <div className="flex flex-wrap items-center justify-center gap-4">
                {canRegister && (
                  <Button size="lg" asChild>
                    <Link href={route('register')}>
                      Start Free Analysis
                      <ArrowRight className="ml-2 h-4 w-4" aria-hidden="true" />
                    </Link>
                  </Button>
                )}
                <Button size="lg" variant="outline" asChild>
                  <Link href={route('welcome')}>Learn More</Link>
                </Button>
              </div>
            </div>
          </section>
        </main>

        <MarketingFooter />
      </div>
    </>
  );
};

BlogShow.disableGlobalUi = true;

export default BlogShow;
