import React, { useCallback, useState, useEffect, useRef } from 'react';
import { useEditor } from '@craftjs/core';
import { useEditorConfig } from '../../state/EditorConfigContext';
import { useWhpApi } from '../../hooks/useWhpApi';
import { usePages } from '../../state/PageContext';
import { useSiteDesign } from '../../state/SiteDesignContext';
import { useIsMobile } from '../../hooks/useIsMobile';
import { useMobileChrome } from '../../state/MobileChromeContext';
import { DeviceMode } from '../../types';
import { TemplateModal } from './TemplateModal';
import { HeadCodeModal } from './HeadCodeModal';
import { ReportIssueModal } from './ReportIssueModal';
import { TopBarOverflowMenu } from './TopBarOverflowMenu';
import { PublishWarnings } from './PublishWarnings';
import { SitesmithButton } from '../sitesmith/SitesmithButton';
import { useSitesmithModal } from '../../state/SitesmithContext';

interface TopBarProps {
  device: DeviceMode;
  onDeviceChange: (device: DeviceMode) => void;
  /** Item 10: canvas dashed guide outlines, default ON. */
  showGuides: boolean;
  onToggleGuides: () => void;
}

export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange, showGuides, onToggleGuides }) => {
  const { whpConfig, isWHP } = useEditorConfig();
  const { actions, query, canUndo, canRedo } = useEditor((_state, query) => ({
    canUndo: query.history.canUndo(),
    canRedo: query.history.canRedo(),
  }));
  const { save, publish, load } = useWhpApi();
  const { headerPage, footerPage, pages, activePageId } = usePages();
  const { design } = useSiteDesign();

  const [saveStatus, setSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle');
  const [publishStatus, setPublishStatus] = useState<'idle' | 'publishing' | 'published' | 'error'>('idle');
  const [publishWarnings, setPublishWarnings] = useState<string[]>([]);
  const [isDraft, setIsDraft] = useState(false);
  // Mobile-A2: lifted from private useState into MobileChromeContext so
  // opening a mobile sheet can close these modals (item 3) -- behavior is
  // otherwise identical for both the desktop and mobile branches below.
  const { templateModalOpen, setTemplateModalOpen, headCodeModalOpen, setHeadCodeModalOpen, overflowOpen, setOverflowOpen } = useMobileChrome();
  const [reportOpen, setReportOpen] = useState(false);
  const isMobile = useIsMobile();
  const { open: openSitesmith } = useSitesmithModal();
  const saveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const publishTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const hasLoadedRef = useRef(false);

  // Load saved state on mount
  useEffect(() => {
    if (!isWHP || hasLoadedRef.current) return;
    hasLoadedRef.current = true;

    load().catch((e) => {
      console.warn('Failed to load project from WHP API:', e);
    });
  }, [isWHP, load]);

  // Auto-save every 30 seconds
  useEffect(() => {
    if (!isWHP) return;

    const interval = setInterval(() => {
      save()
        .then((result) => {
          if (result?.success) {
            setSaveStatus('saved');
            setIsDraft(true);
            if (saveTimeoutRef.current) clearTimeout(saveTimeoutRef.current);
            saveTimeoutRef.current = setTimeout(() => setSaveStatus('idle'), 2000);
          }
        })
        .catch(() => {
          // Silent fail for auto-save
        });
    }, 30000);

    return () => clearInterval(interval);
  }, [isWHP, save]);

  const handleSave = useCallback(async () => {
    setSaveStatus('saving');
    try {
      const result = await save();
      if (result?.success) {
        setSaveStatus('saved');
        setIsDraft(true);
        if (saveTimeoutRef.current) clearTimeout(saveTimeoutRef.current);
        saveTimeoutRef.current = setTimeout(() => setSaveStatus('idle'), 2500);
      } else {
        setSaveStatus('error');
        if (saveTimeoutRef.current) clearTimeout(saveTimeoutRef.current);
        saveTimeoutRef.current = setTimeout(() => setSaveStatus('idle'), 3000);
      }
    } catch (e) {
      console.error('Save failed:', e);
      setSaveStatus('error');
      if (saveTimeoutRef.current) clearTimeout(saveTimeoutRef.current);
      saveTimeoutRef.current = setTimeout(() => setSaveStatus('idle'), 3000);
    }
  }, [save]);

  const handlePublish = useCallback(async () => {
    setPublishStatus('publishing');
    setPublishWarnings([]);
    try {
      const result = await publish();
      if (result?.success) {
        setPublishStatus('published');
        setIsDraft(false);
        // The site published; these are fixable problems, not failures. Held
        // independently of publishStatus so the 3s "Published" flash doesn't
        // take the warning down with it.
        setPublishWarnings(Array.isArray(result.warnings) ? result.warnings : []);
        if (publishTimeoutRef.current) clearTimeout(publishTimeoutRef.current);
        publishTimeoutRef.current = setTimeout(() => setPublishStatus('idle'), 3000);
      } else {
        setPublishStatus('error');
        if (publishTimeoutRef.current) clearTimeout(publishTimeoutRef.current);
        publishTimeoutRef.current = setTimeout(() => setPublishStatus('idle'), 3000);
      }
    } catch (e) {
      console.error('Publish failed:', e);
      setPublishStatus('error');
      if (publishTimeoutRef.current) clearTimeout(publishTimeoutRef.current);
      publishTimeoutRef.current = setTimeout(() => setPublishStatus('idle'), 3000);
    }
  }, [publish]);

  // Cleanup timeouts on unmount
  useEffect(() => {
    return () => {
      if (saveTimeoutRef.current) clearTimeout(saveTimeoutRef.current);
      if (publishTimeoutRef.current) clearTimeout(publishTimeoutRef.current);
    };
  }, []);

  // Extracted so both the desktop inline Preview button and the mobile
  // overflow-menu "Preview" item can trigger the exact same flow.
  const handlePreview = useCallback(() => {
    try {
      const serialized = query.serialize();
      import('../../utils/html-export').then(({ exportToHtml, exportBodyHtml, buildAnimationScript }) => {
        // Get header HTML
        let headerHtml = '';
        try {
          if (headerPage.craftState) {
            headerHtml = exportBodyHtml(headerPage.craftState).html;
          }
        } catch (e) { console.warn('Header export failed:', e); }

        // Get page body HTML
        const bodyResult = exportBodyHtml(serialized);
        const bodyHtml = bodyResult.html;

        // Get footer HTML
        let footerHtml = '';
        try {
          if (footerPage.craftState) {
            footerHtml = exportBodyHtml(footerPage.craftState).html;
          }
        } catch (e) { console.warn('Footer export failed:', e); }

        // Compose full page: header + body + footer. `handlePreview` below
        // replaces the ENTIRE wrapped-doc `<body>` inner (including the
        // in-body reveal `<script>` wrapInDocument already emitted) with
        // this composed string, so the script would otherwise be clobbered
        // and animated elements would stay hidden forever
        // ([data-animation]{opacity:0} with no IntersectionObserver to ever
        // add `.animated`). Re-append the reveal script here -- built from
        // the SAME composed content it will end up living alongside -- so
        // it survives the replacement below and fires exactly once.
        const composedBody =
          headerHtml + bodyHtml + footerHtml +
          buildAnimationScript(headerHtml + bodyHtml + footerHtml);

        // PKG-H: fold the active page's own SEO overrides + the site-wide
        // design tokens/favicon into the Preview export so editor Preview
        // === published output (contract §4/§7). `title` is the fully
        // resolved TITLE (seo.metaTitle || page.name) per the contract --
        // html-export's buildSeoMeta/og:title fallback both key off it.
        const activePage = pages.find((p) => p.id === activePageId);
        const seo = activePage?.seo;
        const title = seo?.metaTitle || activePage?.name || whpConfig?.siteName || 'Preview';

        const result = exportToHtml(serialized, {
          title,
          includeFonts: true,
          headCode: design.headCode,
          description: seo?.metaDescription,
          ogTitle: seo?.ogTitle,
          ogImage: seo?.ogImage,
          twitterCard: seo?.twitterCard,
          noindex: seo?.noindex,
          favicon: design.favicon,
          design,
        });

        // Replace the body in the full document with our composed version.
        // Use a function replacer -- a plain string replacer treats
        // `$&`/`$1`/`$$` sequences in user content as replacement
        // patterns, silently corrupting the output.
        let html = result.html;
        const bodyMatch = html.match(/<body[^>]*>([\s\S]*)<\/body>/i);
        if (bodyMatch) {
          html = html.replace(bodyMatch[1], () => composedBody);
        }

        // Make proxy URLs absolute so they work from the blob: context
        const origin = window.location.origin;
        html = html.replace(/src="\/api\//g, `src="${origin}/api/`);
        html = html.replace(/url\('\/api\//g, `url('${origin}/api/`);
        const blob = new Blob([html], { type: 'text/html' });
        const url = URL.createObjectURL(blob);
        window.open(url, '_blank');
      });
    } catch (e) {
      console.error('Preview failed:', e);
    }
  }, [query, headerPage, footerPage, whpConfig, design, pages, activePageId]);

  // Phase A: at ≤768px the topbar collapses to only the essentials --
  // back arrow, Undo/Redo, Save (+Publish) -- with Templates, Sitesmith,
  // Preview, Head Code, the guides toggle, and the device switcher moved
  // into the "⋯" overflow menu. This keeps desktop's JSX/behavior below
  // completely untouched.
  if (isMobile) {
    return (
      <nav className="topbar topbar-mobile">
        <PublishWarnings warnings={publishWarnings} onDismiss={() => setPublishWarnings([])} />
        <div className="topbar-left">
          {isWHP && (
            <a
              href={whpConfig!.backUrl}
              className="topbar-btn icon-only back-btn"
              aria-label="Back to Panel"
              data-tooltip="Back"
            >
              <i className="fa fa-arrow-left" />
            </a>
          )}
        </div>

        <div className="topbar-right">
          <button
            className="topbar-btn icon-only"
            onClick={() => actions.history.undo()}
            disabled={!canUndo}
            aria-label="Undo"
            data-tooltip="Undo"
          >
            <i className="fa fa-undo" />
          </button>
          <button
            className="topbar-btn icon-only"
            onClick={() => actions.history.redo()}
            disabled={!canRedo}
            aria-label="Redo"
            data-tooltip="Redo"
          >
            <i className="fa fa-repeat" />
          </button>
          <span className="topbar-divider" />
          <button
            className="topbar-btn icon-only primary"
            onClick={handleSave}
            disabled={saveStatus === 'saving'}
            aria-label="Save Draft"
            data-tooltip="Save"
          >
            <i className={`fa ${saveStatus === 'saving' ? 'fa-spinner fa-spin' : 'fa-save'}`} />
          </button>
          {isWHP && (
            <button
              className="topbar-btn icon-only publish"
              onClick={handlePublish}
              disabled={publishStatus === 'publishing' || saveStatus === 'saving'}
              aria-label="Publish to live site"
              data-tooltip="Publish"
            >
              <i className={`fa ${publishStatus === 'publishing' ? 'fa-spinner fa-spin' : 'fa-globe'}`} />
            </button>
          )}
          <button
            type="button"
            className={`topbar-btn icon-only overflow-toggle${overflowOpen ? ' active' : ''}`}
            onClick={() => setOverflowOpen(!overflowOpen)}
            aria-label="More options"
            aria-expanded={overflowOpen}
            aria-haspopup="menu"
            data-tooltip="More"
          >
            <i className="fa fa-ellipsis-h" />
          </button>
        </div>

        <TopBarOverflowMenu
          open={overflowOpen}
          onClose={() => setOverflowOpen(false)}
          device={device}
          onDeviceChange={onDeviceChange}
          showGuides={showGuides}
          onToggleGuides={onToggleGuides}
          onOpenTemplates={() => setTemplateModalOpen(true)}
          onOpenHeadCode={() => setHeadCodeModalOpen(true)}
          onOpenReportIssue={() => setReportOpen(true)}
          onPreview={handlePreview}
          sitesmithNode={<SitesmithButton onClick={() => openSitesmith()} />}
        />

        <TemplateModal open={templateModalOpen} onClose={() => setTemplateModalOpen(false)} />
        <HeadCodeModal open={headCodeModalOpen} onClose={() => setHeadCodeModalOpen(false)} />
        <ReportIssueModal open={reportOpen} onClose={() => setReportOpen(false)} device={device} />
      </nav>
    );
  }

  return (
    <nav className="topbar">
      <PublishWarnings warnings={publishWarnings} onDismiss={() => setPublishWarnings([])} />
      <div className="topbar-left">
        {isWHP && (
          <a href={whpConfig!.backUrl} className="topbar-btn back-btn" aria-label="Back to Panel">
            <i className="fa fa-arrow-left" /> Back to Panel
          </a>
        )}
        <span className="topbar-title">Site Builder</span>
        {isWHP && (
          <span className="topbar-domain">{whpConfig!.siteDomain}</span>
        )}
      </div>

      <div className="topbar-center">
        <div className="device-switcher">
          {(['desktop', 'tablet', 'mobile'] as DeviceMode[]).map((d) => (
            <button
              key={d}
              className={`device-btn ${device === d ? 'active' : ''}`}
              onClick={() => onDeviceChange(d)}
              title={d.charAt(0).toUpperCase() + d.slice(1)}
              aria-label={d.charAt(0).toUpperCase() + d.slice(1)}
              aria-pressed={device === d}
            >
              <i className={`fa ${d === 'desktop' ? 'fa-desktop' : d === 'tablet' ? 'fa-tablet' : 'fa-mobile'}`} />
            </button>
          ))}
        </div>
        <button
          type="button"
          className={`topbar-btn guides-toggle icon-only${showGuides ? ' active' : ''}`}
          onClick={onToggleGuides}
          aria-pressed={showGuides}
          aria-label={showGuides ? 'Hide canvas guides' : 'Show canvas guides'}
          data-tooltip={showGuides ? 'Hide guides' : 'Show guides'}
        >
          <i className={`fa ${showGuides ? 'fa-th' : 'fa-th-large'}`} aria-hidden />
        </button>
      </div>

      <div className="topbar-right">
        <button className="topbar-btn" onClick={() => actions.history.undo()} disabled={!canUndo} title="Undo" aria-label="Undo">
          <i className="fa fa-undo" />
        </button>
        <button className="topbar-btn" onClick={() => actions.history.redo()} disabled={!canRedo} title="Redo" aria-label="Redo">
          <i className="fa fa-repeat" />
        </button>
        <span className="topbar-divider" />
        <button className="topbar-btn" title="Templates" aria-label="Templates" onClick={() => setTemplateModalOpen(true)}>
          <i className="fa fa-th-large" /> Templates
        </button>
        <button
          className="topbar-btn icon-only"
          aria-label="Custom Head Code"
          data-tooltip="Code"
          onClick={() => setHeadCodeModalOpen(true)}
        >
          <i className="fa fa-code" />
        </button>
        <button className="topbar-btn icon-only" aria-label="Preview" data-tooltip="Preview" onClick={handlePreview}>
          <i className="fa fa-eye" />
        </button>
        <button
          className="topbar-btn icon-only"
          aria-label="Report an issue"
          data-tooltip="Report an issue"
          title="Report an issue"
          onClick={() => setReportOpen(true)}
        >
          <i className="fa fa-bug" />
        </button>

        {/* Draft/Published status badge */}
        {isWHP && isDraft && publishStatus !== 'published' && (
          <span className="publish-badge draft">
            <i className="fa fa-pencil" /> Draft
          </span>
        )}
        {publishStatus === 'published' && (
          <span className="publish-badge published">
            <i className="fa fa-check-circle" /> Published
          </span>
        )}

        {/* Save status indicator */}
        {saveStatus === 'saved' && (
          <span className="save-indicator saved">
            <i className="fa fa-check" /> Saved!
          </span>
        )}
        {saveStatus === 'error' && (
          <span className="save-indicator error">
            <i className="fa fa-exclamation-triangle" /> Save Error
          </span>
        )}
        {publishStatus === 'error' && (
          <span className="save-indicator error">
            <i className="fa fa-exclamation-triangle" /> Publish Error
          </span>
        )}

        <SitesmithButton onClick={() => openSitesmith()} />

        <button
          className="topbar-btn primary"
          onClick={handleSave}
          disabled={saveStatus === 'saving'}
          title="Save Draft"
          aria-label="Save Draft"
        >
          {saveStatus === 'saving' ? (
            <><i className="fa fa-spinner fa-spin" /> Saving...</>
          ) : (
            <><i className="fa fa-save" /> Save</>
          )}
        </button>

        {isWHP && (
          <button
            className="topbar-btn publish"
            onClick={handlePublish}
            disabled={publishStatus === 'publishing' || saveStatus === 'saving'}
            title="Publish to live site"
            aria-label="Publish to live site"
          >
            {publishStatus === 'publishing' ? (
              <><i className="fa fa-spinner fa-spin" /> Publishing...</>
            ) : (
              <><i className="fa fa-globe" /> Publish</>
            )}
          </button>
        )}
      </div>
      <TemplateModal open={templateModalOpen} onClose={() => setTemplateModalOpen(false)} />
      <HeadCodeModal open={headCodeModalOpen} onClose={() => setHeadCodeModalOpen(false)} />
      <ReportIssueModal open={reportOpen} onClose={() => setReportOpen(false)} device={device} />
    </nav>
  );
};
