import { getOrderById } from "../../../repositories/order-repo.js";
import { createTaskEvent } from "../../../repositories/task-event-repo.js";
import { updateTask } from "../../../repositories/task-repo.js";
import { createHttpError } from "../../../utils/http.js";
import { nowIso } from "../../../utils/time.js";
import { notifyKuaishouCloudConsumeFailed } from "../../notification/domain-notifications.js";
import { useCloudtentaclesSku } from "../../platforms/cloudtentacles/catalog-service.js";
import { backCloudtentaclesVirtualNumber } from "../../platforms/cloudtentacles/virtual-number-service.js";
import { consumeKuaishouEticket } from "../../platforms/kuaishou-eticket/consume-service.js";
import {
  getKuaishouEticketSourceConfig,
  resolveKuaishouEticketShopConfig,
} from "../../platforms/kuaishou-eticket/source-config-service.js";
import {
  isKuaishouCloudTask,
  maskCode,
  maskPhone,
  normalizeKuaishouCloudFlow,
  type JsonObject,
} from "./domain.js";
import { resolvePersistedCloudtentaclesContextWithFallback } from "./cloudtentacles-context.js";
import { normalizeActor, parseTaskContext } from "./task-context.js";

export async function dispatchKuaishouCloudFulfillmentTask(
  task,
  options: JsonObject = {}
) {
  if (!isKuaishouCloudTask(task)) {
    throw createHttpError("当前任务不是快手 Cloud 履约任务", {
      statusCode: 409,
      errorCode: "kuaishou_cloud_task_invalid",
    });
  }

  const actor = normalizeActor(options.actor);
  const now = nowIso();
  const taskContext = parseTaskContext(task);
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment);
  const effectiveSourceKey =
    flow.binding.resolvedSourceKey || flow.binding.cloudSourceKey || "default";
  const cloudContext = resolvePersistedCloudtentaclesContextWithFallback(
    effectiveSourceKey,
    flow.binding.cloudSourceKeyFallbacks || []
  );

  if (!flow.binding.skuId || !flow.binding.vnId || !flow.binding.vnPhone) {
    throw createHttpError(
      "当前任务还没有准备好绑定资源，请先完成绑定资源准备",
      {
        statusCode: 409,
        errorCode: "kuaishou_cloud_not_prepared",
      }
    );
  }

  const ticketCode = String(options.ticketCode || "").trim();
  const persistedTicketCode = String(flow.ticket.code || "").trim();
  if (!persistedTicketCode && !ticketCode) {
    throw createHttpError("客户还没有提交有效核销码，暂时不能继续兑换", {
      statusCode: 409,
      errorCode: "kuaishou_cloud_missing_ticket_code",
    });
  }

  if (
    flow.dispatch.status === "success" &&
    String(task.task_status || "").trim() === "dispatched_pending_return"
  ) {
    return { task, flow };
  }

  const dispatchResult = await useCloudtentaclesSku({
    ...cloudContext,
    id: flow.binding.skuId,
    virtualNumberId: flow.binding.vnId,
    phone: flow.binding.vnPhone,
  });

  const nextContext = {
    ...taskContext,
    kuaishouCloudFulfillment: {
      ...flow,
      ticket: {
        ...flow.ticket,
        code: ticketCode || persistedTicketCode,
        capturedAt: ticketCode ? now : flow.ticket.capturedAt,
        capturedBy: ticketCode && actor ? actor : flow.ticket.capturedBy,
      },
      dispatch: {
        ...flow.dispatch,
        status: "success",
        dispatchAt: now,
        dispatchBy: actor,
        sendType: Number(dispatchResult.sendType || 0) || 0,
        note: String(
          dispatchResult.note ||
            dispatchResult.responseMessage ||
            "cloudtentacles 发货成功"
        ).trim(),
      },
    },
  };

  let updatedTask = await updateTask(task.id, {
    task_status: "dispatched_pending_return",
    delivery_status: "delivered",
    result_code: "kuaishou_cloud_dispatched",
    result_message: String(
      dispatchResult.responseMessage ||
        dispatchResult.note ||
        "cloudtentacles 发货成功"
    ).trim(),
    user_action_status: "not_required",
    last_error: "",
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  });

  await createTaskEvent(
    task.id,
    "kuaishou_cloud_dispatched",
    {
      source: String(options.source || "system").trim() || "system",
      ticketCodeMasked: maskCode(ticketCode || persistedTicketCode),
      skuId: flow.binding.skuId,
      vnId: flow.binding.vnId,
      vnPhoneMasked: maskPhone(flow.binding.vnPhone),
      sendType: dispatchResult.sendType,
      note: dispatchResult.note,
      actor,
    },
    now
  );

  const shouldAutoFinalize =
    options.autoFinalize === true &&
    normalizeKuaishouCloudFlow(nextContext.kuaishouCloudFulfillment)
      .returnNumber.autoReturnEnabled === true;

  if (shouldAutoFinalize) {
    const finalizeResult = await returnKuaishouCloudFulfillmentTask(
      updatedTask,
      {
        actor,
        source: options.source || "system_auto_finalize",
      }
    );
    updatedTask = finalizeResult.task;
  }

  return {
    task: updatedTask,
    flow: normalizeKuaishouCloudFlow(
      parseTaskContext(updatedTask).kuaishouCloudFulfillment
    ),
  };
}

export async function returnKuaishouCloudFulfillmentTask(
  task,
  options: JsonObject = {}
) {
  if (!isKuaishouCloudTask(task)) {
    throw createHttpError("当前任务不是快手 Cloud 履约任务", {
      statusCode: 409,
      errorCode: "kuaishou_cloud_task_invalid",
    });
  }

  const actor = normalizeActor(options.actor);
  const now = nowIso();
  const taskContext = parseTaskContext(task);
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment);
  const effectiveSourceKey =
    flow.binding.resolvedSourceKey || flow.binding.cloudSourceKey || "default";
  const cloudContext = resolvePersistedCloudtentaclesContextWithFallback(
    effectiveSourceKey,
    flow.binding.cloudSourceKeyFallbacks || []
  );

  if (!flow.binding.vnId || !flow.binding.vnKey) {
    throw createHttpError("当前任务缺少可退还的虚拟号信息", {
      statusCode: 409,
      errorCode: "kuaishou_cloud_missing_return_context",
    });
  }

  if (
    flow.returnNumber.status === "success" &&
    ["completed", "manual_review"].includes(
      String(task.task_status || "").trim()
    )
  ) {
    return { task, flow };
  }

  await backCloudtentaclesVirtualNumber({
    ...cloudContext,
    key: flow.binding.vnKey,
    id: flow.binding.vnId,
  });

  const order = await getOrderById(task.order_id);
  const ticketCode = String(flow.ticket.code || "").trim();
  const shopId = String(flow.consume.shopId || order?.shop_id || "").trim();
  const shopName = String(
    flow.consume.shopName || order?.shop_name || ""
  ).trim();
  const eticketSource = getKuaishouEticketSourceConfig();
  const shopConfig = resolveKuaishouEticketShopConfig({
    shopId,
    shopName,
  });

  let consumeStatus = "pending";
  let consumeErrorMessage = "";
  let consumedAt = null;
  let nextTaskStatus = "completed";
  let nextResultCode = "kuaishou_cloud_completed";
  let nextResultMessage = "cloudtentacles 发货、退号并完成快手核销";

  if (!order) {
    consumeStatus = "failed";
    consumeErrorMessage = "任务关联订单不存在，无法执行快手核销";
  } else if (!ticketCode) {
    consumeStatus = "failed";
    consumeErrorMessage = "客户未提交有效核销码，无法执行快手核销";
  } else if (
    !shopConfig ||
    shopConfig.enabled === false ||
    !String(shopConfig.cookie || "").trim()
  ) {
    consumeStatus = "failed";
    consumeErrorMessage = "订单对应快手小店缺少可用 Cookie，无法执行快手核销";
  } else {
    try {
      const consumeResult = await consumeKuaishouEticket({
        baseUrl: eticketSource.baseUrl,
        cookie: shopConfig.cookie,
        eTicketId: ticketCode,
        oid: String(flow.ticket.oid || "").trim(),
        formToken: String(flow.ticket.formToken || "").trim(),
      });

      if (consumeResult.consumed) {
        consumeStatus = "success";
        consumedAt = now;
      } else {
        consumeStatus = "failed";
        consumeErrorMessage = String(
          consumeResult.errorMessage || "快手核销失败"
        ).trim();
      }
    } catch (error) {
      consumeStatus = "failed";
      consumeErrorMessage =
        error instanceof Error ? error.message : "快手核销失败";
    }
  }

  if (consumeStatus !== "success") {
    nextTaskStatus = "manual_review";
    nextResultCode = "kuaishou_cloud_consume_failed";
    nextResultMessage =
      consumeErrorMessage || "号码已退还，但快手核销未完成，请人工处理";
  }

  const nextContext = {
    ...taskContext,
    kuaishouCloudFulfillment: {
      ...flow,
      returnNumber: {
        ...flow.returnNumber,
        status: "success",
        returnedAt: now,
        returnedBy: actor,
      },
      consume: {
        ...flow.consume,
        status: consumeStatus,
        shopId: shopId || flow.consume.shopId,
        shopName,
        autoConsumeEnabled: flow.consume.autoConsumeEnabled === true,
        consumedAt,
        errorMessage: consumeErrorMessage,
      },
    },
  };

  const updatedTask = await updateTask(task.id, {
    task_status: nextTaskStatus,
    delivery_status: "delivered",
    result_code: nextResultCode,
    result_message: nextResultMessage,
    redeemed_at: consumeStatus === "success" ? now : task.redeemed_at,
    last_error: consumeErrorMessage,
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  });

  await createTaskEvent(
    task.id,
    "kuaishou_cloud_number_returned",
    {
      source: String(options.source || "system").trim() || "system",
      vnId: flow.binding.vnId,
      vnPhoneMasked: maskPhone(flow.binding.vnPhone),
      actor,
    },
    now
  );

  await createTaskEvent(
    task.id,
    consumeStatus === "success"
      ? "kuaishou_cloud_consumed"
      : "kuaishou_cloud_consume_failed",
    {
      source: String(options.source || "system").trim() || "system",
      ticketCodeMasked: maskCode(ticketCode),
      shopId,
      shopName,
      consumeStatus,
      errorMessage: consumeErrorMessage,
      actor,
    },
    now
  );

  if (consumeStatus !== "success") {
    await notifyKuaishouCloudConsumeFailed({
      task: updatedTask,
      order,
      ticketCodeMasked: maskCode(ticketCode),
      shopId,
      shopName,
      errorMessage: consumeErrorMessage,
    });
  }

  return {
    task: updatedTask,
    flow: normalizeKuaishouCloudFlow(
      parseTaskContext(updatedTask).kuaishouCloudFulfillment
    ),
  };
}
