import type { WebAssetItem } from "../types";
import { isRecord, serverRequest } from "./serverConnection";

export interface ServerAssetItem extends WebAssetItem {
  id: string;
  url?: string | null;
  ossKey?: string | null;
  tags: string[];
  sourceTaskId?: string | null;
  sourceProjectId?: string | null;
  metadata?: Record<string, unknown>;
  createdAt?: string;
}

export interface CreateAssetInput {
  type: WebAssetItem["type"] | "image" | "asset" | "other";
  name: string;
  description?: string;
  url?: string;
  imageUrl?: string;
  ossKey?: string;
  tags?: string[];
  status?: WebAssetItem["status"] | "pending" | "failed";
  sourceTaskId?: string;
  sourceProjectId?: string;
  metadata?: Record<string, unknown>;
}

export interface DeleteAssetOptions {
  cleanupUserData?: boolean;
}

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 normalizeAssetType(value: unknown): WebAssetItem["type"] {
  const type = toStringValue(value);
  if (
    type === "character" ||
    type === "scene" ||
    type === "prop" ||
    type === "video" ||
    type === "image" ||
    type === "asset" ||
    type === "other"
  ) {
    return type;
  }
  return "other";
}

function normalizeAssetStatus(value: unknown): WebAssetItem["status"] {
  const status = toStringValue(value);
  if (
    status === "ready" ||
    status === "draft" ||
    status === "reviewing" ||
    status === "pending" ||
    status === "failed"
  ) {
    return status;
  }
  return "ready";
}

function normalizeTags(value: unknown): string[] {
  if (!Array.isArray(value)) return [];
  const tags: string[] = [];
  for (const item of value) {
    const tag = toStringValue(item);
    if (tag) tags.push(tag);
  }
  return tags;
}

function normalizeAsset(raw: unknown): ServerAssetItem {
  const item = isRecord(raw) ? raw : {};
  const url = toStringValue(item.url ?? item.imageUrl) || null;
  return {
    id: toStringValue(item.id, `asset-${Date.now()}`),
    type: normalizeAssetType(item.type),
    name: toStringValue(item.name, "未命名素材"),
    description: toStringValue(item.description, "从服务器资产库同步的素材。"),
    imageUrl: url || "",
    url,
    ossKey: toStringValue(item.ossKey ?? item.oss_key) || null,
    tags: normalizeTags(item.tags),
    status: normalizeAssetStatus(item.status),
    sourceTaskId: toStringValue(item.sourceTaskId ?? item.source_task_id) || null,
    sourceProjectId: toStringValue(item.sourceProjectId ?? item.source_project_id) || null,
    metadata: isRecord(item.metadata) ? item.metadata : {},
    createdAt: toStringValue(item.createdAt ?? item.created_at),
    updatedAt: toStringValue(item.updatedAt ?? item.updated_at, "刚刚"),
  };
}

function extractAssets(payload: unknown): ServerAssetItem[] {
  if (Array.isArray(payload)) return payload.map(normalizeAsset);
  if (!isRecord(payload)) return [];
  const rows = payload.assets ?? payload.items;
  return Array.isArray(rows) ? rows.map(normalizeAsset) : [];
}

export const assetClient = {
  async list(params?: { type?: string; q?: string; status?: string }): Promise<ServerAssetItem[]> {
    const search = new URLSearchParams();
    if (params?.type && params.type !== "all") search.set("type", params.type);
    if (params?.q) search.set("q", params.q);
    if (params?.status) search.set("status", params.status);
    const query = search.toString();
    return extractAssets(await serverRequest<unknown>(`assets${query ? `?${query}` : ""}`));
  },

  async create(input: CreateAssetInput): Promise<ServerAssetItem> {
    const payload = await serverRequest<{ asset: unknown }>("assets", {
      method: "POST",
      body: input,
    });
    return normalizeAsset(payload.asset ?? payload);
  },

  async delete(id: string, options?: DeleteAssetOptions): Promise<void> {
    const path = options?.cleanupUserData ? `assets/${encodeURIComponent(id)}?cleanupUserData=1` : `assets/${encodeURIComponent(id)}`;
    await serverRequest(path, { method: "DELETE" });
  },
};
