import type { CSSProperties } from "react";
import type { VideoBlockProps } from "@/features/editor/state/editorStore";

export type VideoPlatform = "youtube" | "vimeo" | "html5";

export type VideoPlatformInput = VideoPlatform | "auto" | null | undefined;

// 비디오 sourceUrl 을 정규화한다: null/undefined 를 빈 문자열로 만들고 양 끝 공백을 제거한다.
export function normalizeVideoSourceUrl(source: string | null | undefined): string {
  if (!source) {
    return "";
  }

  return source.trim();
}

// platform 값과 URL 을 기반으로 최종 비디오 플랫폼을 결정한다.
// - platform 이 auto 가 아니면 해당 값을 우선 사용한다.
// - auto 인 경우 URL 을 검사해 youtube/vimeo/html5 를 판별한다.
export function resolveVideoPlatform(rawUrl: string, platform: VideoPlatformInput): VideoPlatform {
  if (platform && platform !== "auto") {
    return platform;
  }

  const normalized = normalizeVideoSourceUrl(rawUrl);
  const lower = normalized.toLowerCase();

  if (lower.includes("youtube.com") || lower.includes("youtu.be")) {
    return "youtube";
  }

  if (lower.includes("vimeo.com")) {
    return "vimeo";
  }

  return "html5";
}

export type BuildEmbedUrlOptions = {
  enableVimeoEmbed?: boolean;
};

// 플랫폼과 URL 을 기반으로 최종 embed URL 을 생성한다.
// - YouTube: 항상 watch/short/youtu.be 형태에서 embed URL 로 변환.
// - Vimeo: enableVimeoEmbed 가 true 인 경우에만 player.vimeo.com 기반 embed URL 로 변환.
// - HTML5: 항상 정규화된 원본 URL 을 그대로 사용.
export function buildVideoEmbedUrl(
  rawUrl: string,
  platform: VideoPlatform,
  options?: BuildEmbedUrlOptions,
): string {
  const normalized = normalizeVideoSourceUrl(rawUrl);

  if (platform === "youtube") {
    const idMatch =
      normalized.match(/[?&]v=([^&]+)/) ||
      normalized.match(/youtu\.be\/([^?&]+)/) ||
      normalized.match(/youtube\.com\/shorts\/([^?&]+)/);
    const videoId = idMatch && idMatch[1] ? idMatch[1] : "";
    if (videoId) {
      return `https://www.youtube.com/embed/${videoId}`;
    }
    return normalized;
  }

  if (platform === "vimeo" && options?.enableVimeoEmbed) {
    const idMatch = normalized.match(/vimeo\.com\/(\d+)/);
    const videoId = idMatch && idMatch[1] ? idMatch[1] : "";
    if (videoId) {
      return `https://player.vimeo.com/video/${videoId}`;
    }
    return normalized;
  }

  return normalized;
}

export interface VideoExportEscapers {
  escapeAttr: (value: string) => string;
}

export interface VideoExportTokens {
  wrapperStyleParts: string[];
  videoStyleParts: string[];
  outerStyleParts: string[];
  aspectClass: string;
}

export function computeVideoExportTokens(
  props: VideoBlockProps,
  escapers: VideoExportEscapers,
): VideoExportTokens {
  const { escapeAttr } = escapers;

  const aspect = props.aspectRatio ?? "16:9";
  const aspectClass =
    aspect === "4:3" ? " pb-video-wrapper--4by3" : aspect === "1:1" ? " pb-video-wrapper--1by1" : "";

  const wrapperStyleParts: string[] = [];
  const videoStyleParts: string[] = [];

  const widthMode = props.widthMode ?? "auto";
  if (widthMode === "fixed" && typeof props.widthPx === "number" && props.widthPx > 0) {
    const widthEm = pxToEm(props.widthPx);
    wrapperStyleParts.push(`width:${widthEm}`);
    videoStyleParts.push(`width:${widthEm}`);
  } else if (widthMode === "full") {
    wrapperStyleParts.push("width:100%");
    videoStyleParts.push("width:100%");
  }

  if (typeof props.backgroundColorCustom === "string" && props.backgroundColorCustom.trim() !== "") {
    wrapperStyleParts.push(`background-color:${escapeAttr(props.backgroundColorCustom.trim())}`);
  }

  if (typeof props.cardPaddingPx === "number" && props.cardPaddingPx >= 0) {
    wrapperStyleParts.push(`padding:${pxToEm(props.cardPaddingPx)}`);
  }

  if (typeof props.borderRadiusPx === "number" && props.borderRadiusPx >= 0) {
    wrapperStyleParts.push(`border-radius:${pxToEm(props.borderRadiusPx)}`);
  }

  const align =
    props.align === "left" ? "flex-start" : props.align === "right" ? "flex-end" : "center";
  const outerStyleParts = ["display:flex", `justify-content:${align}`];

  return {
    wrapperStyleParts,
    videoStyleParts,
    outerStyleParts,
    aspectClass,
  };
}

export interface VideoPublicTokens {
  wrapperStyle: CSSProperties;
  videoStyle: CSSProperties;
  justifyClass: string;
  aspectClass: string;
}

const pxToEm = (px: number, base = 16) => `${px / base}em`;

export function computeVideoPublicTokens(props: VideoBlockProps): VideoPublicTokens {
  const aspect = props.aspectRatio ?? "16:9";
  const aspectClass =
    aspect === "4:3" ? " pb-video-wrapper--4by3" : aspect === "1:1" ? " pb-video-wrapper--1by1" : "";

  const wrapperStyle: CSSProperties = {};
  const videoStyle: CSSProperties = {};

  const widthMode = props.widthMode ?? "auto";
  if (widthMode === "fixed" && typeof props.widthPx === "number" && props.widthPx > 0) {
    const widthEm = pxToEm(props.widthPx);
    wrapperStyle.width = widthEm;
    videoStyle.width = widthEm;
  } else if (widthMode === "full") {
    wrapperStyle.width = "100%";
    videoStyle.width = "100%";
  }

  if (props.backgroundColorCustom && props.backgroundColorCustom.trim() !== "") {
    wrapperStyle.backgroundColor = props.backgroundColorCustom.trim();
  }

  if (typeof (props as any).cardPaddingPx === "number" && (props as any).cardPaddingPx >= 0) {
    wrapperStyle.padding = pxToEm((props as any).cardPaddingPx as number);
  }

  if (typeof (props as any).borderRadiusPx === "number" && (props as any).borderRadiusPx >= 0) {
    wrapperStyle.borderRadius = pxToEm((props as any).borderRadiusPx as number);
  }

  const align = props.align ?? "center";
  const justifyClass =
    align === "left" ? "justify-start" : align === "right" ? "justify-end" : "justify-center";

  return {
    wrapperStyle,
    videoStyle,
    justifyClass,
    aspectClass,
  };
}

export interface VideoEditorTokens {
  wrapperStyle: CSSProperties;
  videoStyle: CSSProperties;
  justifyClass: string;
  aspectClass: string;
}

export function computeVideoEditorTokens(props: VideoBlockProps): VideoEditorTokens {
  const aspect = props.aspectRatio ?? "16:9";
  const aspectClass =
    aspect === "4:3" ? " pb-video-wrapper--4by3" : aspect === "1:1" ? " pb-video-wrapper--1by1" : "";

  const wrapperStyle: CSSProperties = {};
  const videoStyle: CSSProperties = {};

  const widthMode = props.widthMode ?? "auto";
  if (widthMode === "fixed" && typeof props.widthPx === "number" && props.widthPx > 0) {
    wrapperStyle.width = `${props.widthPx}px`;
    videoStyle.width = `${props.widthPx}px`;
  } else if (widthMode === "full") {
    wrapperStyle.width = "100%";
    videoStyle.width = "100%";
  }

  if (props.backgroundColorCustom && props.backgroundColorCustom.trim() !== "") {
    wrapperStyle.backgroundColor = props.backgroundColorCustom.trim();
  }
  if (typeof props.cardPaddingPx === "number" && props.cardPaddingPx >= 0) {
    wrapperStyle.padding = `${props.cardPaddingPx}px`;
  }
  if (typeof props.borderRadiusPx === "number" && props.borderRadiusPx >= 0) {
    wrapperStyle.borderRadius = `${props.borderRadiusPx}px`;
  }

  const align = props.align ?? "center";
  const justifyClass =
    align === "left" ? "justify-start" : align === "right" ? "justify-end" : "justify-center";

  return {
    wrapperStyle,
    videoStyle,
    justifyClass,
    aspectClass,
  };
}
