import type { ServerCommunityAsset, ServerCommunityCase } from "../../api/communityClient";
import type { WebCanvasWorkflow } from "../../types";

export type CommunityCaseSurface = "generation" | "canvas" | "unknown";

export interface PromptCaseViewModel {
  id: string;
  title: string;
  author: string;
  category: string;
  imageUrl: string;
  summary: string;
  prompt: string;
  ratio: string;
}

export interface PromptCaseRatioLike {
  ratio?: string | null;
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function toStringValue(value: unknown, fallback = ""): string {
  if (typeof value === "string") return value.trim() || fallback;
  if (typeof value === "number" && Number.isFinite(value)) return String(value);
  return fallback;
}

function normalizeSurface(value: unknown): CommunityCaseSurface {
  const normalized = toStringValue(value).toLowerCase();
  if (!normalized) return "unknown";
  if (normalized === "generation" || normalized === "workbench" || normalized.includes("生成")) return "generation";
  if (normalized === "canvas" || normalized === "workflow" || normalized.includes("画布")) return "canvas";
  return "unknown";
}

function getMetadata(item: Pick<ServerCommunityCase, "metadata">): Record<string, unknown> {
  return isRecord(item.metadata) ? item.metadata : {};
}

function getAssetUrl(asset: ServerCommunityAsset): string {
  return toStringValue(asset.url);
}

export function isCanvasWorkflow(value: unknown): value is WebCanvasWorkflow {
  return Boolean(
    isRecord(value) &&
      Array.isArray(value.nodes) &&
      Array.isArray(value.edges) &&
      isRecord(value.settings),
  );
}

export function getWorkflowFromCase(item: Pick<ServerCommunityCase, "metadata">): WebCanvasWorkflow | null {
  const metadata = getMetadata(item);
  const candidates = [
    metadata.workflow,
    metadata.workflowSnapshot,
    metadata.workflowData,
    metadata.canvasWorkflow,
  ];
  return candidates.find(isCanvasWorkflow) ?? null;
}

export function getWorkflowCoverUrl(workflow: unknown): string {
  if (!isRecord(workflow) || !Array.isArray(workflow.nodes)) return "";
  const previewNode = workflow.nodes.find((node) => isRecord(node) && toStringValue(node.previewUrl));
  return isRecord(previewNode) ? toStringValue(previewNode.previewUrl) : "";
}

export function getCommunityCaseCover(item: Pick<ServerCommunityCase, "coverUrl" | "assets" | "metadata">): string {
  return (
    toStringValue(item.coverUrl) ||
    getWorkflowCoverUrl(getWorkflowFromCase(item)) ||
    item.assets.find((asset) => asset.assetType === "cover" && getAssetUrl(asset))?.url ||
    item.assets.find((asset) => (asset.assetType === "image" || asset.assetType === "asset") && getAssetUrl(asset))?.url ||
    ""
  );
}

export function getCommunityCaseSurface(item: Pick<ServerCommunityCase, "metadata" | "tags" | "coverUrl" | "assets">): CommunityCaseSurface {
  const metadata = getMetadata(item);
  const explicitSurface = normalizeSurface(
    metadata.communitySurface ??
      metadata.targetSurface ??
      metadata.surface ??
      metadata.communityTarget ??
      metadata.targetCommunity,
  );
  if (explicitSurface !== "unknown") return explicitSurface;

  const tags: string[] = [];
  for (const rawTag of item.tags) {
    const tag = rawTag.trim();
    if (tag) tags.push(tag);
  }
  if (tags.some((tag) => tag.includes("生成页面社区") || tag === "Web生成")) return "generation";
  if (tags.some((tag) => tag.includes("画布页面社区") || tag.includes("工作流"))) return "canvas";
  if (getWorkflowFromCase(item)) return "canvas";
  if (toStringValue(metadata.prompt) && getCommunityCaseCover(item)) return "generation";
  return "unknown";
}

export function shouldShowInCanvasCommunity(item: Pick<ServerCommunityCase, "metadata" | "tags" | "coverUrl" | "assets">): boolean {
  return getCommunityCaseSurface(item) === "canvas";
}

export function communityCaseToPromptCase(item: ServerCommunityCase): PromptCaseViewModel | null {
  if (getCommunityCaseSurface(item) !== "generation") return null;

  const metadata = getMetadata(item);
  const imageUrl = getCommunityCaseCover(item);
  const prompt = toStringValue(metadata.prompt ?? metadata.inputPrompt ?? metadata.descriptionPrompt, item.description || "");
  if (!imageUrl || !prompt) return null;

  const category =
    toStringValue(metadata.category) ||
    item.tags.find((tag) => tag !== "生成页面社区" && tag !== "Web生成" && tag !== "图片") ||
    "图片案例";

  return {
    id: `server-prompt-case-${item.id}`,
    title: item.title,
    author: item.username || "OmniAI",
    category,
    imageUrl,
    summary: item.description || "管理员添加的生成页图片案例。",
    prompt,
    ratio: toStringValue(metadata.ratio ?? metadata.imageRatio ?? metadata.aspectRatio, "16:9"),
  };
}

function parseRatioValue(value: string): number | null {
  const normalized = value.replace(/\s+/g, "");
  const pair = normalized.match(/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/);
  if (pair) {
    const width = Number(pair[1]);
    const height = Number(pair[2]);
    return width > 0 && height > 0 ? width / height : null;
  }

  const numeric = Number(normalized);
  return Number.isFinite(numeric) && numeric > 0 ? numeric : null;
}

function getPromptCaseRatioClassName(numericRatio: number): string {
  return numericRatio >= 1.15
    ? "wb-prompt-case-card--ratio-wide"
    : numericRatio >= 0.95
      ? "wb-prompt-case-card--ratio-square"
      : numericRatio >= 0.72
        ? "wb-prompt-case-card--ratio-portrait"
        : "wb-prompt-case-card--ratio-tall";
}

export function getPromptCaseCardClassName(
  item: PromptCaseRatioLike,
  index: number,
  measuredRatio?: number | null,
): string {
  const ratio = toStringValue(item.ratio, "16:9").replace(/\s+/g, "");
  const measured = typeof measuredRatio === "number" && Number.isFinite(measuredRatio) && measuredRatio > 0 ? measuredRatio : null;
  const numericRatio = measured ?? parseRatioValue(ratio) ?? 16 / 9;
  const ratioClass = getPromptCaseRatioClassName(numericRatio);
  const sourceRatioClass = ratio ? ` wb-prompt-case-card--source-${ratio.replace(":", "-")}` : "";
  const measuredClass = measured ? " wb-prompt-case-card--measured" : "";
  return `wb-prompt-case-card ${ratioClass} wb-prompt-case-card--index-${index % 8}${sourceRatioClass}${measuredClass}`;
}
