<script setup lang="ts">
import type { DataTableColumns } from "naive-ui";
import {
  NButton,
  NDataTable,
  NDatePicker,
  NImage,
  NFormItemGi,
  NInput,
  NModal,
  NPagination,
  NSelect,
  NSpace,
  NTag,
  useDialog,
  useMessage,
} from "naive-ui";
import AdminSearchPanel from "@/components/AdminSearchPanel.vue";
import AdminTablePageBar from "@/components/AdminTablePageBar.vue";
import * as orderApi from "@/api/modules/finance/order";
import type { OrderItem, OrderSearchParams } from "@/api/modules/finance/order";
import { useTableColumnsControl } from "@/composables";
import { resolveMediaUrl } from "@/utils/resolveMediaUrl";

const message = useMessage();
const dialog = useDialog();
const loading = ref(false);
const completingId = ref<number | null>(null);

const list = ref<OrderItem[]>([]);
const total = ref(0);
const page = ref(1);
const pageSize = ref(10);
const coursesModalVisible = ref(false);

interface OrderCourseItem {
  frontUrl?: string;
  goodsName?: string;
  title?: string;
  goodsPrice?: number | string;
}

const activeCourses = ref<OrderCourseItem[]>([]);

const statusOptions = [
  { label: "全部", value: "" },
  { label: "未支付", value: "1" },
  { label: "已支付", value: "2" },
  { label: "支付失败", value: "3" },
  { label: "已过期", value: "4" },
  { label: "已取消", value: "5" },
];

const search = ref<{
  serial: string;
  payName: string;
  status: string;
  dateRange: [number, number] | null;
}>({
  serial: "",
  payName: "",
  status: "",
  dateRange: null,
});

function toDateText(ts: number) {
  const d = new Date(ts);
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

function buildSearchPayload(): OrderSearchParams {
  const statusStr = search.value.status;
  return {
    serial: search.value.serial.trim() || undefined,
    payName: search.value.payName.trim() || undefined,
    status:
      statusStr && /^\d+$/.test(statusStr) ? Number(statusStr) : undefined,
    startDate: search.value.dateRange
      ? toDateText(search.value.dateRange[0])
      : undefined,
    endDate: search.value.dateRange
      ? toDateText(search.value.dateRange[1])
      : undefined,
    page: { current: page.value, row: pageSize.value },
  };
}

async function fetchList() {
  loading.value = true;
  try {
    const { list: rows, total: count } = await orderApi.searchOrderPage(
      buildSearchPayload(),
    );
    list.value = rows;
    total.value = count;
  } finally {
    loading.value = false;
  }
}

function onSearch() {
  page.value = 1;
  void fetchList();
}

function resetSearch() {
  search.value = {
    serial: "",
    payName: "",
    status: "",
    dateRange: null,
  };
  page.value = 1;
  void fetchList();
}

function amountText(v: unknown) {
  const n = Number(v ?? 0);
  if (Number.isNaN(n)) return "0.00";
  return n.toLocaleString(undefined, {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
}

function orderStatusTag(status: number | undefined) {
  const s = status ?? 0;
  if (s === 1) return { label: "未支付", type: "warning" as const };
  if (s === 2) return { label: "已支付", type: "success" as const };
  if (s === 3) return { label: "支付失败", type: "error" as const };
  if (s === 4) return { label: "已过期", type: "default" as const };
  if (s === 5) return { label: "已取消", type: "error" as const };
  return { label: String(s || "--"), type: "default" as const };
}

function timeCell(v: unknown) {
  if (v == null || v === "") return "--";
  if (typeof v === "number") {
    const d = new Date(v);
    return Number.isNaN(d.getTime()) ? String(v) : d.toLocaleString();
  }
  const s = String(v).trim();
  if (!s) return "--";
  const n = Number(s);
  if (!Number.isNaN(n) && s === String(n) && s.length >= 10) {
    const d = new Date(n);
    if (!Number.isNaN(d.getTime())) return d.toLocaleString();
  }
  const d = new Date(s);
  if (!Number.isNaN(d.getTime())) return d.toLocaleString();
  return s;
}

function parseOrderCourses(details: unknown): OrderCourseItem[] {
  if (details == null || details === "") return [];
  const normalize = (input: unknown): OrderCourseItem[] => {
    if (Array.isArray(input)) return input as OrderCourseItem[];
    if (input && typeof input === "object") return [input as OrderCourseItem];
    return [];
  };
  if (typeof details === "string") {
    const text = details.trim();
    if (!text) return [];
    try {
      return normalize(JSON.parse(text));
    } catch {
      return [];
    }
  }
  return normalize(details);
}

function courseName(item: OrderCourseItem) {
  return String(item.goodsName ?? item.title ?? "").trim() || "--";
}

function courseAmount(item: OrderCourseItem) {
  const n = Number(item.goodsPrice ?? 0);
  if (Number.isNaN(n)) return "--";
  return amountText(n);
}

function openCoursesModal(row: OrderItem) {
  activeCourses.value = parseOrderCourses(row.details);
  coursesModalVisible.value = true;
}

function confirmOrder(row: OrderItem) {
  dialog.warning({
    title: "确认订单",
    content: `确定将流水号 ${row.serial ?? row.id} 的订单标为已确认？`,
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: async () => {
      completingId.value = row.id;
      try {
        await orderApi.completeOrder({ id: row.id });
        message.success("确认成功");
        await fetchList();
      } finally {
        completingId.value = null;
      }
    },
  });
}

const columns = ref<DataTableColumns<OrderItem>>([
  { title: "CID", key: "cId", width: 120, ellipsis: { tooltip: true } },
  { title: "流水号", key: "serial", width: 180, ellipsis: { tooltip: true } },
  { title: "付款人姓名", key: "payName", width: 100, ellipsis: { tooltip: true } },
  { title: "付款人电话", key: "payPhone", width: 120, ellipsis: { tooltip: true } },
  { title: "邮箱", key: "email", width: 200, ellipsis: { tooltip: true } },
  {
    title: "金额",
    key: "amount",
    width: 110,
    render: (row) => amountText(row.amount),
  },
  { title: "货币", key: "currency", width: 80 },
  {
    title: "汇款金额",
    key: "transformAmount",
    width: 110,
    render: (row) => amountText(row.transformAmount),
  },
  { title: "汇款货币", key: "transformCurrency", width: 96 },
  { title: "支付通道", key: "channelCode", width: 120, ellipsis: { tooltip: true } },
  {
    title: "状态",
    key: "status",
    width: 100,
    render: (row) => {
      const t = orderStatusTag(row.status);
      return h(NTag, { type: t.type, size: "small" }, { default: () => t.label });
    },
  },
  {
    title: "购买时间",
    key: "addTime",
    width: 170,
    render: (row) => timeCell(row.addTime),
  },
  {
    title: "支付时间",
    key: "payTime",
    width: 170,
    render: (row) => timeCell(row.payTime),
  },
  {
    title: "购买的课程",
    key: "details",
    width: 120,
    render: (row) =>
      h(
        NButton,
        { size: "small", onClick: () => openCoursesModal(row) },
        { default: () => "查看" },
      ),
  },
  {
    title: "操作",
    key: "actions",
    width: 120,
    fixed: "right",
    render: (row) =>
      h(
        NButton,
        {
          size: "small",
          type: row.status === 1 ? "primary" : "default",
          disabled: row.status !== 1,
          loading: completingId.value === row.id,
          onClick: () => confirmOrder(row),
        },
        { default: () => "确认订单" },
      ),
  },
]);

const { visibleKeys, displayColumns, columnOptions } = useTableColumnsControl(
  columns,
  { frozenKeys: ["actions"] },
);

watch([page, pageSize], () => {
  void fetchList();
});

onMounted(() => {
  void fetchList();
});

onActivated(() => {
  void fetchList();
});
</script>

<template>
  <div class="page page--table">
    <AdminSearchPanel :field-count="5" @search="onSearch" @reset="resetSearch">
      <NFormItemGi :span="1" label="流水号">
        <NInput
          v-model:value="search.serial"
          clearable
          placeholder="流水号"
          @keyup.enter="onSearch"
        />
      </NFormItemGi>
      <NFormItemGi :span="1" label="付款人姓名">
        <NInput
          v-model:value="search.payName"
          clearable
          placeholder="付款人姓名"
          @keyup.enter="onSearch"
        />
      </NFormItemGi>
      <NFormItemGi :span="1" label="状态">
        <NSelect v-model:value="search.status" :options="statusOptions" />
      </NFormItemGi>
      <NFormItemGi :span="1" label="时间范围">
        <NDatePicker
          v-model:value="search.dateRange"
          type="daterange"
          clearable
          style="width: 100%"
        />
      </NFormItemGi>
    </AdminSearchPanel>

    <NCard :bordered="false" class="table-card table-card--fill">
      <div class="table-card-inner">
        <AdminTablePageBar
          title="订单列表"
          v-model:visible-keys="visibleKeys"
          :column-options="columnOptions"
          :refresh-loading="loading"
          @refresh="fetchList"
        />

        <div class="table-card__body">
          <NDataTable
            :columns="displayColumns"
            :data="list"
            :loading="loading"
            :bordered="false"
            :single-line="false"
            :row-key="(row: OrderItem) => row.id"
            class="data-table-fill"
            :scroll-x="2000"
          />
        </div>

        <div class="pager-wrap">
          <div class="pager-inline">
            <span class="pager-total">共 {{ total }} 条</span>
            <NPagination
              v-model:page="page"
              v-model:page-size="pageSize"
              :item-count="total"
              :page-sizes="[10, 20, 50, 100]"
              show-size-picker
            />
          </div>
        </div>
      </div>
    </NCard>

    <NModal
      v-model:show="coursesModalVisible"
      preset="card"
      title="购买的课程"
      style="width: min(860px, 92vw)"
      :mask-closable="false"
    >
      <div v-if="activeCourses.length" class="order-course-list">
        <div
          v-for="(item, index) in activeCourses"
          :key="`${courseName(item)}-${index}`"
          class="order-course-item"
        >
          <NImage
            class="order-course-item__cover"
            :src="resolveMediaUrl(item.frontUrl)"
            object-fit="cover"
            width="88"
            height="88"
            preview-disabled
            fallback-src=""
          />
          <div class="order-course-item__main">
            <div class="order-course-item__name">{{ courseName(item) }}</div>
            <div class="order-course-item__amount">金额：{{ courseAmount(item) }}</div>
          </div>
        </div>
      </div>
      <div v-else class="order-course-empty">暂无课程数据</div>

      <template #footer>
        <NSpace justify="end">
          <NButton @click="coursesModalVisible = false">关闭</NButton>
        </NSpace>
      </template>
    </NModal>
  </div>
</template>

<style scoped>
.order-course-list {
  display: grid;
  gap: 12px;
  max-height: 58vh;
  overflow: auto;
  padding-right: 2px;
}

.order-course-item {
  display: flex;
  gap: 12px;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  padding: 10px;
  align-items: center;
}

.order-course-item__cover {
  flex: none;
  border-radius: 8px;
  overflow: hidden;
  background: #f8fafc;
}

.order-course-item__main {
  min-width: 0;
}

.order-course-item__name {
  font-size: 14px;
  color: #111827;
  font-weight: 600;
  line-height: 1.4;
  word-break: break-all;
}

.order-course-item__amount {
  margin-top: 8px;
  color: #475569;
  font-size: 13px;
}

.order-course-empty {
  color: #64748b;
  text-align: center;
  padding: 24px 0;
}
</style>
