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

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

import { getCountryAlls } from '#/api/legacy/system';
import {
  confirmManualSalary,
  pageManualSalary,
} from '#/api/legacy/operate';
import AccountInput from '#/components/account-input.vue';
import AdminConfigTable from '#/views/_shared/admin-config-table.vue';
import { getAllowedSysOrigins } from '#/views/system/shared';

import {
  Button,
  Card,
  Modal,
  Select,
  Space,
  Table,
  Tag,
  message,
} from 'antdv-next';

import UserProfileLink from './components/user-profile-link.vue';

defineOptions({ name: 'OperateManualSalaryPayment' });

type SalarySortKey =
  | 'currentSalaryBalance'
  | 'payableSalary'
  | 'totalIssuedSalary';
type SalarySortOrder = '' | 'ascend' | 'descend';

const accessStore = useAccessStore();
const sysOriginOptions = computed(() => {
  const options = getAllowedSysOrigins(accessStore.accessCodes || []);
  return options.length > 0 ? options : getAllowedSysOrigins([]);
});

const loading = ref(false);
const paying = ref(false);
const settlingUserId = ref('');
const total = ref(0);
const list = ref<Array<Record<string, any>>>([]);
const countries = ref<Array<Record<string, any>>>([]);
const countryKeyword = ref('');
const resultOpen = ref(false);
const resultRows = ref<Array<Record<string, any>>>([]);
const selectedUserIds = ref<string[]>([]);
const salarySortKey = ref<'' | SalarySortKey>('');
const salarySortOrder = ref<SalarySortOrder>('');

const query = reactive({
  countryCode: '',
  cursor: 1,
  limit: 20,
  sortField: '',
  sortOrder: '' as SalarySortOrder,
  sysOrigin: '',
  userId: '',
});

const columns = [
  { dataIndex: 'userProfile', key: 'userProfile', title: '用户信息', width: 300 },
  { dataIndex: 'countryCode', key: 'countryCode', title: '国家', width: 90 },
  { dataIndex: 'lastSettlementTarget', key: 'lastSettlementTarget', title: '上次结算的积分', width: 150 },
  { dataIndex: 'currentTarget', key: 'currentTarget', title: '本次积分', width: 130 },
  { dataIndex: 'policyLevel', key: 'policyLevel', title: '本次积分档位', width: 130 },
  { dataIndex: 'expectedMemberSalary', key: 'expectedMemberSalary', title: '主播应发', width: 120 },
  { dataIndex: 'expectedAgentSalary', key: 'expectedAgentSalary', title: '代理应发', width: 120 },
  { dataIndex: 'expectedSalary', key: 'expectedSalary', title: '应发合计', width: 120 },
  { dataIndex: 'payableMemberSalary', key: 'payableMemberSalary', title: '主播差额', width: 120 },
  { dataIndex: 'payableAgentSalary', key: 'payableAgentSalary', title: '代理差额', width: 120 },
  { dataIndex: 'payableSalary', key: 'payableSalary', title: '合计差额', width: 140 },
  { dataIndex: 'memberIssuedSalary', key: 'memberIssuedSalary', title: '主播实收', width: 140 },
  { dataIndex: 'agentIssuedSalary', key: 'agentIssuedSalary', title: '代理实收', width: 140 },
  { dataIndex: 'totalIssuedSalary', key: 'totalIssuedSalary', title: '总发工资', width: 140 },
  { dataIndex: 'currentSalaryBalance', key: 'currentSalaryBalance', title: '当前工资', width: 140 },
  { dataIndex: 'action', fixed: 'right', key: 'action', title: '操作', width: 110 },
];

const resultColumns = [
  { dataIndex: 'userProfile', key: 'userProfile', title: '用户信息', width: 280 },
  { dataIndex: 'countryCode', key: 'countryCode', title: '国家', width: 90 },
  { dataIndex: 'salaryChange', key: 'salaryChange', title: '工资变动', width: 180 },
  { dataIndex: 'issuedSalary', key: 'issuedSalary', title: '发放工资', width: 120 },
  { dataIndex: 'policyLevel', key: 'policyLevel', title: '档位', width: 90 },
  { dataIndex: 'currentTarget', key: 'currentTarget', title: '本次积分', width: 120 },
];

const salarySortableKeys = new Set<SalarySortKey>([
  'payableSalary',
  'totalIssuedSalary',
  'currentSalaryBalance',
]);

const hasMore = computed(() => list.value.length < total.value);

const tableRows = computed(() =>
  list.value.map((item) => ({
    ...item,
    rowKey: getRowKey(item),
  })),
);

const summaryText = computed(() => {
  if (total.value <= 0) {
    return list.value.length > 0 ? `已加载 ${list.value.length} 条` : '';
  }
  return `已加载 ${list.value.length}/${total.value} 条`;
});

const selectedUserCount = computed(() => selectedUserIds.value.length);

const confirmButtonText = computed(() =>
  selectedUserCount.value > 0
    ? `确认发放(${selectedUserCount.value}人)`
    : '确认发放',
);

const rowSelection = computed(() => ({
  getCheckboxProps: (record: Record<string, any>) => ({
    disabled: !record.userId,
  }),
  onChange: (keys: Array<number | string>) => {
    selectedUserIds.value = keys.map(String).filter(Boolean);
  },
  preserveSelectedRowKeys: true,
  selectedRowKeys: selectedUserIds.value,
}));

const filteredCountries = computed(() => {
  const keyword = countryKeyword.value.trim().toLowerCase();
  if (!keyword) {
    return countries.value;
  }
  return countries.value.filter((item) =>
    [
      item.phonePrefix,
      item.countryName,
      item.aliasName,
      item.alphaTwo,
      item.alphaThree,
    ]
      .filter(Boolean)
      .join(' ')
      .toLowerCase()
      .includes(keyword),
  );
});

watch(
  sysOriginOptions,
  (options) => {
    if (!query.sysOrigin && options.length > 0) {
      query.sysOrigin = String(options[0]?.value || '');
    }
  },
  { immediate: true },
);

watch(
  [() => query.sysOrigin, () => query.countryCode, () => query.userId],
  () => {
    selectedUserIds.value = [];
  },
);

async function loadCountries() {
  countries.value = (await getCountryAlls()) || [];
}

async function loadData(reset = false, append = false) {
  if (!query.sysOrigin) {
    return;
  }
  if (!query.countryCode) {
    message.warning('请选择国家');
    return;
  }
  if (reset) {
    query.cursor = 1;
    list.value = [];
    total.value = 0;
    selectedUserIds.value = [];
  }
  loading.value = true;
  try {
    const result = await pageManualSalary({ ...query });
    const records = result.records || [];
    list.value = append ? [...list.value, ...records] : records;
    total.value = Number(result.total || 0);
    sortLoadedRows();
  } finally {
    loading.value = false;
  }
}

async function loadNextPage() {
  if (loading.value || !hasMore.value) {
    return;
  }
  const previousCursor = query.cursor;
  query.cursor = previousCursor + 1;
  try {
    await loadData(false, true);
  } catch (error) {
    query.cursor = previousCursor;
    throw error;
  }
}

function formatMoney(value?: number | string) {
  const amount = Number(value || 0);
  if (Number.isNaN(amount)) {
    return '$0.00';
  }
  return `$${amount.toFixed(2)}`;
}

function formatInteger(value?: number | string) {
  if (value === undefined || value === null || value === '') {
    return '-';
  }
  return Number(value).toLocaleString('en-US');
}

function countryLabel(code?: string) {
  const country = countries.value.find((item) => item.alphaTwo === code);
  if (!country) {
    return code || '-';
  }
  return `${country.phonePrefix || ''} ${country.countryName || country.aliasName || code}`;
}

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

function getSalarySortValue(
  record: Record<string, any>,
  key: SalarySortKey,
) {
  const value = Number(record?.[key] || 0);
  return Number.isFinite(value) ? value : 0;
}

function isSalarySortableColumn(key?: number | string) {
  return salarySortableKeys.has(String(key || '') as SalarySortKey);
}

function salarySortIndicator(key?: number | string) {
  if (salarySortKey.value !== String(key || '') || !salarySortOrder.value) {
    return '排序';
  }
  return salarySortOrder.value === 'descend' ? '降序' : '升序';
}

function sortLoadedRows() {
  if (!salarySortKey.value || !salarySortOrder.value) {
    return;
  }
  const sortKey = salarySortKey.value;
  const direction = salarySortOrder.value === 'ascend' ? 1 : -1;
  list.value = [...list.value].sort((left, right) => {
    const diff =
      getSalarySortValue(left, sortKey) - getSalarySortValue(right, sortKey);
    if (diff !== 0) {
      return diff * direction;
    }
    return getRowKey(left).localeCompare(getRowKey(right));
  });
}

function toggleSalarySort(key?: number | string) {
  if (!isSalarySortableColumn(key)) {
    return;
  }
  const nextKey = String(key) as SalarySortKey;
  if (salarySortKey.value !== nextKey) {
    salarySortKey.value = nextKey;
    salarySortOrder.value = 'descend';
  } else if (salarySortOrder.value === 'descend') {
    salarySortOrder.value = 'ascend';
  } else if (salarySortOrder.value === 'ascend') {
    salarySortKey.value = '';
    salarySortOrder.value = '';
  } else {
    salarySortOrder.value = 'descend';
  }
  query.sortField = salarySortKey.value;
  query.sortOrder = salarySortOrder.value;
  void loadData(true);
}

async function submitManualSalary(userIds?: string[]) {
  const hasSelectedUsers = !!userIds?.length;
  resultRows.value = await confirmManualSalary({
    countryCode: query.countryCode,
    sysOrigin: query.sysOrigin,
    ...(hasSelectedUsers ? { userIds } : {}),
  });
  resultOpen.value = true;
  selectedUserIds.value = [];
  await loadData(true);
}

function confirmPay() {
  if (!query.countryCode) {
    message.warning('请选择国家');
    return;
  }

  const userIds = [...selectedUserIds.value];
  const hasSelectedUsers = userIds.length > 0;

  Modal.confirm({
    content: hasSelectedUsers
      ? '本次只发放已勾选的用户。'
      : '未勾选用户，本次将发放当前筛选国家的所有可发工资用户。',
    title: hasSelectedUsers
      ? `确认发放已选择的 ${userIds.length} 人当前账期工资？`
      : `确认发放 ${countryLabel(query.countryCode)} 当前账期工资？`,
    async onOk() {
      paying.value = true;
      try {
        await submitManualSalary(hasSelectedUsers ? userIds : undefined);
        message.success('发放成功');
      } finally {
        paying.value = false;
      }
    },
  });
}

function settleUser(record: Record<string, any>) {
  if (!query.countryCode) {
    message.warning('请选择国家');
    return;
  }
  const userId = String(record.userId || '');
  if (!userId) {
    message.warning('用户ID为空');
    return;
  }
  const payableSalary = Number(record.payableSalary || 0);
  Modal.confirm({
    content: payableSalary < 0
      ? '该用户应发小于实收，本次发放0并置为已结算，不会对用户扣款。'
      : '本次只结算当前这一行用户的工资。',
    title: `确认结算用户 ${record.userProfile?.account || userId} 的当前账期工资？`,
    async onOk() {
      settlingUserId.value = userId;
      try {
        await submitManualSalary([userId]);
        message.success('结算成功');
      } finally {
        settlingUserId.value = '';
      }
    },
  });
}

void loadCountries();
</script>

<template>
  <Page
    auto-content-height
    content-class="manual-salary-page-content"
    title="工资发放"
  >
    <div class="manual-salary-page">
      <Card class="manual-salary-filter-card">
        <Space wrap>
          <SysOriginSelect
            v-model:value="query.sysOrigin"
            :options="sysOriginOptions"
            style="width: 140px"
          />
          <Select
            v-model:value="query.countryCode"
            allow-clear
            show-search
            :filter-option="false"
            option-label-prop="label"
            placeholder="国家"
            style="width: 240px"
            :options="filteredCountries.map((item) => ({
              label: `${item.phonePrefix || ''} ${item.countryName || item.aliasName || ''}`,
              value: item.alphaTwo as any,
            }))"
            @change="loadData(true)"
            @search="countryKeyword = $event"
          />
          <AccountInput
            v-model:value="query.userId"
            :sys-origin="query.sysOrigin"
            placeholder="用户ID"
            style="width: 260px"
          />
          <Button :loading="loading" type="primary" @click="loadData(true)">
            搜索
          </Button>
          <Button
            danger
            :disabled="!query.countryCode"
            :loading="paying"
            @click="confirmPay"
          >
            {{ confirmButtonText }}
          </Button>
        </Space>
      </Card>

      <AdminConfigTable
        auto-height
        :columns="columns"
        :current="query.cursor"
        :data-source="tableRows"
        :has-more="hasMore"
        infinite
        :loading="loading"
        :page-size="query.limit"
        row-key="rowKey"
        :row-selection="rowSelection"
        :scroll-x="2340"
        :show-pager="false"
        :summary-text="summaryText"
        :total="total"
        @load-more="loadNextPage"
      >
        <template #headerCell="{ column }">
          <button
            v-if="isSalarySortableColumn(column.key)"
            class="salary-sort-header"
            :class="{ 'salary-sort-header--active': salarySortKey === column.key }"
            type="button"
            @click="toggleSalarySort(column.key)"
          >
            <span>{{ column.title }}</span>
            <span class="salary-sort-state">
              {{ salarySortIndicator(column.key) }}
            </span>
          </button>
          <template v-else>
            {{ column.title }}
          </template>
        </template>
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'userProfile'">
            <UserProfileLink :profile="record.userProfile" />
          </template>
          <template v-else-if="column.key === 'countryCode'">
            {{ record.countryCode || '-' }}
          </template>
          <template v-else-if="column.key === 'lastSettlementTarget'">
            {{ formatInteger(record.lastSettlementTarget) }}
          </template>
          <template v-else-if="column.key === 'currentTarget'">
            {{ formatInteger(record.currentTarget) }}
          </template>
          <template v-else-if="column.key === 'policyLevel'">
            <Tag v-if="record.policyLevel" color="blue">
              {{ record.policyLevel }}
            </Tag>
            <span v-else>-</span>
          </template>
          <template v-else-if="column.key === 'expectedSalary'">
            {{ formatMoney(record.expectedSalary) }}
          </template>
          <template v-else-if="column.key === 'expectedMemberSalary'">
            {{ formatMoney(record.expectedMemberSalary) }}
          </template>
          <template v-else-if="column.key === 'expectedAgentSalary'">
            {{ formatMoney(record.expectedAgentSalary) }}
          </template>
          <template v-else-if="column.key === 'payableMemberSalary'">
            <span
              :class="{ 'payable-salary-negative': Number(record.payableMemberSalary || 0) < 0 }"
            >
              {{ formatMoney(record.payableMemberSalary) }}
            </span>
          </template>
          <template v-else-if="column.key === 'payableAgentSalary'">
            <span
              :class="{ 'payable-salary-negative': Number(record.payableAgentSalary || 0) < 0 }"
            >
              {{ formatMoney(record.payableAgentSalary) }}
            </span>
          </template>
          <template v-else-if="column.key === 'payableSalary'">
            <Space size="small">
              <span
                :class="{ 'payable-salary-negative': Number(record.payableSalary || 0) < 0 }"
              >
                {{ formatMoney(record.payableSalary) }}
              </span>
              <Tag v-if="record.paid" color="green">已结算</Tag>
            </Space>
          </template>
          <template v-else-if="column.key === 'memberIssuedSalary'">
            <span>{{ formatMoney(record.memberIssuedSalary) }}</span>
            <span
              v-if="Number(record.memberOverIssuedSalary || 0) > 0"
              class="over-issued-salary"
            >
              ({{ formatMoney(record.memberOverIssuedSalary) }})
            </span>
          </template>
          <template v-else-if="column.key === 'agentIssuedSalary'">
            <span>{{ formatMoney(record.agentIssuedSalary) }}</span>
            <span
              v-if="Number(record.agentOverIssuedSalary || 0) > 0"
              class="over-issued-salary"
            >
              ({{ formatMoney(record.agentOverIssuedSalary) }})
            </span>
          </template>
          <template v-else-if="column.key === 'totalIssuedSalary'">
            <span>{{ formatMoney(record.totalIssuedSalary) }}</span>
            <span
              v-if="Number(record.overIssuedSalary || 0) > 0"
              class="over-issued-salary"
            >
              ({{ formatMoney(record.overIssuedSalary) }})
            </span>
          </template>
          <template v-else-if="column.key === 'currentSalaryBalance'">
            {{ formatMoney(record.currentSalaryBalance) }}
          </template>
          <template v-else-if="column.key === 'action'">
            <Button
              :disabled="!record.userId || record.paid"
              :loading="settlingUserId === String(record.userId || '')"
              size="small"
              type="primary"
              @click="settleUser(record)"
            >
              结算
            </Button>
          </template>
        </template>
      </AdminConfigTable>
    </div>

    <Modal
      v-model:open="resultOpen"
      :footer="null"
      title="发放结果"
      width="980px"
    >
      <Table
        :columns="resultColumns"
        :data-source="resultRows"
        :pagination="false"
        row-key="id"
        size="small"
        :scroll="{ x: 900, y: 520 }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'userProfile'">
            <UserProfileLink :profile="record.userProfile" />
          </template>
          <template v-else-if="column.key === 'salaryChange'">
            {{ formatMoney(record.beforeSalaryBalance) }} -> {{ formatMoney(record.afterSalaryBalance) }}
          </template>
          <template v-else-if="column.key === 'issuedSalary'">
            {{ formatMoney(record.issuedSalary) }}
          </template>
          <template v-else-if="column.key === 'policyLevel'">
            <Tag color="blue">{{ record.policyLevel || '-' }}</Tag>
          </template>
          <template v-else-if="column.key === 'currentTarget'">
            {{ formatInteger(record.currentTarget) }}
          </template>
        </template>
      </Table>
    </Modal>
  </Page>
</template>

<style scoped>
.manual-salary-page {
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: 100%;
  min-height: 0;
}

.manual-salary-filter-card {
  flex: 0 0 auto;
}

.salary-sort-header {
  align-items: center;
  background: transparent;
  border: 0;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  gap: 6px;
  max-width: 100%;
  padding: 0;
  text-align: left;
}

.salary-sort-header:hover,
.salary-sort-header--active {
  color: rgb(22 119 255);
}

.salary-sort-state {
  color: rgb(102 112 133);
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 400;
}

.salary-sort-header--active .salary-sort-state {
  color: rgb(22 119 255);
}

.over-issued-salary {
  color: rgb(217 45 32);
  margin-left: 4px;
}

.payable-salary-negative {
  color: rgb(217 45 32);
  font-weight: 600;
}
</style>
