<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';

import { Page } from '@vben/common-ui';

import {
  Button,
  Card,
  DatePicker,
  Form,
  FormItem,
  InputNumber,
  message,
  Modal,
  Pagination,
  Select,
  Space,
  Table,
  Tag,
  TextArea,
} from 'antdv-next';
import dayjs from 'dayjs';

import { submitGmGoldOperation } from '#/api/legacy/gm';
import { getClsGoldRunningWater } from '#/api/legacy/operate';
import { listMembers } from '#/api/legacy/team';
import { getUserBaseInfoBySysOriginAccount } from '#/api/legacy/user';
import AccountInput from '#/components/account-input.vue';
import UserProfileLink from '#/views/operate/components/user-profile-link.vue';
import { formatDate } from '#/views/system/shared';

defineOptions({ name: 'GmGoldOperation' });

const INCOME_REASON_OPTIONS = [
  { label: '奖励', value: 1 },
  { label: '内部', value: 2 },
  { label: '工资', value: 3 },
  { label: '充值', value: 4 },
  { label: '其他', value: 5 },
];

const DEDUCT_REASON_OPTIONS = [
  { label: '违规', value: 1 },
  { label: '多发', value: 2 },
  { label: '操作错误', value: 3 },
  { label: '其他', value: 4 },
];

const TYPE_OPTIONS = [
  { label: '增加', value: 0 },
  { label: '减少', value: 1 },
];

const DEFAULT_PAGE_SIZE = 100;

const open = ref(false);
const loading = ref(false);
const loadMoreLoading = ref(false);
const submitting = ref(false);
const list = ref<Array<Record<string, any>>>([]);
const notMore = ref(false);
const currentPage = ref(1);
const rangeDate = ref<[string, string] | null>(null);
const operators = ref<Array<Record<string, any>>>([]);

const query = reactive<Record<string, any>>({
  backOperationUser: undefined,
  context: '',
  endTime: '',
  lastId: '',
  limit: DEFAULT_PAGE_SIZE,
  startTime: '',
  type: undefined,
  userId: '',
});

const form = reactive({
  operationType: 0,
  quantity: undefined as number | undefined,
  reasonType: 1,
  remarks: '',
  usdQuantity: undefined as number | undefined,
  userSearch: '',
});

const columns = [
  { dataIndex: 'userProfile', key: 'userProfile', title: '用户', width: 240 },
  { dataIndex: 'type', key: 'type', title: '类型', width: 100 },
  { dataIndex: 'quantity', key: 'quantity', title: '金额', width: 130 },
  { dataIndex: 'balance', key: 'balance', title: '余额', width: 130 },
  { dataIndex: 'originName', key: 'originName', title: '原因', width: 220 },
  { dataIndex: 'remark', key: 'remark', title: '备注', width: 260 },
  { dataIndex: 'backOperationName', key: 'backOperationName', title: '操作人', width: 160 },
  { dataIndex: 'createTime', key: 'createTime', title: '操作时间', width: 180 },
];

const reasonOptions = computed(() =>
  form.operationType === 0 ? INCOME_REASON_OPTIONS : DEDUCT_REASON_OPTIONS,
);

const showUsdQuantity = computed(
  () => form.operationType === 0 && [3, 4].includes(Number(form.reasonType)),
);

const operatorOptions = computed(() =>
  operators.value.map((item) => ({
    label: `${item.nickname || item.loginName || item.id} / ${item.loginName || item.id}`,
    value: item.id,
  })),
);

const currentPageList = computed(() => {
  const pageSize = Number(query.limit || DEFAULT_PAGE_SIZE);
  const startIndex = (currentPage.value - 1) * pageSize;
  return list.value.slice(startIndex, startIndex + pageSize);
});

const paginationTotal = computed(() => {
  const pageSize = Number(query.limit || DEFAULT_PAGE_SIZE);
  if (notMore.value) {
    return list.value.length;
  }
  return Math.max(list.value.length + pageSize, (currentPage.value + 1) * pageSize);
});

watch(
  rangeDate,
  (value) => {
    query.startTime = value?.[0] || '';
    query.endTime = value?.[1] || '';
  },
  { immediate: true },
);

watch(
  () => form.operationType,
  () => {
    form.reasonType = reasonOptions.value[0]?.value || 1;
    form.usdQuantity = undefined;
  },
);

watch(showUsdQuantity, (value) => {
  if (!value) {
    form.usdQuantity = undefined;
  }
});

function createDefaultRange() {
  const end = dayjs().endOf('day');
  const start = dayjs().subtract(1, 'day').startOf('day');
  return [String(start.valueOf()), String(end.valueOf())] as [string, string];
}

function applyRangeDate(value: [string, string] | null) {
  rangeDate.value = value;
  query.startTime = value?.[0] || '';
  query.endTime = value?.[1] || '';
}

function resetForm() {
  form.operationType = 0;
  form.quantity = undefined;
  form.reasonType = 1;
  form.remarks = '';
  form.usdQuantity = undefined;
  form.userSearch = '';
}

function parseEncodedValue(value: unknown) {
  const raw = String(value ?? '');
  const match = raw.match(/^\*(.*)\*$/);
  if (!match) {
    return {
      accountType: '',
      content: raw,
      sysOrigin: '',
    };
  }
  const body = match[1] || '';
  return {
    accountType: body.match(/accountType:([^,]*)/)?.[1] || '',
    content: body.match(/content:(.*)$/)?.[1] || '',
    sysOrigin: body.match(/sysOrigin:([^,]*)/)?.[1] || '',
  };
}

async function resolveUserId() {
  const parsed = parseEncodedValue(form.userSearch);
  const content = String(parsed.content || '').trim();
  if (!content) {
    message.warning('请输入用户ID');
    return '';
  }
  if (!parsed.accountType || parsed.accountType === 'LONG') {
    return content.replace(/[^\d]/g, '');
  }
  if (!parsed.sysOrigin) {
    message.warning('请选择系统');
    return '';
  }
  const result = await getUserBaseInfoBySysOriginAccount(parsed.sysOrigin, content);
  const userId = result?.id || result?.userId;
  if (!userId) {
    message.warning('未找到用户');
    return '';
  }
  return String(userId);
}

function validateForm() {
  if (!String(form.userSearch || '').trim()) {
    message.warning('请输入用户ID');
    return false;
  }
  if (!form.quantity || Number(form.quantity) <= 0) {
    message.warning('请输入大于0的金币数量');
    return false;
  }
  if (!String(form.remarks || '').trim()) {
    message.warning('请输入备注');
    return false;
  }
  return true;
}

function formatRunningWaterTime(value: any) {
  if (typeof value === 'string') {
    const trimmed = value.trim();
    if (/^\d+$/.test(trimmed)) {
      return formatDate(Number(trimmed));
    }
  }
  return formatDate(value);
}

function getRunningWater(record: Record<string, any>) {
  return record.runningWater || record;
}

function getRowKey(record: Record<string, any>) {
  return getRunningWater(record).id || record.id;
}

function getRecordType(record: Record<string, any>) {
  return Number(getRunningWater(record).type);
}

function getAmountPrefix(record: Record<string, any>) {
  return getRecordType(record) === 0 ? '+' : '-';
}

function getAmountClass(record: Record<string, any>) {
  return getRecordType(record) === 0 ? 'amount--income' : 'amount--expense';
}

function filterOperatorOption(input: string, option: any) {
  return String(option?.label || '').toLowerCase().includes(input.toLowerCase());
}

async function loadOperators() {
  operators.value = (await listMembers()) || [];
}

async function loadData(reset = false) {
  if (loading.value || loadMoreLoading.value) {
    return;
  }
  if (!query.startTime || !query.endTime) {
    message.warning('请选择时间范围');
    return;
  }

  const startYear = new Date(Number(query.startTime)).getFullYear();
  const endYear = new Date(Number(query.endTime)).getFullYear();
  if (startYear !== endYear) {
    message.warning('不允许跨年查询');
    return;
  }

  if (reset) {
    list.value = [];
    notMore.value = false;
    query.context = '';
    query.lastId = '';
    currentPage.value = 1;
  }

  if (reset) {
    loading.value = true;
  } else {
    loadMoreLoading.value = true;
  }

  try {
    const result = await getClsGoldRunningWater({
      backOperationUser: query.backOperationUser || undefined,
      context: query.context || undefined,
      endTime: query.endTime,
      lastId: query.lastId || undefined,
      limit: query.limit,
      queryBackOperationUser: true,
      startTime: query.startTime,
      type: query.type,
      userId: query.userId || undefined,
    });
    const waters = result?.waters || [];
    const nextList = reset ? waters : [...list.value, ...waters];
    list.value = nextList;
    query.context = result?.context || '';
    query.lastId = String(getRunningWater(nextList[nextList.length - 1] || {}).id || '');
    notMore.value =
      Boolean(result?.listOver) ||
      (!query.context && waters.length < Number(query.limit || DEFAULT_PAGE_SIZE));
  } finally {
    loading.value = false;
    loadMoreLoading.value = false;
  }
}

async function ensurePageLoaded(page: number) {
  const pageSize = Number(query.limit || DEFAULT_PAGE_SIZE);
  let guard = 0;
  while (!notMore.value && list.value.length < page * pageSize && guard < page) {
    const beforeLength = list.value.length;
    const beforeContext = query.context;
    await loadData(false);
    guard += 1;
    if (list.value.length === beforeLength && query.context === beforeContext) {
      break;
    }
  }
}

async function handlePageChange(page: number, pageSize?: number) {
  if (pageSize && pageSize !== Number(query.limit || DEFAULT_PAGE_SIZE)) {
    query.limit = pageSize;
    await loadData(true);
    return;
  }

  await ensurePageLoaded(page);
  if (notMore.value) {
    const maxPage = Math.max(1, Math.ceil(list.value.length / Number(query.limit || DEFAULT_PAGE_SIZE)));
    currentPage.value = Math.min(page, maxPage);
    return;
  }
  currentPage.value = page;
}

async function handleSearch() {
  await loadData(true);
}

async function handleSubmit() {
  if (!validateForm()) {
    return;
  }
  const userId = await resolveUserId();
  if (!userId) {
    return;
  }
  submitting.value = true;
  try {
    const result = await submitGmGoldOperation({
      operationType: form.operationType,
      quantity: form.quantity,
      reasonType: form.reasonType,
      remarks: form.remarks,
      usdQuantity: showUsdQuantity.value ? form.usdQuantity : undefined,
      userId,
    });
    if (result?.status === 'PENDING') {
      message.success('已提交 yumiadmin 审核');
    } else {
      message.success('金币操作已执行');
    }
    await loadData(true);
    open.value = false;
    resetForm();
  } finally {
    submitting.value = false;
  }
}

applyRangeDate(createDefaultRange());
void loadOperators();
void loadData(true);
</script>

<template>
  <Page title="金币操作">
    <Card>
      <div class="page-head">
        <div>
          <div class="page-head__title">后台金币增减记录</div>
          <div class="page-head__desc">查询所有管理员给用户发放或扣除金币的操作流水</div>
        </div>
        <Button type="primary" @click="open = true">金币操作</Button>
      </div>

      <div class="toolbar">
        <DatePicker.RangePicker
          v-model:value="rangeDate"
          show-time
          style="width: 360px"
          value-format="x"
        />
        <Select
          v-model:value="query.type"
          allow-clear
          placeholder="类型"
          style="width: 140px"
          :options="TYPE_OPTIONS"
        />
        <AccountInput
          v-model:value="query.userId"
          default-select-type="LONG"
          placeholder="用户ID"
          style="width: 240px"
        />
        <Select
          v-model:value="query.backOperationUser"
          allow-clear
          show-search
          placeholder="操作人"
          style="width: 220px"
          :filter-option="filterOperatorOption"
          :options="operatorOptions"
        />
        <Button :loading="loading" type="primary" @click="handleSearch">查询</Button>
      </div>

      <Table
        :columns="columns"
        :data-source="currentPageList"
        :loading="loading"
        :pagination="false"
        :row-key="getRowKey"
        :scroll="{ x: 1420 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'userProfile'">
            <UserProfileLink :profile="record.userProfile" />
          </template>
          <template v-else-if="column.key === 'type'">
            <Tag :color="getRecordType(record) === 0 ? 'green' : 'red'">
              {{ getRecordType(record) === 0 ? '增加' : '减少' }}
            </Tag>
          </template>
          <template v-else-if="column.key === 'quantity'">
            <span :class="['amount', getAmountClass(record)]">
              {{ getAmountPrefix(record) }}{{ getRunningWater(record).quantity ?? 0 }}
            </span>
          </template>
          <template v-else-if="column.key === 'balance'">
            {{ getRunningWater(record).balance ?? '-' }}
          </template>
          <template v-else-if="column.key === 'originName'">
            {{ getRunningWater(record).originName || '-' }}
          </template>
          <template v-else-if="column.key === 'remark'">
            {{ getRunningWater(record).remark || '-' }}
          </template>
          <template v-else-if="column.key === 'backOperationName'">
            {{ record.backOperationName || '-' }}
          </template>
          <template v-else-if="column.key === 'createTime'">
            {{ formatRunningWaterTime(getRunningWater(record).createTime) }}
          </template>
        </template>
      </Table>

      <div v-if="list.length > 0" class="pagination">
        <Pagination
          :current="currentPage"
          :disabled="loading || loadMoreLoading"
          :page-size="query.limit"
          :page-size-options="['20', '50', '100', '200']"
          :show-size-changer="true"
          :total="paginationTotal"
          show-less-items
          @change="handlePageChange"
          @showSizeChange="handlePageChange"
        />
      </div>
    </Card>

    <Modal
      v-model:open="open"
      title="金币操作"
      :confirm-loading="submitting"
      width="560px"
      @cancel="resetForm"
      @ok="handleSubmit"
    >
      <Form layout="vertical">
        <FormItem label="用户ID">
          <AccountInput
            v-model:value="form.userSearch"
            default-select-type="LONG"
            placeholder="请输入长ID或短ID"
          />
        </FormItem>
        <FormItem label="操作类型">
          <Select
            v-model:value="form.operationType"
            :options="[
              { label: '增加金币', value: 0 },
              { label: '扣除金币', value: 1 },
            ]"
          />
        </FormItem>
        <Space class="form-row" :size="12">
          <FormItem class="form-row__item" label="金币数量">
            <InputNumber
              v-model:value="form.quantity"
              :min="0.01"
              :precision="2"
              class="full-input"
            />
          </FormItem>
          <FormItem class="form-row__item" label="原因">
            <Select v-model:value="form.reasonType" :options="reasonOptions" />
          </FormItem>
        </Space>
        <FormItem v-if="showUsdQuantity" label="折算USD金额">
          <InputNumber
            v-model:value="form.usdQuantity"
            :min="0"
            :precision="2"
            class="full-input"
          />
        </FormItem>
        <FormItem label="备注">
          <TextArea
            v-model:value="form.remarks"
            :maxlength="500"
            :rows="4"
            show-count
            placeholder="请输入操作原因和备注"
          />
        </FormItem>
      </Form>
    </Modal>
  </Page>
</template>

<style scoped>
.page-head {
  align-items: center;
  display: flex;
  justify-content: space-between;
  margin-bottom: 16px;
}

.page-head__title {
  color: #111827;
  font-size: 16px;
  font-weight: 600;
}

.page-head__desc {
  color: #6b7280;
  font-size: 13px;
  margin-top: 4px;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}

.amount {
  font-weight: 600;
}

.amount--income {
  color: #16a34a;
}

.amount--expense {
  color: #dc2626;
}

.pagination {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.form-row {
  display: flex;
  width: 100%;
}

.form-row__item {
  flex: 1;
}

.full-input {
  width: 100%;
}
</style>
