import { adminApiRequest, apiRequest } from "./client";

type PageParams = { page?: number; size?: number };
export type AdminPageResponse<T> = { items: T[]; total: number; page: number; size: number };
export type AdminActivityRow = Record<string, any> & {
  id: number;
  title: string;
  status?: string;
  startsAt?: string;
  endsAt?: string;
  location?: string;
  registeredCount?: number;
  checkinCount?: number;
};
export type AdminActivityRegistrationRow = Record<string, any> & {
  id: number;
  activityId: number;
  activityTitle?: string;
  userId: number;
  realName?: string;
  nickname?: string;
  phone?: string;
  email?: string;
  voucherNo?: string;
  orderNo?: string;
  checkedIn?: boolean;
};
export type ActivityParticipantCandidate = Record<string, any> & {
  userId: number;
  realName?: string;
  nickname?: string;
  phone?: string;
  email?: string;
  branchName?: string;
  registered?: boolean;
  checkedIn?: boolean;
};

const TYPE_MAP: Record<string, string> = {
  新闻资讯: "news",
  学习园地: "learning",
  建言献策: "suggestion",
  会员风采: "member_showcase",
};

const ADMIN_DESKTOP_PATH = "/api/console/dashboard/desktop";
const ADMIN_CHANGE_PASSWORD_PATH = "/api/console/auth/change-password";
const PENDING_CONTENTS_BASE = "/api/console/contents/pending";
const REVIEWS_BASE = "/api/console/reviews";

const REVIEW_TYPE_LABELS: Record<string, string> = {
  content: "内容",
  activity: "活动",
  survey: "问卷",
  service_project: "服务项目",
  mutual_aid: "企业互助",
  performance_record: "履职记录",
  proposal: "建言献策",
};

const REVIEW_STAGE_LABELS: Record<string, string> = {
  branch_review: "分会初审",
  city_review: "市级复审",
};

function toCamelKey(key: string) {
  return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
}

function toCamel(value: any): any {
  if (Array.isArray(value)) return value.map(toCamel);
  if (!value || typeof value !== "object") return value;
  return Object.keys(value).reduce((acc, key) => {
    acc[toCamelKey(key)] = toCamel(value[key]);
    return acc;
  }, {} as Record<string, any>);
}

function toPlainText(body?: string) {
  if (!body) return "";
  try {
    const parsed = JSON.parse(body);
    if (Array.isArray(parsed)) {
      return parsed
        .map((block) => {
          if (block?.type === "text") return block.content || "";
          if (block?.type === "image") return block.caption || "[图片]";
          if (block?.type === "video") return block.caption || "[视频]";
          if (block?.type === "audio") return block.caption || "[音频]";
          return "";
        })
        .filter(Boolean)
        .join("\n");
    }
  } catch {
    // Plain text body from older records.
  }
  return body;
}

function parseBodyBlocks(body: any, fallbackText?: string) {
  if (Array.isArray(body)) return body;
  if (typeof body === "string" && body.trim()) {
    try {
      const parsed = JSON.parse(body);
      if (Array.isArray(parsed)) return parsed;
    } catch {
      return [{ type: "text", content: body }];
    }
  }
  const text = String(fallbackText || "").trim();
  return text ? [{ type: "text", content: text }] : [];
}

function blocksToPlainText(blocks: any[]) {
  return blocks
    .map((block) => {
      if (block?.type === "text") return block.content || block.text || "";
      if (block?.type === "image") return block.caption || "[图片]";
      if (block?.type === "video") return block.caption || "[视频]";
      if (block?.type === "audio") return block.caption || "[音频]";
      return "";
    })
    .filter(Boolean)
    .join("\n");
}

function firstNonBlank(...values: any[]) {
  const value = values.find((item) => item !== undefined && item !== null && String(item).trim() !== "");
  return value === undefined || value === null ? "" : String(value).trim();
}

function hasMediaBlock(blocks: any[]) {
  return blocks.some((block) => ["image", "video", "audio"].includes(String(block?.type || "").toLowerCase()));
}

function mediaBlockFromRow(row: any) {
  const type = firstNonBlank(row?.mediaType, row?.type).toLowerCase();
  if (!["image", "video", "audio"].includes(type)) return null;
  const role = firstNonBlank(row?.role).toLowerCase();
  if (row?.isCover === true || role === "cover") return null;
  const originalUrl = firstNonBlank(row?.originalUrl, row?.url, row?.src);
  if (!originalUrl && !row?.fileId) return null;
  return {
    type,
    url: originalUrl,
    src: originalUrl,
    originalUrl,
    fileId: row?.fileId || undefined,
    thumbnailUrl: row?.thumbnailUrl || undefined,
    webpUrl: row?.webpUrl || undefined,
    poster: row?.poster || row?.coverUrl || row?.thumbnailUrl || undefined,
    caption: row?.caption || row?.altText || undefined,
  };
}

function mediaBlocksFrom(item: any) {
  return Array.isArray(item?.medias)
    ? item.medias.map(mediaBlockFromRow).filter(Boolean)
    : [];
}

function normalizeContentRow(row: any) {
  const item = toCamel(row);
  const parsedBlocks = parseBodyBlocks(item.bodyParsed || item.bodyJson, item.body);
  const mediaBlocks = mediaBlocksFrom(item);
  const bodyBlocks = mediaBlocks.length > 0 && !hasMediaBlock(parsedBlocks)
    ? [...parsedBlocks, ...mediaBlocks]
    : parsedBlocks;
  const bodyText = blocksToPlainText(bodyBlocks) || toPlainText(item.body);
  const reviewLogs = Array.isArray(item.reviewLogs) ? item.reviewLogs : [];
  const latestPending = [...reviewLogs]
    .reverse()
    .find((log: any) => log.reviewStatus === "pending" || log.review_status === "pending");
  return {
    ...item,
    createdAt: item.createdAt || item.created_at,
    updatedAt: item.updatedAt || item.updated_at,
    publishedAt: item.publishedAt || item.published_at,
    sourceName: item.sourceName || item.source_name,
    coverImageUrl: item.coverImageUrl || item.cover_image_url,
    authorName: item.authorName || item.author_name,
    reviewStage: item.reviewStage || latestPending?.reviewStage || latestPending?.review_stage,
    bodyBlocks,
    latestReview: latestPending
      ? {
          reviewStage: latestPending.reviewStage || latestPending.review_stage,
          version: latestPending.version || 1,
        }
      : undefined,
    content: item.content || bodyText,
  };
}

function normalizeReviewRow(row: any) {
  const item = toCamel(row);
  const targetType = firstNonBlank(item.targetType, item.target_type, item.type);
  const reviewStage = firstNonBlank(item.reviewStage, item.review_stage, item.stage);
  return {
    ...item,
    id: Number(item.id || item.reviewId || 0),
    reviewId: Number(item.id || item.reviewId || 0),
    targetId: Number(item.targetId || item.target_id || 0),
    targetType,
    type: REVIEW_TYPE_LABELS[targetType] || item.type || targetType || "审核",
    title: item.title || "待审核事项",
    status: item.status || "pending",
    reviewStage,
    stage: REVIEW_STAGE_LABELS[reviewStage] || reviewStage || "-",
    branchName: item.branchName || item.branch_name || "-",
    submitterName: item.submitterName || item.submitter_name || "-",
    createdAt: item.createdAt || item.created_at || item.submittedAt || "-",
    updatedAt: item.updatedAt || item.updated_at || "-",
  };
}

function normalizeReviewDetail(row: any) {
  const item = toCamel(row || {});
  return {
    ...normalizeReviewRow(item),
    target: toCamel(item.target || {}),
    logs: Array.isArray(item.logs) ? item.logs.map(toCamel) : [],
  };
}

function asReviewPage(data: any, params?: { stage?: string; type?: string; page?: number; size?: number }) {
  let items = (Array.isArray(data) ? data : data?.items || []).map(normalizeReviewRow);
  const stage = params?.stage || "";
  const type = params?.type ? TYPE_MAP[params.type] || params.type : "";
  if (stage) items = items.filter((item) => item.reviewStage === stage);
  if (type) items = items.filter((item) => item.targetType === type);
  const page = params?.page || 1;
  const size = params?.size || items.length || 20;
  const start = (page - 1) * size;
  return {
    items: items.slice(start, start + size),
    total: items.length,
    page,
    size,
  };
}

function normalizeAnnouncement(row: any) {
  const item = toCamel(row);
  return {
    ...item,
    createdAt: item.createdAt || item.created_at,
    updatedAt: item.updatedAt || item.updated_at,
    publishedAt: item.publishedAt || item.published_at,
  };
}

function asPage(data: any, params?: PageParams, normalizer: (row: any) => any = toCamel) {
  const rawItems = Array.isArray(data) ? data : data?.items || data?.records || [];
  const normalized = rawItems.map(normalizer);
  if (Array.isArray(data) && params?.page && params?.size) {
    const start = (params.page - 1) * params.size;
    const end = start + params.size;
    return {
      items: normalized.slice(start, end),
      total: normalized.length,
      page: params.page,
      size: params.size,
    };
  }
  return {
    ...toCamel(data || {}),
    items: normalized,
    total: data?.total ?? normalized.length,
    page: data?.page ?? params?.page ?? 1,
    size: data?.size ?? params?.size ?? normalized.length,
  };
}

function queryString(params: Record<string, any>) {
  const query = new URLSearchParams();
  Object.entries(params).forEach(([key, value]) => {
    if (value !== undefined && value !== null && String(value).trim() !== "") {
      query.set(key, String(value));
    }
  });
  const qs = query.toString();
  return qs ? `?${qs}` : "";
}

function contentBody(content?: string, body?: string) {
  const text = (body || content || "").trim();
  if (!text) return "";
  try {
    JSON.parse(text);
    return text;
  } catch {
    return JSON.stringify([{ type: "text", content: text }]);
  }
}

function parseContentBodyJson(body: string) {
  if (!body) return undefined;
  try {
    const parsed = JSON.parse(body);
    return Array.isArray(parsed) ? parsed : undefined;
  } catch {
    return undefined;
  }
}

function normalizeContentPayload(data: any) {
  const type = TYPE_MAP[data.type] || data.type || "news";
  const body = contentBody(data.content, data.body);
  const bodyJson = data.bodyJson || parseContentBodyJson(body);
  const coverImageUrl = data.coverImageUrl || data.coverUrl;
  const medias = Array.isArray(data.medias)
    ? data.medias
    : data.coverFileId || coverImageUrl
      ? [
          {
            mediaType: "image",
            fileId: data.coverFileId || undefined,
            originalUrl: coverImageUrl,
            isCover: true,
          },
        ].filter((item) => item.originalUrl || item.fileId)
      : undefined;
  return {
    type,
    title: data.title,
    summary: data.summary || toPlainText(body).slice(0, 120),
    body,
    bodyJson,
    bodyFormat: data.bodyFormat || (bodyJson ? "blocks_json" : undefined),
    sourceName: data.sourceName || data.source,
    coverImageUrl,
    coverFileId: data.coverFileId || undefined,
    status: data.status || "draft",
    adopted: data.adopted,
    medias,
  };
}

export function adminLogin(username: string, password: string) {
  return apiRequest("/api/admin/auth/login", {
    method: "POST",
    data: { username, password },
  });
}

export function adminRefreshToken(refreshToken: string) {
  return apiRequest("/api/admin/auth/refresh", {
    method: "POST",
    data: { refreshToken },
  });
}

export function adminChangePassword(oldPassword: string, newPassword: string) {
  return adminApiRequest(ADMIN_CHANGE_PASSWORD_PATH, {
    method: "POST",
    data: { oldPassword, newPassword },
  });
}

export function getAdminActivities(params?: { status?: string; keyword?: string; page?: number; pageSize?: number }) {
  const page = params?.page || 1;
  const size = params?.pageSize || 50;
  return adminApiRequest(`/api/console/activities${queryString({
    status: params?.status,
    keyword: params?.keyword,
    page,
    pageSize: size,
  })}`).then((data) => asPage(data, { page, size }, toCamel) as AdminPageResponse<AdminActivityRow>);
}

export function getActivityRegistrations(params: {
  activityId?: number;
  status?: string;
  keyword?: string;
  page?: number;
  pageSize?: number;
}) {
  const page = params.page || 1;
  const size = params.pageSize || 40;
  return adminApiRequest(`/api/console/activities/registrations${queryString({
    activityId: params.activityId,
    status: params.status,
    keyword: params.keyword,
    page,
    pageSize: size,
  })}`).then((data) => asPage(data, { page, size }, toCamel) as AdminPageResponse<AdminActivityRegistrationRow>);
}

export function searchActivityParticipants(activityId: number, keyword: string, limit = 20) {
  return adminApiRequest(`/api/console/activities/${activityId}/participants/search${queryString({
    keyword,
    limit,
  })}`).then((data) => (Array.isArray(data) ? data : []).map(toCamel) as ActivityParticipantCandidate[]);
}

export function manualActivityCheckin(activityId: number, userId: number, reason?: string) {
  return adminApiRequest(`/api/console/activities/${activityId}/checkins/manual`, {
    method: "POST",
    data: { userId, reason: reason || "小程序现场签到" },
  });
}

export function getAdminDashboard() {
  return adminApiRequest(ADMIN_DESKTOP_PATH).then(toCamel);
}

export function getPendingContents(params?: { stage?: string; type?: string; page?: number; size?: number }) {
  const query = new URLSearchParams();
  if (params?.stage) query.set("stage", params.stage);
  if (params?.type) query.set("type", TYPE_MAP[params.type] || params.type);
  if (params?.page) query.set("page", String(params.page));
  if (params?.size) query.set("size", String(params.size));
  const qs = query.toString();
  return adminApiRequest(`${PENDING_CONTENTS_BASE}${qs ? `?${qs}` : ""}`).then((data) =>
    asPage(data, params, normalizeContentRow)
  );
}

export function getPendingReviews(params?: { stage?: string; type?: string; page?: number; size?: number }) {
  const query = new URLSearchParams();
  if (params?.stage) query.set("stage", params.stage);
  if (params?.type) query.set("type", TYPE_MAP[params.type] || params.type);
  if (params?.page) query.set("page", String(params.page));
  if (params?.size) query.set("size", String(params.size));
  const qs = query.toString();
  return adminApiRequest(`${REVIEWS_BASE}${qs ? `?${qs}` : ""}`).then((data) => asReviewPage(data, params));
}

export function getAdminReviewDetail(id: number) {
  return adminApiRequest(`${REVIEWS_BASE}/${id}`).then(normalizeReviewDetail);
}

export function approveReviewTask(id: number, comment?: string) {
  return adminApiRequest(`${REVIEWS_BASE}/${id}/approve`, {
    method: "POST",
    data: { comment: comment || "审核通过" },
  });
}

export function rejectReviewTask(id: number, reason: string) {
  return adminApiRequest(`${REVIEWS_BASE}/${id}/reject`, {
    method: "POST",
    data: { reason },
  });
}

export function getAdminContentDetail(id: number) {
  return adminApiRequest(`/api/console/contents/${id}`).then(normalizeContentRow);
}

export function branchApprove(contentId: number, version?: number) {
  return adminApiRequest(`/api/console/contents/${contentId}/branch-approve`, {
    method: "POST",
    data: { version },
  });
}

export function branchReject(contentId: number, reason: string, version?: number) {
  return adminApiRequest(`/api/console/contents/${contentId}/branch-reject`, {
    method: "POST",
    data: { reason, version },
  });
}

export function cityApprove(contentId: number, version?: number) {
  return adminApiRequest(`/api/console/contents/${contentId}/city-approve`, {
    method: "POST",
    data: { version },
  });
}

export function cityReject(contentId: number, reason: string, version?: number) {
  return adminApiRequest(`/api/console/contents/${contentId}/city-reject`, {
    method: "POST",
    data: { reason, version },
  });
}

export function adminCreateContent(data: any) {
  return adminApiRequest("/api/console/contents", {
    method: "POST",
    data: normalizeContentPayload(data),
  }).then((res: any) => {
    const normalized = toCamel(res || {});
    return { ...normalized, id: normalized.id || normalized.contentId };
  });
}

export function adminUpdateContent(id: number, data: any) {
  return adminApiRequest(`/api/console/contents/${id}`, {
    method: "PUT",
    data: normalizeContentPayload(data),
  });
}

export function adminSubmitContent(id: number) {
  return adminApiRequest(`/api/console/contents/${id}/submit`, {
    method: "POST",
  });
}

export function getAdminContents(params?: { status?: string; page?: number; size?: number }) {
  const query = new URLSearchParams();
  if (params?.status) query.set("status", params.status);
  if (params?.page) query.set("page", String(params.page));
  if (params?.size) query.set("pageSize", String(params.size));
  const qs = query.toString();
  return adminApiRequest(`/api/console/contents${qs ? `?${qs}` : ""}`).then((data) =>
    asPage(data, params, normalizeContentRow)
  );
}

export function createAnnouncement(data: { title: string; content: string; scopeType: string; branchIds?: number[]; status?: string }) {
  return adminApiRequest("/api/console/announcements", {
    method: "POST",
    data: {
      title: data.title,
      content: data.content,
      scopeType: data.scopeType,
      branchIds: data.branchIds || [],
      status: data.status || "draft",
    },
  }).then((res: any) => {
    const normalized = toCamel(res || {});
    return { ...normalized, id: normalized.id || normalized.announcementId };
  });
}

export function updateAnnouncement(id: number, data: { title?: string; content?: string; status?: string }) {
  return adminApiRequest(`/api/console/announcements/${id}`, {
    method: "PUT",
    data,
  });
}

export function publishAnnouncement(id: number) {
  return adminApiRequest(`/api/console/announcements/${id}/publish`, {
    method: "POST",
  });
}

export function withdrawAnnouncement(id: number) {
  return adminApiRequest(`/api/console/announcements/${id}/withdraw`, {
    method: "POST",
  });
}

export function getAnnouncements(params?: { status?: string; page?: number; size?: number }) {
  const query = new URLSearchParams();
  if (params?.status) query.set("status", params.status);
  if (params?.page) query.set("page", String(params.page));
  if (params?.size) query.set("pageSize", String(params.size));
  const qs = query.toString();
  return adminApiRequest(`/api/console/announcements${qs ? `?${qs}` : ""}`).then((data) =>
    asPage(data, params, normalizeAnnouncement)
  );
}
