import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { useState, useEffect } from '@wordpress/element';
import { TabPanel, Spinner } from '@wordpress/components';
import { cog, styles } from '@wordpress/icons';
import { useUniqueBlockClass } from '../../components/hooks/useUniqueBlockClass';
import { useDeviceSettings, generateBlockStyles } from '../../components/controls/blockStyles';
import { useVideoResolution } from './hooks/useVideoResolution';
import { buildEmbedSrc, EMBED_ALLOW } from './embedUtils';
import { SettingsPanel } from './components/SettingsPanel';
import { StylePanel } from './components/StylePanel';
import { sanitizeSvg } from '../../components/settings/iconUtils';
import './editor.scss';

const buildLinkRel = ( { openInNewTab, relNoFollow, relSponsored, relUgc } ) => [
  ...( openInNewTab ? [ 'noopener', 'noreferrer' ] : [] ),
  relNoFollow ? 'nofollow' : '',
  relSponsored ? 'sponsored' : '',
  relUgc ? 'ugc' : '',
].filter( Boolean ).join( ' ' );

const PLAY_OVERLAY_CSS_VARS = {
  playOverlayBackground:   '--axb-video-play-overlay-bg',
  playButtonBackground:    '--axb-video-play-button-bg',
  playButtonColor:         '--axb-video-play-button-color',
  playIconColor:           '--axb-video-play-icon-color',
  playButtonSize:          '--axb-video-play-button-size',
  playIconSize:            '--axb-video-play-icon-size',
  playButtonBorderRadius:  '--axb-video-play-button-radius',
  playOverlayZIndex:       '--axb-video-play-overlay-z-index',
  playButtonZIndex:        '--axb-video-play-button-z-index',
};

const buildPlayOverlayStyle = ( attributes ) =>
  Object.entries( PLAY_OVERLAY_CSS_VARS ).reduce( ( style, [ attrName, cssVar ] ) => {
    const value = attributes[ attrName ];

    if ( typeof value === 'string' && value.trim() ) {
      style[ cssVar ] = value.trim();
    }

    return style;
  }, {} );

const DEFAULT_PLAY_ICON = (
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
    <path d="M8 5v14l11-7z" />
  </svg>
);

// The shared style generator only handles the <figure> wrapper (and an <img>
// child for the image block). The Video block targets a <video> child, so we
// emit its responsive sizing/object-fit CSS here for the editor preview —
// mirroring axcelersblocks_video_generate_video_css() on the front end.
const VIDEO_CSS_PROPS = {
  videoObjectFit:      'object-fit',
  videoObjectPosition: 'object-position',
  videoWidth:          'width',
  videoHeight:         'height',
  videoMinWidth:       'min-width',
  videoMinHeight:      'min-height',
  videoMaxWidth:       'max-width',
  videoMaxHeight:      'max-height',
  videoBorderRadius:   'border-radius',
};

const buildVideoEditorCss = ( uniqueClass, devices, attributes ) => {
  if ( ! uniqueClass || ! devices ) return '';
  const selector = `.editor-styles-wrapper .${ uniqueClass } video, .editor-styles-wrapper .${ uniqueClass } iframe`;
  const overlaySelector = `.editor-styles-wrapper .${ uniqueClass } .axcelersblocks-video__play-overlay`;
  return Object.keys( devices ).map( ( device ) => {
    const decls = Object.entries( VIDEO_CSS_PROPS )
      .map( ( [ attr, prop ] ) => {
        const v = attributes[ attr ]?.[ device ] || '';
        return v ? `${ prop }: ${ v };` : '';
      } )
      .filter( Boolean )
      .join( ' ' );
    const overlayDecls = attributes.videoBorderRadius?.[ device ]
      ? `border-radius: ${ attributes.videoBorderRadius[ device ] };`
      : '';
    if ( ! decls && ! overlayDecls ) return '';
    const css = [
      decls ? `${ selector } { ${ decls } }` : '',
      overlayDecls ? `${ overlaySelector } { ${ overlayDecls } }` : '',
    ].filter( Boolean ).join( ' ' );
    return devices[ device ].media
      ? `${ devices[ device ].media } { ${ css } }`
      : css;
  } ).filter( Boolean ).join( '\n' );
};

export default function Edit( { attributes, setAttributes, clientId } ) {
  const {
    anchor, uniqueClass, openInNewTab,
    linkOption, customLink,
    linkTitle, ariaLabel,
    controls, autoplay, loop, muted,
    sourceMode, embedUrl, embedTitle, embedAspectRatio,
    customPlayOverlay, hideNativeControlsUntilPlay,
  } = attributes;

  const isEmbed = sourceMode === 'embed';

  const devices = useDeviceSettings();

  useUniqueBlockClass( { clientId, uniqueClass, setAttributes, blockName: 'axcelersblocks-video' } );

  const blockProps = useBlockProps( {
    id: anchor || undefined,
    className: [
      'axcelersblocks-video',
      uniqueClass,
      customPlayOverlay && ! autoplay ? 'axcelersblocks-video--has-play-overlay' : '',
    ].filter( Boolean ).join( ' ' ),
    style: customPlayOverlay ? buildPlayOverlayStyle( attributes ) : undefined,
  } );

  // ─── Video resolution ──────────────────────────────────────────────────────

  const {
    resolvedUrl, resolvedType, resolvedPoster, isResolving,
    postLink, termLink,
    isTermAcfDynamic, isTermMetaDynamic,
  } = useVideoResolution( attributes, setAttributes );

  // ─── Link resolution ───────────────────────────────────────────────────────

  const isTermLinked = ( isTermAcfDynamic || isTermMetaDynamic ) && linkOption === 'term' && termLink && termLink !== '#';

  const resolvedLinkHref = ( () => {
    if ( customLink ) return customLink;
    if ( linkOption === 'post' && postLink && postLink !== '#' ) return postLink;
    if ( isTermLinked ) return termLink;
    return null;
  } )();

  // Embeds are iframes from a third-party player; wrapping them in a link makes
  // no sense, so linking only applies to self-hosted video.
  const isLinked  = !! resolvedLinkHref && ! isEmbed;
  const linkClass = uniqueClass ? `${ uniqueClass }-link` : undefined;
  const target    = openInNewTab ? '_blank' : undefined;
  const rel       = buildLinkRel( attributes ) || undefined;

  // ─── Style tab state ───────────────────────────────────────────────────────

  const [ activeStyleTab, setActiveStyleTab ] = useState( 'main' );

  useEffect( () => {
    if ( ! isLinked && [ 'linked', 'linkedHover', 'linkedFocus', 'linkedActive' ].includes( activeStyleTab ) ) {
      setActiveStyleTab( 'main' );
    }
  }, [ isLinked, activeStyleTab ] );

  // ─── Embed element (editor preview) ────────────────────────────────────────

  const renderEmbed = () => {
    const ratioStyle = { aspectRatio: embedAspectRatio || '16 / 9' };

    if ( ! embedUrl ) {
      return (
        <div className="axcelersblocks-video__placeholder" style={ ratioStyle }>
          <div className="axcelersblocks-video__empty">
            <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
              <rect x="2" y="4" width="14" height="16" rx="2" />
              <path d="M16 9l6-3v12l-6-3" />
            </svg>
            <span>{ __( 'Paste a YouTube, Vimeo or Dailymotion link', 'axcelersblocks' ) }</span>
          </div>
        </div>
      );
    }

    // Editor preview never autoplays; keep mute/controls/loop faithful.
    const parsed = buildEmbedSrc( embedUrl, { autoplay: false, muted, loop, controls: controls !== false, playsInline: true } );

    if ( ! parsed ) {
      // Unrecognised platform — oEmbed resolves it on the front end.
      return (
        <div className="axcelersblocks-video__placeholder" style={ ratioStyle }>
          <div className="axcelersblocks-video__empty">
            <span>{ __( 'This platform is embedded automatically on the front end.', 'axcelersblocks' ) }</span>
            <code style={ { fontSize: '11px', wordBreak: 'break-all' } }>{ embedUrl }</code>
          </div>
        </div>
      );
    }

    return (
      <iframe
        className="axcelersblocks-video__embed"
        src={ parsed.src }
        title={ embedTitle || __( 'Embedded video', 'axcelersblocks' ) }
        style={ ratioStyle }
        allow={ EMBED_ALLOW }
        allowFullScreen
        frameBorder="0"
      />
    );
  };

  // ─── Video element (editor preview) ────────────────────────────────────────

  const renderVideo = () => {
    if ( isResolving ) {
      return (
        <div className="axcelersblocks-video__placeholder">
          <Spinner />
          <span>{ __( 'Loading video…', 'axcelersblocks' ) }</span>
        </div>
      );
    }
    if ( ! resolvedUrl ) {
      return (
        <div className="axcelersblocks-video__placeholder">
          <div className="axcelersblocks-video__empty">
            <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
              <rect x="2" y="4" width="14" height="16" rx="2" />
              <path d="M16 9l6-3v12l-6-3" />
            </svg>
            <span>{ __( 'No video selected', 'axcelersblocks' ) }</span>
          </div>
        </div>
      );
    }

    // Editor preview always shows native controls and is muted so editors can
    // scrub without sudden audio; autoplay is intentionally omitted here.
    const shouldHideNativeControls = !! customPlayOverlay && ! autoplay && !! hideNativeControlsUntilPlay && controls !== false;

    return (
      <video
        className="axcelersblocks-video__video"
        controls={ controls !== false && ! shouldHideNativeControls }
        loop={ !! loop }
        muted={ !! muted }
        poster={ resolvedPoster || undefined }
        preload="metadata"
      >
        <source src={ resolvedUrl } type={ resolvedType || undefined } />
      </video>
    );
  };

  const renderPlayIcon = () => {
    const rawSvg = attributes.playIconSvg || attributes.playCustomIcon || '';

    if ( rawSvg && rawSvg.includes( '<svg' ) ) {
      const safeSvg = sanitizeSvg( rawSvg );

      if ( safeSvg ) {
        return (
          <span
            className="axcelersblocks-video__play-icon"
            aria-hidden="true"
            dangerouslySetInnerHTML={ { __html: safeSvg } }
          />
        );
      }
    }

    return <span className="axcelersblocks-video__play-icon">{ DEFAULT_PLAY_ICON }</span>;
  };

  const renderPlayOverlay = () => {
    const preventPreviewPlay = ( event ) => {
      event.preventDefault();
      event.stopPropagation();
    };

    const label = attributes.playButtonLabel || __( 'Play video', 'axcelersblocks' );

    return (
      <>
        <span
          className="axcelersblocks-video__play-overlay"
          data-axb-video-play
          aria-hidden="true"
          onClick={ preventPreviewPlay }
        />
        <span
          className="axcelersblocks-video__play-button"
          role="button"
          tabIndex={ 0 }
          aria-label={ label }
          data-axb-video-play
          onClick={ preventPreviewPlay }
          onKeyDown={ ( event ) => {
            if ( event.key === 'Enter' || event.key === ' ' ) {
              preventPreviewPlay( event );
            }
          } }
        >
          { renderPlayIcon() }
        </span>
      </>
    );
  };

  // ─── Output ────────────────────────────────────────────────────────────────

  const showPlayOverlay = !! customPlayOverlay && ! autoplay && (
    isEmbed ? !! embedUrl : !! resolvedUrl && ! isResolving
  );

  const figureEl = (
    <figure { ...blockProps }>
      <span className="axcelersblocks-video__badge" aria-hidden="true">{ __( 'Video', 'axcelersblocks' ) }</span>
      { isEmbed ? renderEmbed() : renderVideo() }
      { showPlayOverlay && renderPlayOverlay() }
    </figure>
  );

  return (
    <>
      <InspectorControls>
        <TabPanel
          className="axcelersblocks-tabs"
          activeClass="is-active"
          tabs={ [
            { name: 'settings', title: <>{ cog }</>,    className: 'settings-tab' },
            { name: 'style',    title: <>{ styles }</>, className: 'style-tab' },
          ] }
        >
          { ( tab ) => (
            <>
              { tab.name === 'settings' && (
                <SettingsPanel attributes={ attributes } setAttributes={ setAttributes } />
              ) }
              { tab.name === 'style' && (
                <StylePanel
                  attributes={ attributes }
                  setAttributes={ setAttributes }
                  uniqueClass={ uniqueClass }
                  activeTab={ activeStyleTab }
                  setActiveTab={ setActiveStyleTab }
                  isLinked={ isLinked }
                />
              ) }
            </>
          ) }
        </TabPanel>
      </InspectorControls>

      <style>{ generateBlockStyles( uniqueClass, devices, attributes ) }</style>
      <style>{ buildVideoEditorCss( uniqueClass, devices, attributes ) }</style>

      { isLinked ? (
        <a
          className={ linkClass }
          href={ resolvedLinkHref }
          target={ target }
          rel={ rel }
          title={ linkTitle || undefined }
          aria-label={ ariaLabel || undefined }
          onClick={ ( e ) => e.preventDefault() }
          tabIndex={ -1 }
        >
          { figureEl }
        </a>
      ) : (
        figureEl
      ) }
    </>
  );
}
