<template>
  <el-config-provider>
    <main class="app-shell">
      <aside class="sidebar">
        <div class="brand">
          <div class="brand-mark">棋</div>
          <div>
            <h1>自助棋牌室</h1>
            <p>运营后台</p>
          </div>
        </div>
        <nav class="nav-list" aria-label="后台模块">
          <button class="nav-item active" type="button">
            <Sparkles :size="18" />
            <span>保洁运营</span>
          </button>
          <button class="nav-item" type="button" disabled>
            <Store :size="18" />
            <span>门店</span>
          </button>
          <button class="nav-item" type="button" disabled>
            <RadioTower :size="18" />
            <span>设备</span>
          </button>
          <button class="nav-item" type="button" disabled>
            <WalletCards :size="18" />
            <span>支付</span>
          </button>
        </nav>
      </aside>

      <section class="workspace">
        <header class="topbar">
          <div>
            <p class="eyebrow">M08-B</p>
            <h2>保洁任务与结算</h2>
          </div>
          <div class="token-box">
            <el-input
              v-model="tokenDraft"
              type="password"
              show-password
              placeholder="后台访问令牌"
              autocomplete="off"
              @keyup.enter="saveToken"
            />
            <el-tooltip content="保存令牌" placement="bottom">
              <el-button :icon="Save" type="primary" @click="saveToken" />
            </el-tooltip>
          </div>
        </header>

        <section class="metric-grid" aria-label="保洁概览">
          <div class="metric">
            <span>待验收</span>
            <strong>{{ statistics.summary.pendingReview }}</strong>
          </div>
          <div class="metric">
            <span>已完成</span>
            <strong>{{ statistics.summary.completed }}</strong>
          </div>
          <div class="metric">
            <span>待发放</span>
            <strong>{{ money(statistics.summary.confirmedSettlementCents) }}</strong>
          </div>
          <div class="metric">
            <span>待结算</span>
            <strong>{{ money(statistics.summary.pendingSettlementCents) }}</strong>
          </div>
        </section>

        <section class="action-board" aria-label="运营待处理">
          <button class="action-tile" type="button" @click="jumpToTaskStatus('SUBMITTED')">
            <ClipboardCheck :size="20" />
            <span>待验收任务</span>
            <strong>{{ statistics.summary.pendingReview }}</strong>
          </button>
          <button class="action-tile" type="button" @click="jumpToTaskStatus('REJECTED')">
            <RotateCcw :size="20" />
            <span>驳回补做</span>
            <strong>{{ statistics.summary.rejected }}</strong>
          </button>
          <button class="action-tile" type="button" @click="jumpToSettlementStatus('DRAFT')">
            <ListTodo :size="20" />
            <span>待确认结算</span>
            <strong>{{ draftSettlementTotal }}</strong>
          </button>
          <button class="action-tile" type="button" @click="jumpToSettlementStatus('CONFIRMED')">
            <Send :size="20" />
            <span>待发放金额</span>
            <strong>{{ money(statistics.summary.confirmedSettlementCents) }}</strong>
          </button>
          <button class="action-tile" type="button" @click="exportOperationalQueue">
            <Download :size="20" />
            <span>导出待处理</span>
            <strong>{{ operationalQueueTotal }}</strong>
          </button>
        </section>

        <el-alert
          v-if="lastError"
          class="alert-line"
          :title="lastError"
          type="error"
          show-icon
          :closable="true"
          @close="lastError = ''"
        />
        <el-alert
          v-if="lastMessage"
          class="alert-line"
          :title="lastMessage"
          type="success"
          show-icon
          :closable="true"
          @close="lastMessage = ''"
        />

        <el-tabs v-model="activeTab" class="work-tabs">
          <el-tab-pane label="任务" name="tasks">
            <CleaningTasksPanel
              :session="session"
              :loading="loading.tasks"
              :items="tasks.items"
              :cleaners="cleaners.items"
              :total="tasks.total"
              :page="tasks.page"
              :page-size="tasks.pageSize"
              :status="taskStatus"
              :filters="taskFilters"
              @refresh="loadTasks"
              @status-change="changeTaskStatus"
              @filter="changeTaskFilters"
              @page-change="changeTaskPage"
              @assign="handleAssign"
              @complete="handleComplete"
              @complete-many="handleCompleteMany"
              @reject="handleReject"
              @reject-many="handleRejectMany"
              @reclaim="handleReclaim"
            />
          </el-tab-pane>
          <el-tab-pane label="结算" name="settlements">
            <CleaningSettlementsPanel
              :session="session"
              :loading="loading.settlements"
              :items="settlements.items"
              :cleaners="cleaners.items"
              :total="settlements.total"
              :page="settlements.page"
              :page-size="settlements.pageSize"
              :status="settlementStatus"
              :filters="settlementFilters"
              @refresh="loadSettlements"
              @status-change="changeSettlementStatus"
              @filter="changeSettlementFilters"
              @page-change="changeSettlementPage"
              @generate="handleGenerateSettlement"
              @confirm="handleConfirmSettlement"
              @transfer="handleTransfer"
              @sync-transfer="handleSyncTransfer"
              @sync-transfer-many="handleSyncTransferMany"
              @failure="handleFailure"
            />
          </el-tab-pane>
          <el-tab-pane label="统计" name="statistics">
            <CleaningStatisticsPanel
              :loading="loading.statistics"
              :statistics="statistics"
              :filters="statisticsFilters"
              :cleaners="cleaners.items"
              @refresh="loadStatistics"
              @filter="changeStatisticsFilters"
            />
          </el-tab-pane>
          <el-tab-pane label="保洁员" name="cleaners">
            <CleanersPanel
              :loading="loading.cleaners"
              :items="cleaners.items"
              :total="cleaners.total"
              :page="cleaners.page"
              :page-size="cleaners.pageSize"
              :status="cleanerStatus"
              :search="cleanerSearch"
              @refresh="loadCleaners"
              @status-change="changeCleanerStatus"
              @search-change="changeCleanerSearch"
              @page-change="changeCleanerPage"
              @create="handleCreateCleaner"
              @update="handleUpdateCleaner"
              @status-toggle="handleToggleCleanerStatus"
              @reset-sessions="handleResetCleanerSessions"
            />
          </el-tab-pane>
          <el-tab-pane label="联调" name="handoff">
            <CleaningFieldHandoffPanel />
          </el-tab-pane>
        </el-tabs>
      </section>
    </main>
  </el-config-provider>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import {
  ClipboardCheck,
  Download,
  ListTodo,
  RadioTower,
  RotateCcw,
  Save,
  Send,
  Sparkles,
  Store,
  WalletCards
} from '@lucide/vue';
import CleaningTasksPanel from './components/CleaningTasksPanel.vue';
import CleaningSettlementsPanel from './components/CleaningSettlementsPanel.vue';
import CleaningStatisticsPanel from './components/CleaningStatisticsPanel.vue';
import CleanersPanel from './components/CleanersPanel.vue';
import CleaningFieldHandoffPanel from './components/CleaningFieldHandoffPanel.vue';
import {
  ApiError,
  assignCleaningTask,
  completeCleaningTask,
  confirmCleaningSettlement,
  createStaffUser,
  executeWechatTransfer,
  generateCleaningSettlement,
  getCleaningStatistics,
  listCleaningSettlements,
  listCleaningTasks,
  listStaffUsers,
  reclaimCleaningTimeouts,
  recordPayoutFailure,
  rejectCleaningTask,
  resetStaffSessions,
  syncWechatTransfer,
  updateStaffUser
} from './api';
import type {
  CleaningSettlement,
  CleaningStatistics,
  CleaningTask,
  ManagedUser,
  PageResult,
  PayoutStateFilter,
  SettlementStatus,
  TaskStatus,
  TransferMode,
  UserStatus
} from './types';
import { money } from './format';

const tokenDraft = ref(localStorage.getItem('qipai.admin.token') || '');
const activeTab = ref('tasks');
const lastError = ref('');
const lastMessage = ref('');
const taskStatus = ref<TaskStatus | ''>('SUBMITTED');
const settlementStatus = ref<SettlementStatus | ''>('CONFIRMED');
const cleanerStatus = ref<UserStatus | ''>('ACTIVE');
const cleanerSearch = ref('');
const session = computed(() => ({ token: tokenDraft.value }));
const loading = reactive({ tasks: false, settlements: false, statistics: false, cleaners: false });
const tasks = reactive<PageResult<CleaningTask>>({ items: [], total: 0, page: 1, pageSize: 20 });
const settlements = reactive<PageResult<CleaningSettlement>>({
  items: [],
  total: 0,
  page: 1,
  pageSize: 20
});
const cleaners = reactive<PageResult<ManagedUser>>({ items: [], total: 0, page: 1, pageSize: 20 });
const taskFilters = reactive({ storeId: '', cleanerUserId: '' });
const settlementFilters = reactive<{ storeId: string; cleanerUserId: string; payoutState: PayoutStateFilter | '' }>({
  storeId: '',
  cleanerUserId: '',
  payoutState: ''
});
const statisticsFilters = reactive({ from: '', to: '', storeId: '', cleanerUserId: '' });
const statistics = reactive<CleaningStatistics>({
  summary: {
    taskTotal: 0,
    pendingReview: 0,
    active: 0,
    rejected: 0,
    completed: 0,
    rewardCents: 0,
    pendingSettlementCents: 0,
    confirmedSettlementCents: 0,
    paidSettlementCents: 0
  },
  byStatus: [],
  byStore: [],
  settlements: [],
  members: [],
  trend: []
});
const draftSettlementTotal = computed(() => statistics.settlements
  .find((item) => item.status === 'DRAFT')?.total || 0);
const operationalQueueTotal = computed(() => (
  statistics.summary.pendingReview
  + statistics.summary.rejected
  + draftSettlementTotal.value
));

function saveToken() {
  localStorage.setItem('qipai.admin.token', tokenDraft.value.trim());
  ElMessage.success('已保存');
}

async function runAction(work: () => Promise<void>, success: string) {
  lastError.value = '';
  lastMessage.value = '';
  try {
    await work();
    lastMessage.value = success;
    ElMessage.success(success);
  } catch (error) {
    lastError.value = error instanceof ApiError
      ? `${error.code}${error.traceId ? ` · ${error.traceId}` : ''}`
      : error instanceof Error ? error.message : '操作失败';
  }
}

async function loadTasks() {
  loading.tasks = true;
  await runAction(async () => {
    const result = await listCleaningTasks(session.value, {
      page: tasks.page,
      pageSize: tasks.pageSize,
      status: taskStatus.value || undefined,
      storeId: taskFilters.storeId || undefined,
      cleanerUserId: taskFilters.cleanerUserId || undefined
    });
    Object.assign(tasks, result);
  }, '任务已刷新');
  loading.tasks = false;
}

async function loadSettlements() {
  loading.settlements = true;
  await runAction(async () => {
    const result = await listCleaningSettlements(session.value, {
      page: settlements.page,
      pageSize: settlements.pageSize,
      status: settlementStatus.value || undefined,
      payoutState: settlementFilters.payoutState || undefined,
      storeId: settlementFilters.storeId || undefined,
      cleanerUserId: settlementFilters.cleanerUserId || undefined
    });
    Object.assign(settlements, result);
  }, '结算已刷新');
  loading.settlements = false;
}

async function loadStatistics() {
  loading.statistics = true;
  await runAction(async () => {
    const result = await getCleaningStatistics(session.value, {
      from: statisticsFilters.from || undefined,
      to: statisticsFilters.to || undefined,
      storeId: statisticsFilters.storeId || undefined,
      cleanerUserId: statisticsFilters.cleanerUserId || undefined
    });
    Object.assign(statistics.summary, result.summary);
    statistics.byStatus = result.byStatus;
    statistics.byStore = result.byStore;
    statistics.settlements = result.settlements;
    statistics.members = result.members;
    statistics.trend = result.trend;
  }, '统计已刷新');
  loading.statistics = false;
}

async function loadCleaners() {
  loading.cleaners = true;
  await runAction(async () => {
    const result = await listStaffUsers(session.value, {
      page: cleaners.page,
      pageSize: cleaners.pageSize,
      role: 'CLEANER',
      status: cleanerStatus.value || undefined,
      search: cleanerSearch.value || undefined
    });
    Object.assign(cleaners, {
      items: result.items,
      total: result.total,
      page: cleaners.page,
      pageSize: cleaners.pageSize
    });
  }, '保洁员已刷新');
  loading.cleaners = false;
}

function changeTaskStatus(status: TaskStatus | '') {
  taskStatus.value = status;
  tasks.page = 1;
  void loadTasks();
}

function jumpToTaskStatus(status: TaskStatus) {
  activeTab.value = 'tasks';
  taskStatus.value = status;
  tasks.page = 1;
  void loadTasks();
}

function changeTaskFilters(input: { storeId: string; cleanerUserId: string }) {
  Object.assign(taskFilters, input);
  tasks.page = 1;
  void loadTasks();
}

function changeSettlementStatus(status: SettlementStatus | '') {
  settlementStatus.value = status;
  settlements.page = 1;
  void loadSettlements();
}

function jumpToSettlementStatus(status: SettlementStatus) {
  activeTab.value = 'settlements';
  settlementStatus.value = status;
  settlementFilters.payoutState = '';
  settlements.page = 1;
  void loadSettlements();
}

function exportOperationalQueue() {
  downloadCsv(`cleaning-operational-queue-${Date.now()}.csv`, [
    ['队列', '数量', '金额', '入口'],
    ['待验收任务', String(statistics.summary.pendingReview), '', '任务/SUBMITTED'],
    ['驳回补做', String(statistics.summary.rejected), '', '任务/REJECTED'],
    ['待确认结算', String(draftSettlementTotal.value), '', '结算/DRAFT'],
    ['待发放金额', '', money(statistics.summary.confirmedSettlementCents), '结算/CONFIRMED'],
    ['待结算金额', '', money(statistics.summary.pendingSettlementCents), '统计/待结算'],
    ['已完成任务', String(statistics.summary.completed), '', '统计/已完成']
  ]);
}

function downloadCsv(filename: string, rows: string[][]) {
  const content = rows.map((row) => row.map(csvCell).join(',')).join('\r\n');
  const blob = new Blob([`\uFEFF${content}`], { type: 'text/csv;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  link.click();
  URL.revokeObjectURL(url);
}

function csvCell(value: string) {
  const normalized = value.replace(/\r?\n/g, ' ');
  return /[",\r\n]/.test(normalized) ? `"${normalized.replace(/"/g, '""')}"` : normalized;
}

function changeSettlementFilters(input: { storeId: string; cleanerUserId: string; payoutState: PayoutStateFilter | '' }) {
  Object.assign(settlementFilters, input);
  settlements.page = 1;
  void loadSettlements();
}

function changeTaskPage(page: number) {
  tasks.page = page;
  void loadTasks();
}

function changeSettlementPage(page: number) {
  settlements.page = page;
  void loadSettlements();
}

function changeStatisticsFilters(input: { from: string; to: string; storeId: string; cleanerUserId: string }) {
  Object.assign(statisticsFilters, input);
  void loadStatistics();
}

function changeCleanerStatus(status: UserStatus | '') {
  cleanerStatus.value = status;
  cleaners.page = 1;
  void loadCleaners();
}

function changeCleanerSearch(search: string) {
  cleanerSearch.value = search;
  cleaners.page = 1;
  void loadCleaners();
}

function changeCleanerPage(page: number) {
  cleaners.page = page;
  void loadCleaners();
}

async function handleAssign(input: { taskId: string; cleanerUserId: string; note?: string }) {
  await runAction(async () => {
    await assignCleaningTask(session.value, input.taskId, input);
    await Promise.all([loadTasks(), loadStatistics()]);
  }, '已指派');
}

async function handleComplete(input: { taskId: string; note?: string }) {
  await runAction(async () => {
    await completeCleaningTask(session.value, input.taskId, input.note);
    await Promise.all([loadTasks(), loadStatistics()]);
  }, '已验收');
}

async function handleCompleteMany(input: { taskIds: string[]; note?: string }) {
  await runAction(async () => {
    for (const taskId of input.taskIds) {
      await completeCleaningTask(session.value, taskId, input.note);
    }
    await Promise.all([loadTasks(), loadStatistics()]);
  }, `已批量验收 ${input.taskIds.length} 个任务`);
}

async function handleReject(input: { taskId: string; reason: string }) {
  await runAction(async () => {
    await rejectCleaningTask(session.value, input.taskId, input.reason);
    await Promise.all([loadTasks(), loadStatistics()]);
  }, '已驳回');
}

async function handleRejectMany(input: { taskIds: string[]; reason: string }) {
  await runAction(async () => {
    for (const taskId of input.taskIds) {
      await rejectCleaningTask(session.value, taskId, input.reason);
    }
    await Promise.all([loadTasks(), loadStatistics()]);
  }, `已批量驳回 ${input.taskIds.length} 个任务`);
}

async function handleReclaim(input: { olderThanMinutes: number; limit: number }) {
  await runAction(async () => {
    await reclaimCleaningTimeouts(session.value, input);
    await Promise.all([loadTasks(), loadStatistics()]);
  }, '已回收超时任务');
}

async function handleGenerateSettlement(
  input: { cleanerUserId: string; storeId?: string; note?: string }
) {
  await runAction(async () => {
    await generateCleaningSettlement(session.value, input);
    await Promise.all([loadTasks(), loadSettlements(), loadStatistics()]);
  }, '已生成结算单');
}

async function handleConfirmSettlement(input: { settlementId: string; note?: string }) {
  await runAction(async () => {
    await confirmCleaningSettlement(session.value, input.settlementId, input.note);
    await Promise.all([loadSettlements(), loadStatistics()]);
  }, '已确认结算单');
}

async function handleTransfer(input: { settlementId: string; mode: TransferMode; note?: string }) {
  await runAction(async () => {
    await executeWechatTransfer(session.value, input.settlementId, {
      mode: input.mode,
      note: input.note
    });
    await Promise.all([loadSettlements(), loadStatistics()]);
  }, '已提交微信转账');
}

async function handleSyncTransfer(input: { settlementId: string; note?: string }) {
  await runAction(async () => {
    await syncWechatTransfer(session.value, input.settlementId, input.note);
    await Promise.all([loadSettlements(), loadStatistics()]);
  }, '已同步微信状态');
}

async function handleSyncTransferMany(input: { settlementIds: string[]; note?: string }) {
  await runAction(async () => {
    for (const settlementId of input.settlementIds) {
      await syncWechatTransfer(session.value, settlementId, input.note);
    }
    await Promise.all([loadSettlements(), loadStatistics()]);
  }, `已批量同步 ${input.settlementIds.length} 个结算单`);
}

async function handleFailure(
  input: { settlementId: string; error: string; payoutReference?: string; note?: string }
) {
  await runAction(async () => {
    await recordPayoutFailure(session.value, input.settlementId, {
      error: input.error,
      payoutChannel: 'WECHAT_TRANSFER',
      payoutReference: input.payoutReference,
      note: input.note
    });
    await Promise.all([loadSettlements(), loadStatistics()]);
  }, '已记录失败');
}

async function handleCreateCleaner(
  input: { nickname: string; phone: string; storeIds: string[]; note?: string }
) {
  await runAction(async () => {
    await createStaffUser(session.value, {
      nickname: input.nickname,
      phone: input.phone,
      roles: ['CLEANER'],
      storeIds: input.storeIds,
      note: input.note
    });
    await loadCleaners();
  }, '已新增保洁员');
}

async function handleUpdateCleaner(
  input: { userId: string; nickname: string; phone?: string; storeIds: string[]; note?: string }
) {
  await runAction(async () => {
    await updateStaffUser(session.value, input.userId, {
      nickname: input.nickname,
      phone: input.phone,
      roles: ['CLEANER'],
      storeIds: input.storeIds,
      note: input.note
    });
    await loadCleaners();
  }, '已更新保洁员');
}

async function handleToggleCleanerStatus(input: { userId: string; status: UserStatus }) {
  await runAction(async () => {
    await updateStaffUser(session.value, input.userId, { status: input.status });
    await loadCleaners();
  }, input.status === 'ACTIVE' ? '已启用保洁员' : '已停用保洁员');
}

async function handleResetCleanerSessions(userId: string) {
  await runAction(async () => {
    await resetStaffSessions(session.value, userId);
    await loadCleaners();
  }, '已重置保洁员会话');
}

onMounted(() => {
  if (session.value.token) {
    void Promise.all([loadTasks(), loadSettlements(), loadStatistics(), loadCleaners()]);
  }
});
</script>
