import {
  DownOutlined,
  ExpandOutlined,
  MutedOutlined,
  PauseCircleOutlined,
  PlayCircleOutlined,
  SoundOutlined,
} from "@ant-design/icons";
import { useEffect, useRef, useState, type ChangeEvent, type MouseEvent } from "react";
import type { CanvasOption } from "./canvasTypes";
import { getOptionLabel } from "./canvasUtils";
import { formatCanvasVideoTime } from "./canvasWorkflowDeserialize";

export function CanvasSelectChip({
  value,
  options,
  open,
  onToggle,
  onChange,
  ariaLabel,
  className,
  compact = false,
}: {
  value: string;
  options: CanvasOption[];
  open: boolean;
  onToggle: () => void;
  onChange: (value: string) => void;
  ariaLabel: string;
  className?: string;
  compact?: boolean;
}) {
  return (
    <div className={`canvas-select-chip${open ? " is-open" : ""}${compact ? " canvas-select-chip--compact" : ""}${className ? ` ${className}` : ""}`}>
      <button
        type="button"
        className="canvas-select-chip__trigger"
        aria-label={ariaLabel}
        aria-haspopup="listbox"
        aria-expanded={open}
        onMouseDown={(event) => event.stopPropagation()}
        onPointerDown={(event) => event.stopPropagation()}
        onClick={(event) => {
          event.preventDefault();
          event.stopPropagation();
          onToggle();
        }}
      >
        <span className="canvas-select-chip__value">{getOptionLabel(options, value)}</span>
        <DownOutlined className="canvas-select-chip__arrow" />
      </button>
      {open ? (
        <div
          className="canvas-select-chip__dropdown"
          role="listbox"
          onMouseDown={(event) => event.stopPropagation()}
          onClick={(event) => event.stopPropagation()}
        >
          {options.map((option, index) => (
            <button
              key={option.value}
              type="button"
              className={`canvas-select-chip__option${option.value === value ? " is-active" : ""}`}
              role="option"
              aria-selected={option.value === value}
              style={{ animationDelay: `${index * 18}ms` }}
              onClick={(event) => {
                event.preventDefault();
                event.stopPropagation();
                onChange(option.value);
              }}
            >
              <span className="canvas-select-chip__option-dot" />
              <span>{option.label}</span>
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}


export function CanvasNodeVideoPlayer({ src, title, onVideoMeta }: { src: string; title: string; onVideoMeta?: (width: number, height: number) => void }) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [isMuted, setIsMuted] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);

  useEffect(() => {
    setIsPlaying(false);
    setCurrentTime(0);
    setDuration(0);
  }, [src]);

  const stopPlayerEvent = (event: MouseEvent<HTMLElement>) => {
    event.preventDefault();
    event.stopPropagation();
  };

  const syncVideoState = () => {
    const video = videoRef.current;
    if (!video) return;
    setCurrentTime(video.currentTime || 0);
    setDuration(Number.isFinite(video.duration) ? video.duration : 0);
    setIsMuted(video.muted);
    setIsPlaying(!video.paused && !video.ended);
  };

  const togglePlayback = async (event: MouseEvent<HTMLButtonElement>) => {
    stopPlayerEvent(event);
    const video = videoRef.current;
    if (!video) return;

    if (video.paused || video.ended) {
      try {
        await video.play();
      } catch {
        setIsPlaying(false);
      }
    } else {
      video.pause();
    }
    syncVideoState();
  };

  const toggleMuted = (event: MouseEvent<HTMLButtonElement>) => {
    stopPlayerEvent(event);
    const video = videoRef.current;
    if (!video) return;
    video.muted = !video.muted;
    setIsMuted(video.muted);
  };

  const handleSeek = (event: ChangeEvent<HTMLInputElement>) => {
    event.stopPropagation();
    const video = videoRef.current;
    const nextTime = Number(event.target.value);
    if (!video || !Number.isFinite(nextTime)) return;
    video.currentTime = nextTime;
    setCurrentTime(nextTime);
  };

  return (
    <div className={`studio-canvas-video-player${isPlaying ? " is-playing" : ""}`}>
      <video
        ref={videoRef}
        src={src}
        playsInline
        preload="metadata"
        onLoadedMetadata={() => {
          syncVideoState();
          const video = videoRef.current;
          if (video && video.videoWidth > 0 && video.videoHeight > 0 && onVideoMeta) {
            onVideoMeta(video.videoWidth, video.videoHeight);
          }
        }}
        onTimeUpdate={syncVideoState}
        onPlay={syncVideoState}
        onPause={syncVideoState}
        onEnded={syncVideoState}
        aria-label={title}
      />
      <span className="studio-canvas-video-player__shade" aria-hidden="true" />
      <button
        type="button"
        className="studio-canvas-video-player__center"
        aria-label={isPlaying ? "Pause video preview" : "Play video preview"}
        title={isPlaying ? "Pause" : "Play"}
        onMouseDown={stopPlayerEvent}
        onClick={togglePlayback}
      >
        {isPlaying ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
      </button>
      <div className="studio-canvas-video-player__controls" onMouseDown={stopPlayerEvent}>
        <button
          type="button"
          className="studio-canvas-video-player__button"
          aria-label={isPlaying ? "Pause video preview" : "Play video preview"}
          onClick={togglePlayback}
        >
          {isPlaying ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
        </button>
        <span className="studio-canvas-video-player__time">
          {formatCanvasVideoTime(currentTime)} / {formatCanvasVideoTime(duration)}
        </span>
        <input
          className="studio-canvas-video-player__seek"
          type="range"
          min="0"
          max={Math.max(duration, 0)}
          step="0.1"
          value={Math.min(currentTime, duration || currentTime)}
          aria-label="Video preview progress"
          onMouseDown={stopPlayerEvent}
          onChange={handleSeek}
        />
        <button
          type="button"
          className="studio-canvas-video-player__button"
          aria-label={isMuted ? "Unmute video preview" : "Mute video preview"}
          onClick={toggleMuted}
        >
          {isMuted ? <MutedOutlined /> : <SoundOutlined />}
        </button>
      </div>
    </div>
  );
}

export interface CanvasNodeToolbarAction {
  key: string;
  label: string;
  icon: React.ReactNode;
  disabled?: boolean;
  loading?: boolean;
}

export function CanvasNodeToolbar({
  actions,
  onAction,
  moreActions,
  onMoreAction,
}: {
  actions: CanvasNodeToolbarAction[];
  onAction: (key: string) => void;
  moreActions?: CanvasNodeToolbarAction[];
  onMoreAction?: (key: string) => void;
}) {
  const [moreOpen, setMoreOpen] = useState(false);
  const moreRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!moreOpen) return;
    const handler = (e: globalThis.MouseEvent) => {
      if (moreRef.current && !moreRef.current.contains(e.target as Node)) {
        setMoreOpen(false);
      }
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [moreOpen]);

  return (
    <div
      className="studio-canvas-node-toolbar"
      onMouseDown={(e) => e.stopPropagation()}
      onPointerDown={(e) => e.stopPropagation()}
    >
      {actions.map((action) => (
        <button
          key={action.key}
          type="button"
          className={`studio-canvas-node-toolbar__btn${action.disabled ? " is-disabled" : ""}${action.loading ? " is-loading" : ""}`}
          disabled={action.disabled || action.loading}
          title={action.label}
          onClick={(e) => {
            e.stopPropagation();
            onAction(action.key);
          }}
        >
          {action.icon}
          <span>{action.label}</span>
        </button>
      ))}
      {moreActions && moreActions.length > 0 && (
        <div className="studio-canvas-node-toolbar__more" ref={moreRef}>
          <button
            type="button"
            className={`studio-canvas-node-toolbar__btn studio-canvas-node-toolbar__more-trigger${moreOpen ? " is-open" : ""}`}
            title="更多操作"
            onClick={(e) => {
              e.stopPropagation();
              setMoreOpen((v) => !v);
            }}
          >
            <ExpandOutlined />
            <span>更多</span>
          </button>
          {moreOpen && (
            <div className="studio-canvas-node-toolbar__dropdown">
              {moreActions.map((action) => (
                <button
                  key={action.key}
                  type="button"
                  className={`studio-canvas-node-toolbar__dropdown-item${action.disabled ? " is-disabled" : ""}`}
                  disabled={action.disabled}
                  onClick={(e) => {
                    e.stopPropagation();
                    setMoreOpen(false);
                    onMoreAction?.(action.key);
                  }}
                >
                  {action.icon}
                  <span>{action.label}</span>
                </button>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}
