import {
  AlertCircle,
  BarChart2,
  CheckCircle2,
  ChevronDown,
  ChevronRight,
  Save,
  ThumbsDown,
  ThumbsUp,
} from 'lucide-react';
import { toast } from 'sonner';

import { lazy, Suspense, useEffect, useRef, useState } from 'react';

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

import PublishDraftModal from '@/Components/Ai/PublishDraftModal';
import { EditorToolbar } from '@/Components/ContentEditor/EditorToolbar';
import type { QualityMetrics } from '@/Components/ContentEditor/QualityScoreSidebar';
const ContentScoreSidebar = lazy(
  () => import('@/Components/ContentEditor/ContentScoreSidebar'),
);
const EeatScorePanel = lazy(() => import('@/Components/ContentEditor/EeatScorePanel'));
const GeoScorePanel = lazy(() => import('@/Components/ContentEditor/GeoScorePanel'));
const QualityScoreSidebar = lazy(
  () => import('@/Components/ContentEditor/QualityScoreSidebar'),
);
const SerpCompetitorPanel = lazy(
  () => import('@/Components/ContentEditor/SerpCompetitorPanel'),
);
import TipTapEditor, { TipTapEditorHandle } from '@/Components/ContentEditor/TipTapEditor';
import SiteNav from '@/Components/Navigation/SiteNav';
import { Alert, AlertDescription } from '@/Components/ui/alert';
import { Badge } from '@/Components/ui/badge';
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from '@/Components/ui/breadcrumb';
import { Button } from '@/Components/ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/Components/ui/collapsible';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/Components/ui/sheet';
import { Skeleton } from '@/Components/ui/skeleton';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs';
import { useAutoSave } from '@/hooks/useAutoSave';
import { useContentScore } from '@/hooks/useContentScore';
import type { TermStatus } from '@/hooks/useContentScore';
import { useQualityScore } from '@/hooks/useQualityScore';
import { useSerpAnalysis } from '@/hooks/useSerpAnalysis';
import { useUnsavedChanges } from '@/hooks/useUnsavedChanges';
import DashboardLayout from '@/Layouts/DashboardLayout';
import { trackProductEvent } from '@/lib/analytics';
import {
  CONTENT_EDITOR_OPENED,
  EDITOR_SESSION_END,
  EDITOR_SESSION_START,
} from '@/lib/event-catalog';
import { sanitizeHtml } from '@/lib/sanitize';
import { cn } from '@/lib/utils';
import type { PageProps, SiteBasic } from '@/types';

interface Draft {
  id: number;
  content: string;
  edited_content: string | null;
  token_usage: { prompt_tokens: number; completion_tokens: number } | null;
  created_at: string;
  ai_job: {
    id: number;
    model: string;
  };
  quality_rating?: number | null;
  recommendation: {
    id: number;
    page_url: string;
    title: string;
    action_type: string;
    wp_post_content: string | null;
    wp_post_id?: string;
    wp_modified_at?: string | null;
  } | null;
}

interface SerpSnapshot {
  keyword: string;
  target_url: string;
  results: Array<{
    position: number;
    domain: string;
    title: string;
    description: string;
    url: string;
    word_count: number;
    heading_structure: { h1: number; h2: number; h3: number; h4: number; h5: number; h6: number };
  }>;
  analysis: {
    avg_word_count: number;
    word_count_range: { min: number; max: number };
    common_h2_terms: string[];
    top_terms: Array<{ term: string; frequency: number }>;
  };
}

interface Props {
  site: SiteBasic;
  draft: Draft;
  serpSnapshot?: SerpSnapshot | null;
}

interface SidebarTabsProps {
  has_serp_key: boolean;
  showCompetitorsTab: boolean;
  contentScore: {
    overall_score: number;
    term_coverage: { score: number; covered: number; total: number; percentage: number };
    word_count_score: {
      score: number;
      draft_count: number;
      competitor_avg: number;
      competitor_median: number;
    };
    structure_score: { score: number; details: Record<string, unknown> };
    readability_score: { score: number; details: Record<string, unknown> };
  } | null;
  serpData: { analysis?: { word_count_range: { min: number; max: number } } | null } | null;
  contentTerms: TermStatus[];
  isLoadingScore: boolean;
  isAnalyzing: boolean;
  analysisStatus: 'idle' | 'pending' | 'processing' | 'completed' | 'failed';
  analysisError: string | null;
  scoreError: string | null;
  analyzeSerpKeyword: (keyword: string, languageCode?: string, targetUrl?: string) => void;
  cancelSerpAnalysis: () => void;
  metrics: QualityMetrics | null;
  isLoadingMetrics: boolean;
  serpSnapshot?: SerpSnapshot | null;
}

function SidebarTabs({
  has_serp_key,
  showCompetitorsTab,
  contentScore,
  serpData,
  contentTerms,
  isLoadingScore,
  isAnalyzing,
  analysisStatus,
  analysisError,
  scoreError,
  analyzeSerpKeyword,
  cancelSerpAnalysis,
  metrics,
  isLoadingMetrics,
  serpSnapshot,
}: SidebarTabsProps) {
  return (
    <Tabs defaultValue="score">
      <TabsList className="w-full mb-4">
        <TabsTrigger value="score" className="flex-1 text-xs whitespace-nowrap">
          Score
        </TabsTrigger>
        <TabsTrigger value="quality" className="flex-1 text-xs whitespace-nowrap">
          Quality
        </TabsTrigger>
        {showCompetitorsTab && (
          <TabsTrigger value="competitors" className="flex-1 text-xs whitespace-nowrap">
            Competitors
          </TabsTrigger>
        )}
      </TabsList>

      <TabsContent value="score">
        <p className="text-xs text-muted-foreground mb-3">
          Enter a target keyword to see how well your content covers key terms.
        </p>
        <Suspense fallback={<div className="p-4 space-y-3"><Skeleton className="h-6 w-3/4" /><Skeleton className="h-32 w-full" /><Skeleton className="h-4 w-1/2" /><Skeleton className="h-4 w-2/3" /></div>}>
          <ContentScoreSidebar
            overallScore={contentScore?.overall_score ?? null}
            termCoverage={contentScore?.term_coverage ?? null}
            wordCountScore={contentScore?.word_count_score ?? null}
            wordCountRange={serpData?.analysis?.word_count_range ?? null}
            structureScore={contentScore?.structure_score ?? null}
            readabilityScore={contentScore?.readability_score ?? null}
            terms={contentTerms}
            isLoading={isLoadingScore}
            isAnalyzing={isAnalyzing}
            hasSerpKey={has_serp_key}
            analysisStatus={analysisStatus}
            analysisError={analysisError}
            scoreError={scoreError}
            onAnalyze={analyzeSerpKeyword}
            onCancel={cancelSerpAnalysis}
          />
        </Suspense>
      </TabsContent>

      <TabsContent value="quality" className="space-y-4">
        <p className="text-xs text-muted-foreground mb-1">
          Readability metrics, E-E-A-T signals, and GEO optimization scores.
        </p>
        <Suspense fallback={<div className="p-4 space-y-3"><Skeleton className="h-6 w-3/4" /><Skeleton className="h-32 w-full" /><Skeleton className="h-4 w-1/2" /><Skeleton className="h-4 w-2/3" /></div>}>
          <QualityScoreSidebar metrics={metrics} isLoading={isLoadingMetrics} />
        </Suspense>
        <div className="rounded-lg border border-dashed bg-card/50 p-4">
          <Suspense fallback={<div className="p-4 space-y-2"><Skeleton className="h-5 w-2/3" /><Skeleton className="h-16 w-full" /></div>}>
            <EeatScorePanel
              overallScore={metrics?.eeat_overall_score}
              experience={metrics?.eeat_experience}
              expertise={metrics?.eeat_expertise}
              authoritativeness={metrics?.eeat_authoritativeness}
              trustworthiness={metrics?.eeat_trustworthiness}
              isLoading={isLoadingMetrics}
            />
          </Suspense>
        </div>
        <div className="rounded-lg border border-dashed bg-card/50 p-4">
          <Suspense fallback={<div className="p-4 space-y-2"><Skeleton className="h-5 w-2/3" /><Skeleton className="h-16 w-full" /></div>}>
            <GeoScorePanel
              overallScore={metrics?.geo_overall_score}
              directAnswers={metrics?.geo_direct_answers}
              faqStructure={metrics?.geo_faq_structure}
              structuredData={metrics?.geo_structured_data}
              conceptClarity={metrics?.geo_concept_clarity}
              citationReadiness={metrics?.geo_citation_readiness}
              schemaOpportunities={metrics?.geo_schema_opportunities}
              isLoading={isLoadingMetrics}
            />
          </Suspense>
        </div>
      </TabsContent>

      {showCompetitorsTab && (
        <TabsContent value="competitors">
          {serpSnapshot ? (
            <Suspense fallback={<div className="p-4 space-y-3"><Skeleton className="h-6 w-3/4" /><Skeleton className="h-32 w-full" /><Skeleton className="h-4 w-1/2" /><Skeleton className="h-4 w-2/3" /></div>}>
              <SerpCompetitorPanel
                serpSnapshot={serpSnapshot}
                keyword={serpSnapshot.keyword}
                targetUrl={serpSnapshot.target_url}
              />
            </Suspense>
          ) : (
            <div className="rounded-lg border border-dashed bg-muted/30 p-5 text-center space-y-3">
              <p className="text-sm font-medium text-foreground">Enable SERP Analysis</p>
              <p className="text-xs text-muted-foreground">
                Add your DataForSEO API key to score your content against top-ranking competitors
                and get semantic keyword suggestions.
              </p>
              <Button size="sm" variant="outline" asChild>
                <Link href={route('settings.serp')} className="inline-flex items-center gap-1.5">
                  Set Up Now
                  <ChevronRight className="h-3.5 w-3.5" aria-hidden="true" />
                </Link>
              </Button>
            </div>
          )}
        </TabsContent>
      )}
    </Tabs>
  );
}

export default function ContentEditorEdit({ site, draft, serpSnapshot }: Props) {
  const { has_serp_key } = usePage<PageProps>().props;
  const editorRef = useRef<TipTapEditorHandle>(null);
  const [editorContent, setEditorContent] = useState(draft.edited_content ?? draft.content);
  const [isPublishModalOpen, setIsPublishModalOpen] = useState(false);
  const [viewOriginalOpen, setViewOriginalOpen] = useState(false);
  const [sidebarSheetOpen, setSidebarSheetOpen] = useState(false);
  const [draftRating, setDraftRating] = useState<number | null>(draft.quality_rating ?? null);
  const [isSubmittingRating, setIsSubmittingRating] = useState(false);

  const submitDraftRating = (value: 1 | -1) => {
    setDraftRating(value);
    setIsSubmittingRating(true);
    router.post(
      route('ai-drafts.rate', [site.id, draft.id]),
      { quality_rating: value },
      {
        preserveState: true,
        preserveScroll: true,
        onFinish: () => setIsSubmittingRating(false),
      },
    );
  };

  // Show competitors tab when SERP key is configured or a snapshot already exists
  const showCompetitorsTab = has_serp_key || !!serpSnapshot;

  // Get the editor instance for the toolbar
  const editorInstance = editorRef.current?.getEditor() ?? null;

  // Auto-save hook
  const {
    isSaving,
    hasUnsavedChanges,
    lastSavedAt,
    error: saveError,
    saveNow,
  } = useAutoSave({
    content: editorContent,
    siteId: site.id,
    draftId: draft.id,
    enabled: true,
    intervalMs: 30000, // 30 seconds
  });

  // Warn user before navigating away with unsaved changes
  useUnsavedChanges(hasUnsavedChanges);

  // Quality score hook
  const {
    metrics,
    isLoading: isLoadingMetrics,
    error: metricsError,
  } = useQualityScore({
    content: editorContent,
    siteUrl: site.domain,
    siteId: site.id,
    enabled: true,
    debounceMs: 500,
  });

  // SERP analysis hook
  const {
    analyze: analyzeSerpKeyword,
    cancel: cancelSerpAnalysis,
    serpSnapshotId,
    status: analysisStatus,
    error: analysisError,
    isAnalyzing,
    serpData,
  } = useSerpAnalysis({ siteId: site.id });

  // Content score hook
  const {
    score: contentScore,
    isLoading: isLoadingScore,
    error: scoreError,
    terms: contentTerms,
  } = useContentScore({
    content: editorContent,
    siteId: site.id,
    siteUrl: site.domain,
    serpSnapshotId,
    nlpTerms: serpData?.nlp_terms ?? null,
    debounceMs: 2000,
  });

  // Track editor session start/end and score changes
  const sessionIdRef = useRef(crypto.randomUUID());
  const sessionStartRef = useRef(Date.now());
  const initialScoreRef = useRef<number | null>(null);
  const lastScoreBandRef = useRef<number | null>(null);
  // Refs for live values captured in the session-end event (avoid stale closures)
  const currentScoreRef = useRef<number>(0);
  const publishedRef = useRef(false);
  const serpTriggeredRef = useRef(false);
  const sessionEndFiredRef = useRef(false);

  // Keep currentScoreRef in sync with the latest content score
  useEffect(() => {
    if (contentScore?.overall_score != null) {
      currentScoreRef.current = contentScore.overall_score;
    }
  }, [contentScore?.overall_score]);

  // Track when SERP analysis is triggered in this session
  useEffect(() => {
    if (isAnalyzing) {
      serpTriggeredRef.current = true;
    }
  }, [isAnalyzing]);

  // Fire CONTENT_EDITOR_OPENED exactly once on mount, independent of session tracking
  useEffect(() => {
    trackProductEvent(CONTENT_EDITOR_OPENED, {
      site_id: String(site.id),
      draft_id: draft.id,
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    trackProductEvent(EDITOR_SESSION_START, {
      session_id: sessionIdRef.current,
      site_id: String(site.id),
      draft_id: draft.id,
    });

    const fireSessionEnd = () => {
      if (sessionEndFiredRef.current) return;
      sessionEndFiredRef.current = true;
      const duration_ms = Date.now() - sessionStartRef.current;
      trackProductEvent(EDITOR_SESSION_END, {
        session_id: sessionIdRef.current,
        draft_id: draft.id,
        duration_ms,
        final_score: currentScoreRef.current,
        published: publishedRef.current,
        serp_analysis_triggered: serpTriggeredRef.current,
      });
    };

    const handleVisibilityChange = () => {
      if (document.visibilityState === 'hidden') {
        fireSessionEnd();
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);

    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
      fireSessionEnd();
    };
    // intentional: session-start tracking uses refs for live values; adding deps would re-register the effect
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Track 10-point score band changes
  useEffect(() => {
    if (contentScore?.overall_score == null) return;
    const currentBand = Math.floor(contentScore.overall_score / 10) * 10;

    if (initialScoreRef.current === null) {
      initialScoreRef.current = contentScore.overall_score;
      lastScoreBandRef.current = currentBand;
      return;
    }

    if (lastScoreBandRef.current !== null && currentBand !== lastScoreBandRef.current) {
      trackProductEvent('editor_score_changed', {
        site_id: String(site.id),
        draft_id: draft.id,
        previous_score_band: lastScoreBandRef.current,
        new_score_band: currentBand,
      });
      lastScoreBandRef.current = currentBand;
    }
  }, [contentScore?.overall_score, site.id, draft.id]);

  // Toast on SERP analysis completion
  useEffect(() => {
    if (analysisStatus === 'completed' && serpData) {
      const termCount = serpData.nlp_terms?.length ?? 0;
      toast.success(`Analysis complete. Found ${termCount} semantic terms.`);
    }
  }, [analysisStatus, serpData]);

  const originalContent = draft.recommendation?.wp_post_content ?? '';
  const canPublish = draft.recommendation?.wp_post_id;
  const isEdited = draft.edited_content && draft.edited_content !== draft.content;

  const handleEditorChange = (html: string) => {
    setEditorContent(html);
  };

  const formatLastSaved = (date: Date | null) => {
    if (!date) return null;
    const now = new Date();
    const diffSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);

    if (diffSeconds < 60) return 'just now';
    if (diffSeconds < 120) return '1 minute ago';
    if (diffSeconds < 3600) return `${Math.floor(diffSeconds / 60)} minutes ago`;
    if (diffSeconds < 7200) return '1 hour ago';
    return `${Math.floor(diffSeconds / 3600)} hours ago`;
  };

  return (
    <>
      <Head title={`${site.name} - Edit Draft`} />

      <div className="container py-6">
        <SiteNav
          siteId={site.id}
          canAnalyze
          canRecommend
          canCannibalization
          canOpportunityMap
          canGeographic
          canDevice
        />

        {/* Breadcrumb Navigation */}
        <nav className="mb-4" aria-label="Breadcrumb">
          <Breadcrumb>
            <BreadcrumbList>
              <BreadcrumbItem>
                <BreadcrumbLink asChild>
                  <Link href={route('dashboard')}>Dashboard</Link>
                </BreadcrumbLink>
              </BreadcrumbItem>
              <BreadcrumbSeparator />
              {draft.recommendation ? (
                <>
                  <BreadcrumbItem>
                    <BreadcrumbLink asChild>
                      <Link href={route('recommendations.index', site.id)}>Recommendations</Link>
                    </BreadcrumbLink>
                  </BreadcrumbItem>
                  <BreadcrumbSeparator />
                  <BreadcrumbItem>
                    <BreadcrumbPage>Edit Draft</BreadcrumbPage>
                  </BreadcrumbItem>
                </>
              ) : (
                <>
                  <BreadcrumbItem>
                    <BreadcrumbLink asChild>
                      <Link href={route('ai-drafts.show', [site.id, draft.id])}>Drafts</Link>
                    </BreadcrumbLink>
                  </BreadcrumbItem>
                  <BreadcrumbSeparator />
                  <BreadcrumbItem>
                    <BreadcrumbPage>Edit</BreadcrumbPage>
                  </BreadcrumbItem>
                </>
              )}
            </BreadcrumbList>
          </Breadcrumb>
        </nav>

        {/* Header with navigation and actions */}
        <div className="flex items-center justify-between gap-3 mb-2">
          <div className="flex items-center gap-2">
            {draft.recommendation && (
              <Button variant="outline" size="sm" asChild>
                <Link href={route('recommendations.index', site.id)}>
                  &larr; Back to Recommendations
                </Link>
              </Button>
            )}
            <Button variant="ghost" size="sm" asChild>
              <Link href={route('ai-drafts.show', [site.id, draft.id])}>View Draft</Link>
            </Button>
          </div>

          <div className="flex items-center gap-2">
            {/* Save status indicator */}
            <div
              aria-live="polite"
              aria-atomic="true"
              className="flex items-center gap-2 text-sm text-muted-foreground transition-opacity duration-300 min-w-35 justify-end bg-muted rounded-full px-3 py-1"
            >
              {isSaving && (
                <>
                  <Save className="h-4 w-4 animate-spin text-primary" aria-hidden="true" />
                  <span>Saving...</span>
                </>
              )}
              {!isSaving && hasUnsavedChanges && (
                <>
                  <AlertCircle
                    className="h-4 w-4 text-amber-500 dark:text-amber-400"
                    aria-hidden="true"
                  />
                  <span className="text-amber-500 dark:text-amber-400">Unsaved changes</span>
                </>
              )}
              {!isSaving && !hasUnsavedChanges && lastSavedAt && (
                <>
                  <CheckCircle2
                    className="h-4 w-4 text-emerald-500 dark:text-emerald-400"
                    aria-hidden="true"
                  />
                  <span>Saved {formatLastSaved(lastSavedAt)}</span>
                </>
              )}
            </div>

            {/* Manual save button */}
            {hasUnsavedChanges && (
              <Button size="sm" variant="outline" onClick={saveNow} disabled={isSaving}>
                Save Now
              </Button>
            )}

            {/* Publish button */}
            {canPublish && (
              <Button size="sm" onClick={() => {
                publishedRef.current = true;
                trackProductEvent('draft_published', { draft_id: draft.id, site_id: String(site.id) });
                setIsPublishModalOpen(true);
              }}>
                Publish to WordPress
              </Button>
            )}
          </div>
        </div>

        {/* Title and meta */}
        <div className="mb-6">
          <div className="flex items-center gap-3 mb-1">
            <h1 className="text-2xl font-bold tracking-tight">
              {draft.recommendation?.title ?? `Edit Draft #${draft.id}`}
            </h1>
            {isEdited && <Badge variant="outline">Edited</Badge>}
          </div>
          {draft.recommendation && (
            <p className="text-sm text-muted-foreground">{draft.recommendation.page_url}</p>
          )}
        </div>

        {/* Error alerts */}
        {saveError && (
          <Alert variant="destructive" className="mb-6">
            <AlertDescription>
              <strong>Save Failed:</strong> {saveError}
            </AlertDescription>
          </Alert>
        )}

        {metricsError && (
          <Alert variant="destructive" className="mb-6">
            <AlertDescription>
              <strong>Quality Analysis Failed:</strong> {metricsError}
            </AlertDescription>
          </Alert>
        )}

        {/* Editor and sidebar layout */}
        <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
          {/* Editor section (2/3 width) */}
          <div className="lg:col-span-2 space-y-4">
            <div className="rounded-lg border bg-card p-4">
              <h2 className="text-lg font-semibold mb-4">Content Editor</h2>

              {/* View Original Collapsible */}
              {isEdited && (
                <Collapsible
                  open={viewOriginalOpen}
                  onOpenChange={setViewOriginalOpen}
                  className="mb-4 rounded-lg border border-border p-3 bg-muted/30"
                >
                  <CollapsibleTrigger asChild>
                    <button
                      type="button"
                      className="flex w-full items-center justify-between rounded py-1 hover:text-foreground transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                    >
                      <span className="text-sm font-medium">View Original</span>
                      <ChevronDown
                        className={cn(
                          'h-4 w-4 transition-transform duration-200',
                          viewOriginalOpen && 'rotate-180',
                        )}
                        aria-hidden="true"
                      />
                    </button>
                  </CollapsibleTrigger>
                  <CollapsibleContent className="pt-3 text-sm">
                    <div className="prose prose-sm max-w-none rounded bg-background p-3">
                      <div dangerouslySetInnerHTML={{ __html: sanitizeHtml(draft.content) }} />
                    </div>
                  </CollapsibleContent>
                </Collapsible>
              )}

              {/* Editor toolbar */}
              <EditorToolbar editor={editorInstance} className="mb-3" />

              {/* TipTap editor */}
              <TipTapEditor
                ref={editorRef}
                value={editorContent}
                onChange={handleEditorChange}
                placeholder="Start editing your content..."
                className="min-h-75 lg:min-h-125"
                highlightTerms={contentTerms.map((t) => t.term)}
              />

              {contentTerms.length > 0 && (
                <p className="text-xs text-muted-foreground flex items-center gap-1.5 -mt-1">
                  <span
                    className="inline-block w-3 h-3 rounded-sm bg-primary/20 border border-primary/30 shrink-0"
                    aria-hidden="true"
                  />
                  Highlighted terms are NLP keywords from your top competitors
                </p>
              )}

              <p className="mt-3 text-xs text-muted-foreground">
                Auto-saves every 30 seconds &bull;{' '}
                {draft.token_usage
                  ? `${draft.token_usage.prompt_tokens + draft.token_usage.completion_tokens} tokens`
                  : 'No token info'}{' '}
                &bull; {draft.ai_job.model}
              </p>

              {/* AI draft quality rating */}
              <div className="mt-4 pt-4 border-t flex items-center gap-3">
                <span className="text-xs text-muted-foreground">Rate this AI draft:</span>
                <Button
                  variant={draftRating === 1 ? 'default' : 'outline'}
                  size="sm"
                  onClick={() => draftRating !== 1 && submitDraftRating(1)}
                  disabled={isSubmittingRating}
                  aria-pressed={draftRating === 1}
                  aria-label="Thumbs up — good draft"
                  className="h-7 px-2 text-xs"
                >
                  <ThumbsUp className="h-3.5 w-3.5 mr-1" aria-hidden="true" />
                  Good
                </Button>
                <Button
                  variant={draftRating === -1 ? 'destructive' : 'outline'}
                  size="sm"
                  onClick={() => draftRating !== -1 && submitDraftRating(-1)}
                  disabled={isSubmittingRating}
                  aria-pressed={draftRating === -1}
                  aria-label="Thumbs down — needs improvement"
                  className="h-7 px-2 text-xs"
                >
                  <ThumbsDown className="h-3.5 w-3.5 mr-1" aria-hidden="true" />
                  Needs work
                </Button>
                {draftRating !== null && !isSubmittingRating && (
                  <span className="text-xs text-muted-foreground">Saved</span>
                )}
              </div>
            </div>
          </div>

          {/* Tabbed sidebar (1/3 width, desktop) */}
          <div className="lg:col-span-1 hidden lg:block">
            <div className="rounded-lg border bg-card p-4 lg:sticky lg:top-6">
              <SidebarTabs
                has_serp_key={has_serp_key}
                showCompetitorsTab={showCompetitorsTab}
                contentScore={contentScore}
                serpData={serpData}
                contentTerms={contentTerms}
                isLoadingScore={isLoadingScore}
                isAnalyzing={isAnalyzing}
                analysisStatus={analysisStatus}
                analysisError={analysisError}
                scoreError={scoreError}
                analyzeSerpKeyword={analyzeSerpKeyword}
                cancelSerpAnalysis={cancelSerpAnalysis}
                metrics={metrics}
                isLoadingMetrics={isLoadingMetrics}
                serpSnapshot={serpSnapshot}
              />
            </div>
          </div>
        </div>

        {/* Mobile FAB — opens scoring sidebar in a Sheet */}
        <button
          type="button"
          className="lg:hidden fixed bottom-6 right-6 z-40 flex h-14 w-14 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
          onClick={() => setSidebarSheetOpen(true)}
          aria-label="Open scoring sidebar"
        >
          <BarChart2 className="h-6 w-6" aria-hidden="true" />
        </button>

        {/* Mobile Sheet sidebar */}
        <Sheet open={sidebarSheetOpen} onOpenChange={setSidebarSheetOpen}>
          <SheetContent side="right" className="w-full sm:max-w-md overflow-y-auto">
            <SheetHeader className="mb-4">
              <SheetTitle>Content Analysis</SheetTitle>
            </SheetHeader>
            <SidebarTabs
              has_serp_key={has_serp_key}
              showCompetitorsTab={showCompetitorsTab}
              contentScore={contentScore}
              serpData={serpData}
              contentTerms={contentTerms}
              isLoadingScore={isLoadingScore}
              isAnalyzing={isAnalyzing}
              analysisStatus={analysisStatus}
              analysisError={analysisError}
              scoreError={scoreError}
              analyzeSerpKeyword={analyzeSerpKeyword}
              cancelSerpAnalysis={cancelSerpAnalysis}
              metrics={metrics}
              isLoadingMetrics={isLoadingMetrics}
              serpSnapshot={serpSnapshot}
            />
          </SheetContent>
        </Sheet>

        {/* Publish modal */}
        {canPublish && draft.recommendation && (
          <PublishDraftModal
            open={isPublishModalOpen}
            onOpenChange={setIsPublishModalOpen}
            siteId={site.id}
            draftId={draft.id}
            wpPostId={draft.recommendation.wp_post_id ?? ''}
            wpModifiedAt={draft.recommendation.wp_modified_at ?? null}
            originalContent={originalContent}
            newContent={editorContent}
            pageUrl={draft.recommendation.page_url}
          />
        )}
      </div>
    </>
  );
}

ContentEditorEdit.layout = (page: React.ReactElement) => <DashboardLayout>{page}</DashboardLayout>;
