import { computed, onMounted, reactive, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { billingAPI } from "@/api";
import type { DataGridColumn } from "@/components/common/DataGrid.vue";
import { useConsoleViewState } from "@/composables/useConsoleViewState";
import type { RedeemCodeSummary, RedeemRedemptionSummary } from "@/types";

export function useBillingWorkspace() {
const route = useRoute();
const router = useRouter();
const viewState = useConsoleViewState<"summary" | "detail">({
  view: "summary",
  viewValues: ["summary", "detail"],
  tab: "codes",
});
const codes = ref<RedeemCodeSummary[]>([]);
const redemptions = ref<RedeemRedemptionSummary[]>([]);
const loading = ref(true);
const loaded = ref(false);
const error = ref<string | null>(null);
const pending = ref<string | null>(null);
const selectedCodeId = ref<string | null>(
  typeof route.query.selectedCodeId === "string"
    ? route.query.selectedCodeId
    : null,
);
const createOpen = ref(false);
const createdCode = ref<string | null>(null);
const filters = reactive({
  status: typeof route.query.filter === "string" ? route.query.filter : "",
  userId: typeof route.query.userId === "string" ? route.query.userId : "",
  codeId: typeof route.query.codeId === "string" ? route.query.codeId : "",
});
const form = reactive({
  displayName: "",
  creditAmount: 10,
  reason: "redeem",
  maxRedemptions: 1,
  perUserLimit: 1,
  expiresAt: "",
});
let refreshSequence = 0;
const activeTab = computed({
  get: () => (viewState.tab.value === "redemptions" ? "redemptions" : "codes"),
  set: (value: string) =>
    void viewState.update(
      { tab: value === "codes" ? undefined : "redemptions" },
      false,
    ),
});
const viewMode = computed({
  get: () => viewState.view.value,
  set: (value: "summary" | "detail") =>
    void viewState.update(
      { view: value === "summary" ? undefined : value },
      false,
    ),
});
const selectedCode = computed(() =>
  selectedCodeId.value
    ? (codes.value.find((item) => codeKey(item) === selectedCodeId.value) ??
      null)
    : null,
);
const asyncState = computed(() =>
  loading.value
    ? loaded.value
      ? "refreshing"
      : "initial-loading"
    : error.value
      ? loaded.value
        ? "partial"
        : "error"
      : loaded.value
        ? "ready"
        : "empty",
);
const statusItems = computed(() => [
  { id: "codes", label: "Codes", value: codes.value.length },
  {
    id: "active",
    label: "Active",
    value: codes.value.filter((item) => item.status === "active").length,
    tone: "ok" as const,
  },
  { id: "redemptions", label: "Redemptions", value: redemptions.value.length },
  { id: "authority", label: "Authority", value: "user-billing" },
]);
const codeColumns: DataGridColumn[] = [
  { key: "code", label: "Code" },
  { key: "status", label: "Status" },
  { key: "credits", label: "Credits", align: "right" },
  { key: "usage", label: "Usage" },
  { key: "expires", label: "Expires" },
  { key: "actions", label: "Action", align: "right" },
];
const redemptionColumns: DataGridColumn[] = [
  { key: "time", label: "Time" },
  { key: "user", label: "User" },
  { key: "code", label: "Code" },
  { key: "credits", label: "Credits", align: "right" },
  { key: "status", label: "Status" },
  { key: "ledger", label: "Ledger" },
];

onMounted(refreshAll);
watch(
  () => [route.query.filter, route.query.userId, route.query.codeId].join("\0"),
  () => {
    filters.status =
      typeof route.query.filter === "string" ? route.query.filter : "";
    filters.userId =
      typeof route.query.userId === "string" ? route.query.userId : "";
    filters.codeId =
      typeof route.query.codeId === "string" ? route.query.codeId : "";
    void refreshAll();
  },
);
watch(
  () => route.query.selectedCodeId,
  (value) => {
    selectedCodeId.value = typeof value === "string" ? value : null;
  },
);
async function refreshAll(): Promise<void> {
  const requestSequence = ++refreshSequence;
  loading.value = true;
  error.value = null;
  const [codeResult, redemptionResult] = await Promise.all([
    billingAPI.adminRedeemCodes({
      status: filters.status || undefined,
      limit: 100,
    }),
    billingAPI.adminRedeemRedemptions({
      userId: filters.userId || undefined,
      codeId: filters.codeId || undefined,
      limit: 100,
    }),
  ]);
  if (requestSequence !== refreshSequence) return;
  const errors: string[] = [];
  if (codeResult.ok) codes.value = codeResult.data?.codes ?? [];
  else errors.push(`Codes: ${codeResult.error ?? `HTTP ${codeResult.status}`}`);
  if (redemptionResult.ok)
    redemptions.value = redemptionResult.data?.redemptions ?? [];
  else
    errors.push(
      `Redemptions: ${redemptionResult.error ?? `HTTP ${redemptionResult.status}`}`,
    );
  error.value = errors.join(" · ") || null;
  loading.value = false;
  loaded.value = true;
}
async function persistFilters(): Promise<void> {
  await router.push({
    query: {
      ...route.query,
      filter: filters.status || undefined,
      userId: filters.userId.trim() || undefined,
      codeId: filters.codeId.trim() || undefined,
    },
  });
}
async function selectCode(code: RedeemCodeSummary): Promise<void> {
  const codeId = codeKey(code);
  selectedCodeId.value = codeId;
  await router.push({ query: { ...route.query, selectedCodeId: codeId } });
}
async function closeInspector(): Promise<void> {
  selectedCodeId.value = null;
  await router.push({ query: { ...route.query, selectedCodeId: undefined } });
}
async function setStatus(code: RedeemCodeSummary): Promise<void> {
  if (!code.id) return;
  pending.value = `status:${code.id}`;
  const response = await billingAPI.updateAdminRedeemCode(code.id, {
    status: code.status === "disabled" ? "active" : "disabled",
  });
  pending.value = null;
  if (!response.ok) error.value = response.error ?? `HTTP ${response.status}`;
  else await refreshAll();
}
async function createCode(): Promise<void> {
  pending.value = "create";
  const body: Record<string, unknown> = {
    ...form,
    creditAmount: Number(form.creditAmount),
    maxRedemptions: Number(form.maxRedemptions),
    perUserLimit: Number(form.perUserLimit),
  };
  if (form.expiresAt) body.expiresAt = new Date(form.expiresAt).toISOString();
  else delete body.expiresAt;
  const response = await billingAPI.createAdminRedeemCode(body);
  pending.value = null;
  if (!response.ok) {
    error.value = response.error ?? `HTTP ${response.status}`;
    return;
  }
  createdCode.value = response.data?.redeemCode ?? null;
  await refreshAll();
}
function codeKey(item: RedeemCodeSummary): string {
  return item.id || item.codePrefix || "redeem-code";
}
function redemptionKey(item: RedeemRedemptionSummary): string {
  return item.id || `${item.userId}:${item.codeId}:${item.createdAt}`;
}
function formatNumber(value: unknown): string {
  return new Intl.NumberFormat("zh-CN").format(Number(value ?? 0));
}
function formatDate(value: unknown): string {
  const text = String(value ?? "");
  if (!text) return "-";
  const date = new Date(text);
  return Number.isNaN(date.getTime()) ? text : date.toLocaleString("zh-CN");
}

  return {
    codes, redemptions, loading, loaded, error, pending, selectedCodeId,
    createOpen, createdCode, filters, form, activeTab, viewMode, selectedCode,
    asyncState, statusItems, codeColumns, redemptionColumns, refreshAll,
    persistFilters, selectCode, closeInspector, setStatus, createCode,
    codeKey, redemptionKey, formatNumber, formatDate,
  };
}
