<template>
    <div class="default-main ba-table-box">
        <el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />

        <TableHeader
            :buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
            :quick-search-placeholder="t('Quick search placeholder', { fields: t('channel.quick Search Fields') })"
        ></TableHeader>
        <div class="channel-top-actions">
            <div class="channel-stats-cards">
                <el-card shadow="never" class="channel-stat-card">
                    <div class="label">{{ t('channel.settle_stats_channel_total') }}</div>
                    <div class="value">{{ settleStats.channel_total }}</div>
                </el-card>
                <el-card shadow="never" class="channel-stat-card">
                    <div class="label">{{ t('channel.settle_stats_enabled') }}</div>
                    <div class="value">{{ settleStats.enabled_count }}</div>
                </el-card>
                <el-card shadow="never" class="channel-stat-card">
                    <div class="label">{{ t('channel.settle_stats_pending_dividend') }}</div>
                    <div class="value">{{ settleStats.carryover_positive_count }}</div>
                </el-card>
                <el-card shadow="never" class="channel-stat-card">
                    <div class="label">{{ t('channel.settle_stats_pending_amount') }}</div>
                    <div class="value">{{ settleStats.carryover_positive_total }}</div>
                </el-card>
                <el-card
                    shadow="never"
                    class="channel-stat-card"
                    :class="{ 'channel-stat-card-clickable': auth('index') }"
                    @click="onCompanyTotalBetCardClick"
                >
                    <div class="label">{{ t('channel.settle_stats_company_total_bet') }}</div>
                    <div class="value">{{ settleStats.company_total_bet_amount }}</div>
                </el-card>
                <el-card
                    shadow="never"
                    class="channel-stat-card"
                    :class="{ 'channel-stat-card-clickable': auth('index') }"
                    @click="onPaidDividendCardClick"
                >
                    <div class="label">{{ t('channel.settle_stats_paid_dividend') }}</div>
                    <div class="value">{{ settleStats.paid_dividend_total }}</div>
                </el-card>
            </div>
            <div class="channel-action-row">
                <el-radio-group v-model="settleFilterMode" size="small" @change="onSettleFilterChange">
                    <el-radio-button label="all">{{ t('channel.settle_filter_all') }}</el-radio-button>
                    <el-radio-button label="with_balance">{{ t('channel.settle_filter_with_balance') }}</el-radio-button>
                    <el-radio-button label="no_balance">{{ t('channel.settle_filter_no_balance') }}</el-radio-button>
                    <el-radio-button label="enabled">{{ t('channel.settle_filter_enabled') }}</el-radio-button>
                    <el-radio-button label="disabled">{{ t('channel.settle_filter_disabled') }}</el-radio-button>
                </el-radio-group>
                <el-button v-if="auth('batchSettlePending')" type="warning" @click="onBatchSettlePending">
                    {{ t('channel.batch_settle_pending') }}
                </el-button>
            </div>
        </div>

        <Table ref="tableRef"></Table>

        <PopupForm />

        <el-dialog
            class="manual-settle-dialog"
            :close-on-click-modal="false"
            :model-value="manualSettle.visible"
            :width="manualSettleDialogWidth"
            align-center
            append-to-body
            destroy-on-close
            @close="closeManualSettleDialog"
            @opened="dismissFloatingTooltips"
        >
            <template #header>
                <div class="title">{{ t('channel.manual_settle') }}</div>
            </template>
            <div v-loading="manualSettle.previewLoading" class="manual-settle-dialog-body">
                <el-descriptions
                    class="manual-settle-summary"
                    :column="manualSettleSummaryColumns"
                    border
                    :size="manualSettleViewportMobile ? 'small' : 'default'"
                >
                    <el-descriptions-item :label="t('channel.manual_settle_settlement_no')">
                        {{ manualSettle.form.settlement_no || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_period_start')">
                        {{ manualSettle.form.period_start_at || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_period_end')">
                        {{ manualSettle.form.period_end_at || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_total_bet')">
                        {{ manualSettle.form.total_bet_amount || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_total_payout')">
                        {{ manualSettle.form.total_payout_amount || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_platform_profit')">
                        {{ manualSettle.form.platform_profit_amount || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_commission_rate')">
                        {{ manualSettle.form.commission_rate || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_calc_base')">
                        {{ manualSettle.form.calc_base_amount || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item :label="t('channel.manual_settle_commission_amount')">
                        <span class="manual-settle-summary-highlight">{{ manualSettle.form.commission_amount || '-' }}</span>
                    </el-descriptions-item>
                </el-descriptions>

                <el-form
                    :model="manualSettle.form"
                    :label-width="manualSettleFormLabelWidth"
                    label-position="top"
                    :size="manualSettleFormSize"
                    class="manual-settle-form"
                >
                    <el-form-item :label="t('channel.share_config')" class="manual-settle-form-item-full manual-settle-split-form-item">
                        <div class="manual-settle-split-block">
                            <div
                                class="manual-settle-split-table-scroll"
                                :class="{ 'is-mobile': manualSettleViewportMobile }"
                            >
                                <div
                                    class="manual-settle-split-table-inner"
                                    :class="{ 'is-mobile': manualSettleViewportMobile }"
                                    :style="manualSettleSplitInnerStyle"
                                >
                                    <el-table
                                        :data="manualSettleSplitTree"
                                        row-key="admin_id"
                                        :tree-props="{ children: 'children' }"
                                        default-expand-all
                                        border
                                        :size="manualSettleTableSize"
                                        :fit="!manualSettleViewportMobile"
                                        class="manual-settle-split-table"
                                        :class="{ 'is-mobile': manualSettleViewportMobile, 'w100': !manualSettleViewportMobile }"
                                        :table-layout="manualSettleTableLayout"
                                    >
                                        <el-table-column
                                            prop="admin_username"
                                            :label="t('channel.admin__username')"
                                            :min-width="manualSettleViewportMobile ? undefined : manualSettleSplitCol.adminWidth"
                                            :width="manualSettleViewportMobile ? manualSettleSplitCol.adminWidth : undefined"
                                            :show-overflow-tooltip="!manualSettleViewportMobile"
                                        />
                                    <el-table-column
                                        prop="settlement_base_amount"
                                        :label="t('channel.manual_settle_col_base')"
                                        :width="manualSettleSplitCol.baseWidth"
                                        align="center"
                                        :formatter="formatSplitAmountCell"
                                    />
                                    <el-table-column
                                        prop="share_rate"
                                        :label="t('channel.manual_settle_col_share')"
                                        :width="manualSettleSplitCol.shareWidth"
                                        align="center"
                                    >
                                        <template #default="scope">{{ scope.row.share_rate }}%</template>
                                    </el-table-column>
                                    <el-table-column
                                        prop="commission_amount"
                                        :label="t('channel.manual_settle_col_gross')"
                                        :width="manualSettleSplitCol.grossWidth"
                                        align="center"
                                        :formatter="formatSplitAmountCell"
                                    />
                                    <el-table-column
                                        prop="commission_share_percent"
                                        :label="t('channel.manual_settle_col_commission_share')"
                                        :width="manualSettleSplitCol.commissionShareWidth"
                                        align="center"
                                    >
                                        <template #default="scope">{{ formatCommissionSharePercent(scope.row) }}</template>
                                    </el-table-column>
                                    <el-table-column
                                        prop="handling_fee"
                                        :label="t('channel.manual_settle_col_fee')"
                                        :width="manualSettleSplitCol.feeWidth"
                                        align="center"
                                        :formatter="formatSplitAmountCell"
                                    />
                                    <el-table-column
                                        :label="t('channel.manual_settle_col_net')"
                                        :width="manualSettleSplitCol.netWidth"
                                        align="center"
                                    >
                                        <template #default="scope">{{ formatNetCommission(scope.row) }}</template>
                                    </el-table-column>
                                    </el-table>
                                </div>
                                <p v-if="manualSettleViewportMobile" class="manual-settle-split-scroll-tip">
                                    {{ t('channel.manual_settle_split_scroll_tip') }}
                                </p>
                            </div>
                            <el-collapse v-model="manualSettleCalcCollapse" class="manual-settle-calc-collapse">
                                <el-collapse-item :title="t('channel.manual_settle_calc_title')" name="calc">
                                    <ul class="manual-settle-calc-list">
                                        <li v-for="(line, idx) in manualSettleCalcDescLines" :key="idx">{{ line }}</li>
                                    </ul>
                                </el-collapse-item>
                            </el-collapse>
                        </div>
                    </el-form-item>
                    <el-form-item :label="t('channel.manual_settle_remark')" class="manual-settle-form-item-full">
                        <el-input v-model="manualSettle.form.remark" type="textarea" :rows="2" />
                    </el-form-item>
                </el-form>
            </div>
            <template #footer>
                <div class="manual-settle-footer">
                    <el-button @click="closeManualSettleDialog">{{ t('Cancel') }}</el-button>
                    <el-button type="primary" :disabled="manualSettle.previewLoading" :loading="manualSettle.loading" @click="submitManualSettle">
                        {{ t('channel.manual_settle_submit') }}
                    </el-button>
                </div>
            </template>
        </el-dialog>

        <el-dialog
            class="channel-record-dialog"
            :close-on-click-modal="false"
            :model-value="dividendDialog.visible"
            width="92%"
            @close="closeDividendDialog"
        >
            <template #header>
                <div class="title">{{ t('channel.dividend_record_dialog_title') }}</div>
            </template>
            <div v-loading="dividendDialog.loading" class="channel-record-dialog__body">
                <div class="channel-record-table-wrap">
                <el-table :data="dividendDialog.list" border size="small" class="channel-record-table">
                    <el-table-column prop="settlement_no" :label="t('channel.dividend_settlement_no')" min-width="150" show-overflow-tooltip />
                    <el-table-column prop="channel_name" :label="t('channel.dividend_channel_name')" min-width="100" />
                    <el-table-column prop="admin_username" :label="t('channel.dividend_admin_username')" min-width="100" />
                    <el-table-column prop="commission_amount" :label="t('channel.dividend_commission_amount')" min-width="100" align="right" />
                    <el-table-column :label="t('channel.dividend_period_range')" min-width="180">
                        <template #default="scope">
                            {{ scope.row.period_start_at || '-' }} ~ {{ scope.row.period_end_at || '-' }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="settled_at" :label="t('channel.dividend_settled_at')" min-width="150" />
                </el-table>
                </div>
                <div class="channel-record-pagination">
                    <el-pagination
                        background
                        layout="total, prev, pager, next"
                        :total="dividendDialog.total"
                        :page-size="dividendDialog.limit"
                        :current-page="dividendDialog.page"
                        @current-change="onDividendPageChange"
                    />
                </div>
            </div>
        </el-dialog>

        <el-dialog
            class="channel-record-dialog channel-bet-record-dialog"
            :close-on-click-modal="false"
            :model-value="betRecordDialog.visible"
            width="92%"
            @close="closeBetRecordDialog"
        >
            <template #header>
                <div class="title">{{ betRecordDialog.title }}</div>
            </template>
            <div v-loading="betRecordDialog.loading" class="channel-record-dialog__body">
                <div class="channel-bet-summary">
                    <el-card shadow="never" class="channel-bet-summary-card channel-stat-card">
                        <div class="label">{{ t('channel.bet_record_summary_count') }}</div>
                        <div class="value">{{ betRecordDialog.summary.record_count }}</div>
                    </el-card>
                    <el-card shadow="never" class="channel-bet-summary-card channel-stat-card">
                        <div class="label">{{ t('channel.bet_record_summary_bet') }}</div>
                        <div class="value">{{ betRecordDialog.summary.total_bet_amount }}</div>
                    </el-card>
                    <el-card shadow="never" class="channel-bet-summary-card channel-stat-card">
                        <div class="label">{{ t('channel.bet_record_summary_win') }}</div>
                        <div class="value">{{ betRecordDialog.summary.total_win_amount }}</div>
                    </el-card>
                </div>
                <el-form :inline="true" size="small" class="channel-bet-filter" @submit.prevent="onBetRecordSearch">
                    <el-form-item :label="t('channel.bet_record_period_no')">
                        <el-input
                            v-model="betRecordDialog.filters.period_no"
                            clearable
                            :placeholder="t('Fuzzy query')"
                            class="channel-bet-filter-input"
                            @keyup.enter="onBetRecordSearch"
                        />
                    </el-form-item>
                    <el-form-item :label="t('channel.bet_record_user_username')">
                        <el-input
                            v-model="betRecordDialog.filters.user_keyword"
                            clearable
                            :placeholder="t('Fuzzy query')"
                            class="channel-bet-filter-input"
                            @keyup.enter="onBetRecordSearch"
                        />
                    </el-form-item>
                    <el-form-item :label="t('channel.bet_record_result_number')">
                        <el-input
                            v-model="betRecordDialog.filters.result_number"
                            clearable
                            class="channel-bet-filter-input--short"
                            @keyup.enter="onBetRecordSearch"
                        />
                    </el-form-item>
                    <el-form-item :label="t('channel.bet_record_pick_numbers')">
                        <el-input
                            v-model="betRecordDialog.filters.pick_number"
                            clearable
                            :placeholder="t('channel.bet_record_pick_filter_placeholder')"
                            class="channel-bet-filter-input--short"
                            @keyup.enter="onBetRecordSearch"
                        />
                    </el-form-item>
                    <el-form-item :label="t('channel.bet_record_win_hit')">
                        <el-select
                            v-model="betRecordDialog.filters.win_hit"
                            clearable
                            :placeholder="t('Please select field', { field: t('channel.bet_record_win_hit') })"
                            class="channel-bet-filter-select"
                        >
                            <el-option :label="t('channel.bet_record_win_hit_won')" value="won" />
                            <el-option :label="t('channel.bet_record_win_hit_lost')" value="lost" />
                            <el-option :label="t('channel.bet_record_win_hit_pending')" value="pending" />
                        </el-select>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="onBetRecordSearch">{{ t('Search') }}</el-button>
                        <el-button @click="onBetRecordReset">{{ t('Reset') }}</el-button>
                    </el-form-item>
                </el-form>
                <div class="channel-record-table-wrap">
                <el-table
                    :data="betRecordDialog.list"
                    border
                    size="small"
                    class="channel-bet-record-table channel-record-table"
                >
                    <el-table-column
                        prop="period_no"
                        :label="t('channel.bet_record_period_no')"
                        min-width="120"
                        align="center"
                        header-align="center"
                        show-overflow-tooltip
                    />
                    <el-table-column
                        prop="user_username"
                        :label="t('channel.bet_record_user_username')"
                        min-width="120"
                        align="center"
                        header-align="center"
                        show-overflow-tooltip
                    />
                    <el-table-column
                        v-if="betRecordDialog.mode === 'company'"
                        prop="channel_name"
                        :label="t('channel.bet_record_channel_name')"
                        min-width="100"
                        align="center"
                        header-align="center"
                        show-overflow-tooltip
                    />
                    <el-table-column
                        prop="pick_numbers"
                        :label="t('channel.bet_record_pick_numbers')"
                        min-width="120"
                        align="center"
                        header-align="center"
                        show-overflow-tooltip
                    />
                    <el-table-column
                        prop="result_number"
                        :label="t('channel.bet_record_result_number')"
                        min-width="90"
                        align="center"
                        header-align="center"
                    />
                    <el-table-column
                        :label="t('channel.bet_record_win_hit')"
                        min-width="90"
                        align="center"
                        header-align="center"
                    >
                        <template #default="scope">
                            <el-tag
                                v-if="scope.row.win_hit"
                                :type="betRecordWinHitTagType(scope.row.win_hit)"
                                effect="dark"
                                size="small"
                            >
                                {{ formatBetRecordWinHit(scope.row.win_hit) }}
                            </el-tag>
                            <span v-else>-</span>
                        </template>
                    </el-table-column>
                    <el-table-column
                        prop="total_amount"
                        :label="t('channel.bet_record_total_amount')"
                        min-width="100"
                        align="center"
                        header-align="center"
                    />
                    <el-table-column
                        prop="win_amount"
                        :label="t('channel.bet_record_win_amount')"
                        min-width="100"
                        align="center"
                        header-align="center"
                    />
                </el-table>
                </div>
                <div class="channel-record-pagination">
                    <el-pagination
                        background
                        layout="total, prev, pager, next"
                        :total="betRecordDialog.total"
                        :page-size="betRecordDialog.limit"
                        :current-page="betRecordDialog.page"
                        @current-change="onBetRecordPageChange"
                    />
                </div>
            </div>
        </el-dialog>

    </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, provide, reactive, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElMessage } from 'element-plus'
import PopupForm from './popupForm.vue'
import { baTableApi } from '/@/api/common'
import { auth } from '/@/utils/common'
import { defaultOptButtons } from '/@/components/table'
import TableHeader from '/@/components/table/header/index.vue'
import Table from '/@/components/table/index.vue'
import baTableClass from '/@/utils/baTable'
import createAxios from '/@/utils/axios'

defineOptions({
    name: 'channel',
})

const { t } = useI18n()

const MANUAL_SETTLE_MOBILE_BREAKPOINT = 768
const manualSettleViewportMobile = ref(typeof window !== 'undefined' ? window.innerWidth <= MANUAL_SETTLE_MOBILE_BREAKPOINT : false)
const manualSettleCalcCollapse = ref<string[]>([])
const manualSettleDialogWidth = computed(() => (manualSettleViewportMobile.value ? '96%' : '920px'))
const manualSettleSummaryColumns = computed(() => (manualSettleViewportMobile.value ? 1 : 3))
const manualSettleFormSize = computed(() => (manualSettleViewportMobile.value ? 'small' : 'default'))
const manualSettleTableSize = computed(() => (manualSettleViewportMobile.value ? 'small' : 'default'))
const manualSettleFormLabelWidth = computed(() => 'auto')
const manualSettleTableLayout = computed(() => 'fixed')
const manualSettleSplitCol = computed(() => {
    if (manualSettleViewportMobile.value) {
        return {
            adminWidth: 120,
            baseWidth: 72,
            shareWidth: 58,
            grossWidth: 72,
            commissionShareWidth: 62,
            feeWidth: 64,
            netWidth: 72,
        }
    }
    return {
        adminWidth: 132,
        baseWidth: 88,
        shareWidth: 72,
        grossWidth: 88,
        commissionShareWidth: 76,
        feeWidth: 80,
        netWidth: 88,
    }
})

const manualSettleSplitTableMinWidth = computed(() => {
    const col = manualSettleSplitCol.value
    return (
        col.adminWidth +
        col.baseWidth +
        col.shareWidth +
        col.grossWidth +
        col.commissionShareWidth +
        col.feeWidth +
        col.netWidth +
        32
    )
})

const manualSettleSplitInnerStyle = computed(() => {
    if (!manualSettleViewportMobile.value) {
        return {}
    }
    return {
        width: `${manualSettleSplitTableMinWidth.value}px`,
    }
})

const syncManualSettleViewport = () => {
    if (typeof window === 'undefined') {
        return
    }
    manualSettleViewportMobile.value = window.innerWidth <= MANUAL_SETTLE_MOBILE_BREAKPOINT
}

const dismissFloatingTooltips = () => {
    if (typeof document === 'undefined') {
        return
    }
    document.querySelectorAll('.el-popper[role="tooltip"]').forEach((node) => node.remove())
    const active = document.activeElement
    if (active instanceof HTMLElement) {
        active.blur()
    }
}
const tableRef = useTemplateRef('tableRef')
let optButtons: OptButton[] = [
    {
        render: 'tipButton',
        name: 'manualSettle',
        title: 'channel.manual_settle',
        text: '',
        type: 'warning',
        icon: 'el-icon-Clock',
        class: 'table-row-manual-settle',
        disabledTip: true,
        display: () => auth('manualSettle'),
        click: (row: TableRow) => {
            void openManualSettleDialog(row)
        },
    },
]
optButtons = optButtons.concat(defaultOptButtons(['edit', 'delete']))
const formatAmountInt = (_row: any, _column: any, cellValue: number | string | null) => {
    if (cellValue === null || cellValue === undefined || cellValue === '') return '-'
    const num = Number(cellValue)
    if (Number.isNaN(num)) return '-'
    return `${num}`
}
const formatCommissionSharePercent = (row: { commission_amount?: string | number; commission_share_percent?: string | number }) => {
    const preset = row.commission_share_percent
    if (preset !== null && preset !== undefined && preset !== '') {
        const n = Number(preset)
        if (Number.isFinite(n)) {
            return `${n.toFixed(2)}%`
        }
    }
    const total = Number(manualSettle.form.commission_amount ?? 0)
    const gross = Number(row.commission_amount ?? 0)
    if (!Number.isFinite(total) || total <= 0 || !Number.isFinite(gross) || gross <= 0) {
        return '0.00%'
    }
    return `${((gross / total) * 100).toFixed(2)}%`
}

const formatSplitAmountCell = (_row: anyObj, _column: any, cellValue: unknown) => {
    if (cellValue === null || cellValue === undefined || cellValue === '') {
        return '-'
    }
    const n = Number(cellValue)
    if (!Number.isFinite(n)) {
        return String(cellValue)
    }
    return n.toFixed(2)
}

const formatAmount2 = (_row: any, _column: any, cellValue: number | string | null) => {
    if (cellValue === null || cellValue === undefined || cellValue === '') return '-'
    const num = Number(cellValue)
    if (Number.isNaN(num)) return '-'
    return num.toFixed(2)
}
const formatBetRecordWinHit = (code: unknown) => {
    const key = code === null || code === undefined ? '' : String(code)
    if (!key) return '-'
    const i18nKey = `channel.bet_record_win_hit_${key}`
    const text = t(i18nKey)
    return text !== i18nKey ? text : key
}

const betRecordWinHitTagType = (code: unknown): 'success' | 'info' | 'warning' | 'danger' => {
    const key = code === null || code === undefined ? '' : String(code)
    const map: Record<string, 'success' | 'info' | 'warning' | 'danger'> = {
        won: 'success',
        lost: 'info',
        pending: 'warning',
    }
    return map[key] ?? 'info'
}

const formatSettleDay = (row: anyObj) => {
    if (row.settle_cycle === 'weekly') {
        return t(`channel.weekday ${row.settle_weekday ?? 1}`)
    }
    if (row.settle_cycle === 'monthly') {
        return `${row.settle_monthday ?? 1}${t('channel.day_suffix')}`
    }
    return t('channel.settle_day_daily')
}

const manualSettle = reactive({
    visible: false,
    loading: false,
    previewLoading: false,
    channelId: 0,
    form: {
        settlement_no: '',
        period_start_at: '',
        period_end_at: '',
        total_bet_amount: '',
        total_payout_amount: '',
        platform_profit_amount: '',
        commission_rate: '',
        calc_base_amount: '',
        commission_amount: '',
        agent_mode: 'turnover' as string,
        settlement_handling_fee: '0.00',
        commission_split: [] as Array<{
            admin_id: number
            admin_username: string
            parent_admin_id?: number
            level?: number
            settlement_base_amount?: string
            share_rate: string
            commission_amount: string
            commission_share_percent?: string
            handling_fee_rate: number | string
            handling_fee?: string
            net_commission_amount?: string
        }>,
        remark: '',
    },
})

const settleFilterMode = ref<'all' | 'with_balance' | 'no_balance' | 'enabled' | 'disabled'>('all')
const settleStats = reactive({
    channel_total: 0,
    enabled_count: 0,
    disabled_count: 0,
    carryover_positive_count: 0,
    carryover_total: '0.00',
    carryover_positive_total: '0.00',
    paid_dividend_total: '0.00',
    company_total_bet_amount: '0.00',
})

const dividendDialog = reactive({
    visible: false,
    loading: false,
    page: 1,
    limit: 20,
    total: 0,
    list: [] as anyObj[],
})

const createBetRecordFilters = () => ({
    period_no: '',
    user_keyword: '',
    result_number: '',
    pick_number: '',
    win_hit: '' as '' | 'won' | 'lost' | 'pending',
})

const betRecordDialog = reactive({
    visible: false,
    loading: false,
    mode: '' as '' | 'direct' | 'company',
    channelId: 0,
    title: '',
    page: 1,
    limit: 20,
    total: 0,
    list: [] as anyObj[],
    filters: createBetRecordFilters(),
    summary: {
        record_count: 0,
        total_bet_amount: '0.00',
        total_win_amount: '0.00',
    },
})

const resetManualSettleForm = () => {
    manualSettle.form.settlement_no = ''
    manualSettle.form.period_start_at = ''
    manualSettle.form.period_end_at = ''
    manualSettle.form.total_bet_amount = ''
    manualSettle.form.total_payout_amount = ''
    manualSettle.form.platform_profit_amount = ''
    manualSettle.form.commission_rate = ''
    manualSettle.form.calc_base_amount = ''
    manualSettle.form.commission_amount = ''
    manualSettle.form.commission_split = []
    manualSettle.form.agent_mode = 'turnover'
    manualSettle.form.settlement_handling_fee = '0.00'
    manualSettle.form.remark = ''
}

type ManualSettleSplitRow = {
    admin_id: number
    admin_username: string
    parent_admin_id?: number
    level?: number
    settlement_base_amount?: string
    share_rate: string
    commission_amount: string
    commission_share_percent?: string
    handling_fee_rate: number | string
    handling_fee?: string
    net_commission_amount?: string
    children?: ManualSettleSplitRow[]
}

const buildCommissionSplitTree = (flat: ManualSettleSplitRow[]): ManualSettleSplitRow[] => {
    if (!flat.length) {
        return []
    }
    const nodeMap = new Map<number, ManualSettleSplitRow>()
    for (const row of flat) {
        nodeMap.set(row.admin_id, { ...row, children: [] })
    }
    const roots: ManualSettleSplitRow[] = []
    for (const row of flat) {
        const node = nodeMap.get(row.admin_id)
        if (!node) {
            continue
        }
        const parentId = Number(row.parent_admin_id ?? 0)
        if (parentId > 0 && nodeMap.has(parentId)) {
            const parent = nodeMap.get(parentId)
            if (parent) {
                if (!parent.children) {
                    parent.children = []
                }
                parent.children.push(node)
            }
            continue
        }
        roots.push(node)
    }
    const pruneEmptyChildren = (nodes: ManualSettleSplitRow[]) => {
        for (const node of nodes) {
            if (node.children && node.children.length > 0) {
                pruneEmptyChildren(node.children)
            } else {
                delete node.children
            }
        }
    }
    pruneEmptyChildren(roots)
    return roots
}

const manualSettleSplitTree = computed(() => buildCommissionSplitTree(manualSettle.form.commission_split))

const manualSettleCalcDescLines = computed(() => {
    const mode = manualSettle.form.agent_mode === 'affiliate' ? 'affiliate' : 'turnover'
    const feeRate = manualSettle.form.settlement_handling_fee
    const prefix =
        mode === 'affiliate'
            ? [
                  t('channel.manual_settle_calc_intro_affiliate_1'),
                  t('channel.manual_settle_calc_intro_affiliate_2'),
                  t('channel.manual_settle_calc_intro_affiliate_3'),
              ]
            : [
                  t('channel.manual_settle_calc_intro_turnover_1'),
                  t('channel.manual_settle_calc_intro_turnover_2'),
                  t('channel.manual_settle_calc_intro_turnover_3'),
              ]
    return [
        ...prefix,
        t('channel.manual_settle_calc_tree_1'),
        t('channel.manual_settle_calc_tree_2'),
        t('channel.manual_settle_calc_tree_3'),
        t('channel.manual_settle_calc_handling_fee', { rate: feeRate }),
    ]
})

const closeManualSettleDialog = () => {
    manualSettle.visible = false
    resetManualSettleForm()
}

const openManualSettleDialog = async (row: TableRow) => {
    dismissFloatingTooltips()
    syncManualSettleViewport()
    manualSettle.channelId = row.id
    resetManualSettleForm()
    manualSettle.visible = true
    await nextTick()
    dismissFloatingTooltips()
    manualSettle.previewLoading = true
    try {
        const res = await createAxios(
            {
                url: '/admin/channel/manualSettlePreview',
                method: 'get',
                params: { id: row.id },
            },
            { showErrorMessage: true }
        )
        if (res.code !== 1 || !res.data) {
            manualSettle.visible = false
            return
        }
        const d = res.data as anyObj
        manualSettle.form.settlement_no = d.settlement_no ?? ''
        manualSettle.form.period_start_at = d.period_start_at ?? ''
        manualSettle.form.period_end_at = d.period_end_at ?? ''
        manualSettle.form.total_bet_amount = d.total_bet_amount ?? ''
        manualSettle.form.total_payout_amount = d.total_payout_amount ?? ''
        manualSettle.form.platform_profit_amount = d.platform_profit_amount ?? ''
        manualSettle.form.commission_rate = d.commission_rate ?? ''
        manualSettle.form.calc_base_amount = d.calc_base_amount ?? ''
        manualSettle.form.commission_amount = d.commission_amount ?? ''
        manualSettle.form.agent_mode = d.agent_mode ?? 'turnover'
        manualSettle.form.settlement_handling_fee = d.settlement_handling_fee ?? '0.00'
        manualSettle.form.commission_split = normalizeManualSettleSplit(d.commission_split, d.settlement_handling_fee)
        manualSettle.form.remark = `${t('channel.manual_settle')}-CH${row.id}`
    } catch {
        manualSettle.visible = false
    } finally {
        manualSettle.previewLoading = false
    }
}

const calcHandlingFeeByPercent = (gross: number, ratePercent: number) => {
    const g = Number.isFinite(gross) && gross > 0 ? gross : 0
    let rate = Number.isFinite(ratePercent) ? ratePercent : 0
    if (rate < 0) rate = 0
    if (rate > 100) rate = 100
    return Math.round(g * rate * 100) / 10000
}

const applyManualSettleRowAmounts = (row: {
    commission_amount?: string | number
    handling_fee_rate?: string | number
    handling_fee?: string | number
    net_commission_amount?: string
}) => {
    const gross = Number(row.commission_amount ?? 0)
    const rate = Number(row.handling_fee_rate ?? 0)
    const feeAmount = calcHandlingFeeByPercent(gross, rate)
    row.handling_fee = feeAmount.toFixed(2)
    row.net_commission_amount = Math.max(0, (Number.isFinite(gross) ? gross : 0) - feeAmount).toFixed(2)
}

const normalizeManualSettleSplit = (rows: unknown, defaultFeeRate: unknown) => {
    const feeDefault = Number(defaultFeeRate)
    const baseRate = Number.isFinite(feeDefault) && feeDefault >= 0 ? Math.min(100, feeDefault) : 0
    if (!Array.isArray(rows)) {
        return []
    }
    return rows.map((row: anyObj) => {
        let rate = Number(row.handling_fee_rate ?? row.handling_fee ?? baseRate)
        if (!Number.isFinite(rate) || rate < 0) {
            rate = baseRate
        }
        if (rate > 100) {
            rate = 100
        }
        const normalized = {
            ...row,
            handling_fee_rate: rate,
        }
        applyManualSettleRowAmounts(normalized)
        return normalized
    })
}

const formatNetCommission = (row: {
    commission_amount?: string | number
    handling_fee_rate?: string | number
    net_commission_amount?: string
}) => {
    if (row.net_commission_amount !== undefined && row.net_commission_amount !== '') {
        return row.net_commission_amount
    }
    const gross = Number(row.commission_amount ?? 0)
    const rate = Number(row.handling_fee_rate ?? 0)
    const net = Math.max(0, (Number.isFinite(gross) ? gross : 0) - calcHandlingFeeByPercent(gross, rate))
    return net.toFixed(2)
}

const submitManualSettle = async () => {
    if (!manualSettle.channelId) return
    manualSettle.loading = true
    try {
        await createAxios(
            {
                url: '/admin/channel/manualSettle',
                method: 'post',
                data: {
                    id: manualSettle.channelId,
                    remark: manualSettle.form.remark,
                    commission_split: manualSettle.form.commission_split.map((row) => ({
                        admin_id: row.admin_id,
                        handling_fee_rate: row.handling_fee_rate ?? 0,
                    })),
                },
            },
            { showSuccessMessage: true }
        )
        closeManualSettleDialog()
        baTable.onTableHeaderAction('refresh', { event: 'manual-settle' })
    } finally {
        manualSettle.loading = false
    }
}

const onBatchSettlePending = async () => {
    await createAxios(
        {
            url: '/admin/channel/batchSettlePending',
            method: 'post',
        },
        { showSuccessMessage: true }
    )
    await loadSettleStats()
    baTable.onTableHeaderAction('refresh', { event: 'batch-settle' })
}

const onSettleFilterChange = () => {
    baTable.getData()
}

const loadSettleStats = async () => {
    const res = await createAxios({ url: '/admin/channel/settleStats', method: 'get' })
    if (res.code !== 1 || !res.data) {
        return
    }
    settleStats.channel_total = Number(res.data.channel_total ?? 0)
    settleStats.enabled_count = Number(res.data.enabled_count ?? 0)
    settleStats.disabled_count = Number(res.data.disabled_count ?? 0)
    settleStats.carryover_positive_count = Number(res.data.carryover_positive_count ?? 0)
    settleStats.carryover_total = String(res.data.carryover_total ?? '0.00')
    settleStats.carryover_positive_total = String(res.data.carryover_positive_total ?? '0.00')
    settleStats.paid_dividend_total = String(res.data.paid_dividend_total ?? '0.00')
    settleStats.company_total_bet_amount = String(res.data.company_total_bet_amount ?? '0.00')
}

const loadDividendRecords = async () => {
    dividendDialog.loading = true
    try {
        const res = await createAxios({
            url: '/admin/channel/dividendRecordList',
            method: 'get',
            params: { page: dividendDialog.page, limit: dividendDialog.limit },
        })
        if (res.code !== 1 || !res.data) {
            return
        }
        dividendDialog.list = Array.isArray(res.data.list) ? res.data.list : []
        dividendDialog.total = Number(res.data.total ?? 0)
    } finally {
        dividendDialog.loading = false
    }
}

const onPaidDividendCardClick = () => {
    if (!auth('index')) {
        return
    }
    dividendDialog.page = 1
    dividendDialog.visible = true
    void loadDividendRecords()
}

const onCompanyTotalBetCardClick = () => {
    if (!auth('index')) {
        return
    }
    resetBetRecordDialog()
    betRecordDialog.mode = 'company'
    betRecordDialog.channelId = 0
    betRecordDialog.title = t('channel.company_bet_record_dialog_title')
    betRecordDialog.visible = true
    void loadBetRecords()
}

const closeDividendDialog = () => {
    dividendDialog.visible = false
    dividendDialog.list = []
    dividendDialog.total = 0
    dividendDialog.page = 1
}

const onDividendPageChange = (page: number) => {
    dividendDialog.page = page
    void loadDividendRecords()
}

const resetBetRecordDialog = () => {
    betRecordDialog.mode = ''
    betRecordDialog.channelId = 0
    betRecordDialog.title = ''
    betRecordDialog.page = 1
    betRecordDialog.total = 0
    betRecordDialog.list = []
    betRecordDialog.summary = {
        record_count: 0,
        total_bet_amount: '0.00',
        total_win_amount: '0.00',
    }
    Object.assign(betRecordDialog.filters, createBetRecordFilters())
}

const buildBetRecordFilterParams = () => {
    const f = betRecordDialog.filters
    const params: Record<string, string> = {}
    if (f.period_no.trim()) {
        params.period_no = f.period_no.trim()
    }
    if (f.user_keyword.trim()) {
        params.user_keyword = f.user_keyword.trim()
    }
    if (f.result_number.trim()) {
        params.result_number = f.result_number.trim()
    }
    if (f.pick_number.trim()) {
        params.pick_number = f.pick_number.trim()
    }
    if (f.win_hit) {
        params.win_hit = f.win_hit
    }
    return params
}

const loadBetRecords = async () => {
    if (!betRecordDialog.mode) {
        return
    }
    if (betRecordDialog.mode === 'direct' && !betRecordDialog.channelId) {
        return
    }
    const url =
        betRecordDialog.mode === 'direct'
            ? '/admin/channel/directBetRecordList'
            : '/admin/channel/companyBetRecordList'
    betRecordDialog.loading = true
    try {
        const params: Record<string, string | number> = {
            page: betRecordDialog.page,
            limit: betRecordDialog.limit,
            ...buildBetRecordFilterParams(),
        }
        if (betRecordDialog.mode === 'direct') {
            params.channel_id = betRecordDialog.channelId
        }
        const res = await createAxios({
            url,
            method: 'get',
            params,
        })
        if (res.code !== 1 || !res.data) {
            return
        }
        betRecordDialog.list = Array.isArray(res.data.list) ? res.data.list : []
        betRecordDialog.total = Number(res.data.total ?? 0)
        const summary = res.data.summary
        if (summary && typeof summary === 'object') {
            betRecordDialog.summary.record_count = Number(summary.record_count ?? 0)
            betRecordDialog.summary.total_bet_amount = String(summary.total_bet_amount ?? '0.00')
            betRecordDialog.summary.total_win_amount = String(summary.total_win_amount ?? '0.00')
        }
    } finally {
        betRecordDialog.loading = false
    }
}

const openBetRecordDialog = (mode: 'direct' | 'company', row: TableRow) => {
    if (!auth('index')) {
        return
    }
    resetBetRecordDialog()
    betRecordDialog.mode = mode
    betRecordDialog.channelId = Number(row.id ?? 0)
    betRecordDialog.title =
        mode === 'direct'
            ? `${t('channel.direct_bet_record_dialog_title')} - ${row.name ?? row.id}`
            : t('channel.company_bet_record_dialog_title')
    betRecordDialog.visible = true
    void loadBetRecords()
}

const closeBetRecordDialog = () => {
    betRecordDialog.visible = false
    resetBetRecordDialog()
}

const onBetRecordPageChange = (page: number) => {
    betRecordDialog.page = page
    void loadBetRecords()
}

const onBetRecordSearch = () => {
    betRecordDialog.page = 1
    void loadBetRecords()
}

const onBetRecordReset = () => {
    Object.assign(betRecordDialog.filters, createBetRecordFilters())
    onBetRecordSearch()
}

const openDirectBetDialog = (row: TableRow) => {
    void openBetRecordDialog('direct', row)
}

const baTable = new baTableClass(
    new baTableApi('/admin/channel/'),
    {
        pk: 'id',
        column: [
            { type: 'selection', align: 'center', operator: false },
            { label: t('channel.id'), prop: 'id', align: 'center', width: 70, operator: 'RANGE', sortable: 'custom' },
            {
                label: t('channel.code'),
                prop: 'code',
                align: 'center',
                operatorPlaceholder: t('Fuzzy query'),
                sortable: false,
                operator: 'LIKE',
            },
            {
                label: t('channel.name'),
                prop: 'name',
                align: 'center',
                operatorPlaceholder: t('Fuzzy query'),
                sortable: false,
                operator: 'LIKE',
            },
            {
                label: t('channel.agent_mode'),
                prop: 'agent_mode',
                align: 'center',
                minWidth: 120,
                operator: 'eq',
                sortable: false,
                render: 'tag',
                custom: {
                    turnover: 'primary',
                    affiliate: 'success',
                },
                replaceValue: {
                    turnover: t('channel.agent_mode turnover'),
                    affiliate: t('channel.agent_mode affiliate'),
                },
            },
            {
                label: t('channel.carryover_balance'),
                prop: 'carryover_balance',
                align: 'center',
                minWidth: 130,
                sortable: false,
                operator: 'RANGE',
                formatter: formatAmountInt,
            },
            {
                label: t('channel.affiliate_contract_no'),
                prop: 'affiliate_contract_no',
                align: 'center',
                minWidth: 140,
                sortable: false,
                operator: 'LIKE',
                operatorPlaceholder: t('Fuzzy query'),
                showOverflowTooltip: true,
            },
            {
                label: t('channel.settle_cycle'),
                prop: 'settle_cycle',
                align: 'center',
                width: 110,
                operator: 'eq',
                sortable: false,
                render: 'tag',
                custom: { daily: 'info', weekly: 'primary', monthly: 'success' },
                replaceValue: {
                    daily: t('channel.settle_cycle daily'),
                    weekly: t('channel.settle_cycle weekly'),
                    monthly: t('channel.settle_cycle monthly'),
                },
            },
            {
                label: t('channel.settle_weekday'),
                prop: 'settle_day',
                align: 'center',
                width: 110,
                operator: false,
                sortable: false,
                formatter: (row: anyObj) => formatSettleDay(row),
            },
            {
                label: t('channel.settle_time'),
                prop: 'settle_time',
                align: 'center',
                width: 100,
                operator: 'LIKE',
                sortable: false,
            },
            {
                label: t('channel.affiliate_effective_start_at'),
                prop: 'affiliate_effective_start_at',
                align: 'center',
                render: 'datetime',
                operator: 'RANGE',
                comSearchRender: 'datetime',
                sortable: 'custom',
                width: 160,
                timeFormat: 'yyyy-mm-dd hh:MM:ss',
            },
            {
                label: t('channel.affiliate_effective_end_at'),
                prop: 'affiliate_effective_end_at',
                align: 'center',
                render: 'datetime',
                operator: 'RANGE',
                comSearchRender: 'datetime',
                sortable: 'custom',
                width: 160,
                timeFormat: 'yyyy-mm-dd hh:MM:ss',
            },
            {
                label: t('channel.user_count'),
                prop: 'user_count',
                align: 'center',
                sortable: false,
                operator: 'RANGE',
            },
            {
                label: t('channel.direct_bet_amount'),
                prop: 'direct_bet_amount',
                align: 'center',
                minWidth: 120,
                sortable: false,
                operator: false,
                render: 'tag',
                formatter: formatAmount2,
                customRenderAttr: {
                    tag: ({ row }: { row: TableRow }) => ({
                        class: auth('index') ? 'channel-direct-bet-tag' : '',
                        onClick: auth('index') ? () => openDirectBetDialog(row) : undefined,
                    }),
                },
            },
            {
                label: t('channel.profit_amount'),
                prop: 'profit_amount',
                align: 'center',
                minWidth: 110,
                sortable: false,
                operator: 'RANGE',
                formatter: formatAmountInt,
            },
            {
                label: t('channel.total_profit_amount'),
                prop: 'total_profit_amount',
                align: 'center',
                minWidth: 110,
                sortable: false,
                operator: 'RANGE',
                formatter: formatAmountInt,
            },
            {
                label: t('channel.commission_pool_amount'),
                prop: 'commission_pool_amount',
                align: 'center',
                minWidth: 110,
                sortable: false,
                operator: 'RANGE',
                formatter: formatAmountInt,
            },
            {
                label: t('channel.status'),
                prop: 'status',
                align: 'center',
                operator: 'eq',
                sortable: false,
                render: 'switch',
                replaceValue: { '0': t('channel.status 0'), '1': t('channel.status 1') },
            },
            {
                label: t('channel.create_time'),
                prop: 'create_time',
                align: 'center',
                render: 'datetime',
                operator: 'RANGE',
                comSearchRender: 'datetime',
                sortable: 'custom',
                width: 160,
                timeFormat: 'yyyy-mm-dd hh:MM:ss',
            },
            {
                label: t('channel.update_time'),
                prop: 'update_time',
                align: 'center',
                render: 'datetime',
                operator: 'RANGE',
                comSearchRender: 'datetime',
                sortable: 'custom',
                width: 160,
                timeFormat: 'yyyy-mm-dd hh:MM:ss',
            },
            { label: t('Operate'), align: 'center', width: 160, render: 'buttons', buttons: optButtons, operator: false, fixed: 'right' },
        ],
        dblClickNotEditColumn: [undefined, 'status'],
    },
    {
        defaultItems: {
            status: '1',
            agent_mode: 'turnover',
            settlement_handling_fee: 0,
            settle_cycle: 'weekly',
            settle_weekday: 1,
            settle_monthday: 1,
            settle_time: '02:00:00',
        },
    }
)

baTable.before.getData = () => {
    const filter = baTable.table.filter || {}
    const searchRaw = filter.search
    const search = Array.isArray(searchRaw) ? searchRaw.filter((item: any) => item && item.field !== 'carryover_balance' && item.field !== 'status') : []
    if (settleFilterMode.value === 'with_balance') {
        search.push({ field: 'carryover_balance', operator: 'gt', val: 0 })
    } else if (settleFilterMode.value === 'no_balance') {
        search.push({ field: 'carryover_balance', operator: 'elt', val: 0 })
    } else if (settleFilterMode.value === 'enabled') {
        search.push({ field: 'status', operator: 'eq', val: 1 })
    } else if (settleFilterMode.value === 'disabled') {
        search.push({ field: 'status', operator: 'eq', val: 0 })
    }
    filter.search = search
    baTable.table.filter = filter
}

baTable.after.getData = () => {
    void loadSettleStats()
}

provide('baTable', baTable)

onMounted(() => {
    syncManualSettleViewport()
    window.addEventListener('resize', syncManualSettleViewport)
    baTable.table.ref = tableRef.value
    baTable.mount()
    baTable.getData()?.then(() => {
        baTable.initSort()
        baTable.dragSort()
    })
    void loadSettleStats()
})

onUnmounted(() => {
    window.removeEventListener('resize', syncManualSettleViewport)
})
</script>

<style scoped lang="scss">
.mb-12 {
    margin-bottom: 12px;
}

.share-total-row {
    margin-top: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.share-group-single {
    font-size: 12px;
    line-height: 1.4;
    color: var(--el-text-color-regular);
}

.share-group-empty {
    color: var(--el-text-color-placeholder);
}

.channel-top-actions {
    margin: 8px 0 12px;
}

.channel-stats-cards {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 8px;
    margin-bottom: 10px;
}

.channel-stats-cards :deep(.el-card__body) {
    padding: 10px 8px;
}

.channel-stat-card {
    text-align: center;
    min-width: 0;
}

.channel-stat-card-clickable {
    cursor: pointer;
    transition: box-shadow 0.2s ease;
}

.channel-stat-card-clickable:hover {
    box-shadow: 0 0 0 1px var(--el-color-primary-light-5);
}

.channel-stat-card-clickable .value {
    color: var(--el-color-primary);
}

:deep(.channel-direct-bet-tag) {
    cursor: pointer;
}

.channel-bet-filter {
    margin-bottom: 12px;
    padding: 10px 12px 2px;
    background: var(--el-fill-color-lighter);
    border-radius: 6px;
}

.channel-bet-filter :deep(.el-form-item) {
    margin-bottom: 8px;
    margin-right: 12px;
}

.channel-bet-filter-input {
    width: 140px;
}

.channel-bet-filter-input--short {
    width: 100px;
}

.channel-bet-filter-select {
    width: 120px;
}

.channel-bet-summary {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 14px;
}

.channel-bet-summary-card {
    text-align: center;
}

.channel-bet-summary-card .label {
    font-size: 12px;
    color: var(--el-text-color-secondary);
}

.channel-bet-summary-card .value {
    margin-top: 6px;
    font-size: 20px;
    font-weight: 600;
    color: var(--el-text-color-primary);
}

.channel-bet-record-table :deep(.el-table__cell) {
    text-align: center;
}

.channel-bet-record-table :deep(.cell) {
    display: flex;
    align-items: center;
    justify-content: center;
}

.channel-record-pagination {
    margin-top: 12px;
    display: flex;
    justify-content: flex-end;
}

.channel-stat-card .label {
    font-size: 11px;
    color: var(--el-text-color-secondary);
    line-height: 1.3;
    word-break: break-all;
}

.channel-stat-card .value {
    margin-top: 4px;
    font-size: 17px;
    font-weight: 600;
    color: var(--el-text-color-primary);
    line-height: 1.2;
}

.channel-action-row {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
}

/* 手动结算弹窗：可滚动（勿使用 ba-operate-dialog 固定 58vh 高度） */
:deep(.manual-settle-dialog.el-dialog) {
    display: flex !important;
    flex-direction: column;
    width: 92% !important;
    max-width: 920px;
    max-height: 90vh;
    margin: 5vh auto !important;
    padding-bottom: 0;
    overflow: hidden;
}

:deep(.manual-settle-dialog .el-dialog__header) {
    flex-shrink: 0;
    padding: 14px 20px;
    margin-right: 0;
}

:deep(.manual-settle-dialog .el-dialog__header .title) {
    font-size: 16px;
    font-weight: 600;
}

:deep(.manual-settle-dialog .el-dialog__body) {
    flex: 1 1 auto;
    min-height: 0;
    height: auto !important;
    max-height: calc(90vh - 116px);
    overflow-y: auto !important;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 16px 20px 18px;
}

:deep(.manual-settle-dialog .el-dialog__footer) {
    flex-shrink: 0;
    position: static;
    width: auto;
    box-shadow: none;
    border-top: 1px solid var(--el-border-color-lighter);
}

.manual-settle-dialog-body {
    min-height: 0;
    overflow: visible;
}

:deep(.manual-settle-dialog-body .el-loading-mask) {
    border-radius: 4px;
}

.manual-settle-summary {
    margin-bottom: 16px;
}

.manual-settle-summary :deep(.el-descriptions__label) {
    width: 148px;
    font-size: 13px;
    color: var(--el-text-color-secondary);
    font-weight: 500;
}

.manual-settle-summary :deep(.el-descriptions__content) {
    font-size: 14px;
    line-height: 1.5;
    color: var(--el-text-color-primary);
}

.manual-settle-summary-highlight {
    font-size: 15px;
    font-weight: 600;
    color: var(--el-color-primary);
}

.manual-settle-form {
    display: block;
    min-width: 0;
    max-width: 100%;
}

.manual-settle-form :deep(.el-form-item) {
    margin-bottom: 14px;
}

.manual-settle-split-form-item :deep(.el-form-item__label) {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.5;
    padding-bottom: 8px;
    color: var(--el-text-color-primary);
}

.manual-settle-form-item-full {
    grid-column: 1 / -1;
    min-width: 0;
}

.manual-settle-form-item-full :deep(.el-form-item__content) {
    min-width: 0;
    max-width: 100%;
}

.manual-settle-split-block {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
}

.manual-settle-split-table-scroll {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
}

.manual-settle-split-table-scroll.is-mobile {
    overflow-x: scroll;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 6px;
    background: var(--el-fill-color-blank);
}

.manual-settle-split-table-inner.is-mobile {
    display: inline-block;
    max-width: none;
    vertical-align: top;
}

.manual-settle-split-table-scroll.is-mobile :deep(.el-table) {
    width: 100% !important;
}

.manual-settle-split-table-scroll.is-mobile :deep(.el-table__inner-wrapper) {
    width: 100% !important;
}

.manual-settle-split-table-scroll.is-mobile :deep(.el-table__body-wrapper),
.manual-settle-split-table-scroll.is-mobile :deep(.el-table__header-wrapper) {
    overflow: visible !important;
}

.manual-settle-split-table-scroll.is-mobile :deep(.el-scrollbar__wrap) {
    overflow: visible !important;
}

.manual-settle-split-table-scroll.is-mobile :deep(.el-scrollbar__bar.is-horizontal) {
    display: none !important;
}

.manual-settle-split-scroll-tip {
    margin: 6px 0 0;
    font-size: 11px;
    line-height: 1.4;
    color: var(--el-text-color-secondary);
    text-align: center;
}

.manual-settle-split-table:not(.is-mobile) {
    width: 100%;
}

.manual-settle-split-table :deep(.el-table__header th.el-table__cell),
.manual-settle-split-table :deep(.el-table__body td.el-table__cell) {
    padding: 10px 8px;
}

.manual-settle-split-table :deep(.el-table__header .cell),
.manual-settle-split-table :deep(.el-table__body .cell) {
    padding: 0 4px;
    font-size: 14px;
    line-height: 1.5;
    word-break: break-word;
}

.manual-settle-split-table :deep(.el-table__header .cell) {
    white-space: normal;
    font-weight: 600;
    color: var(--el-text-color-primary);
}

.manual-settle-split-table.is-mobile :deep(.el-table__header th.el-table__cell),
.manual-settle-split-table.is-mobile :deep(.el-table__body td.el-table__cell) {
    padding: 5px 3px;
}

.manual-settle-split-table.is-mobile :deep(.el-table__header .cell),
.manual-settle-split-table.is-mobile :deep(.el-table__body .cell) {
    font-size: 11px;
    line-height: 1.3;
    white-space: nowrap;
    word-break: keep-all;
    overflow-wrap: normal;
}

.manual-settle-split-table.is-mobile :deep(.el-table__body td:first-child .cell) {
    white-space: nowrap;
    word-break: keep-all;
}

.manual-settle-calc-collapse {
    margin-top: 12px;
    border: none;
}

.manual-settle-calc-collapse :deep(.el-collapse-item__header) {
    height: 40px;
    line-height: 40px;
    font-size: 14px;
    font-weight: 500;
    border-bottom: none;
    background: var(--el-fill-color-light);
    border-radius: 6px;
    padding: 0 12px;
}

.manual-settle-calc-collapse :deep(.el-collapse-item__wrap) {
    border-bottom: none;
}

.manual-settle-calc-collapse :deep(.el-collapse-item__content) {
    padding: 10px 12px 4px;
}

.manual-settle-calc-list {
    margin: 0;
    padding-left: 20px;
    line-height: 1.65;
    font-size: 13px;
    color: var(--el-text-color-regular);
}

.manual-settle-calc-list li + li {
    margin-top: 4px;
}

.manual-settle-footer {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 4px 0 0;
}

.manual-settle-footer .el-button {
    min-width: 88px;
}

/* 渠道记录弹窗：可滚动、适配移动端（勿使用 ba-operate-dialog 固定高度） */
:deep(.channel-record-dialog.el-dialog) {
    display: flex;
    flex-direction: column;
    max-height: 92vh;
    margin: 4vh auto !important;
    padding-bottom: 0;
    overflow: hidden;
    width: 92% !important;
    max-width: 1080px;
}

:deep(.channel-record-dialog.channel-bet-record-dialog.el-dialog) {
    max-width: 1080px;
}

:deep(.channel-record-dialog .el-dialog__header) {
    flex-shrink: 0;
    padding: 12px 16px;
    margin-right: 0;
}

:deep(.channel-record-dialog .el-dialog__body) {
    flex: 1;
    min-height: 0;
    height: auto !important;
    max-height: calc(92vh - 56px);
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    padding: 12px 14px 16px;
}

.channel-record-dialog__body {
    min-height: 0;
}

.channel-record-table-wrap {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.channel-record-table {
    min-width: 640px;
}

.channel-bet-record-table {
    min-width: 880px;
}

@media (max-width: 900px) {
    .channel-stats-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .manual-settle-summary :deep(.el-descriptions__label) {
        width: auto;
        font-size: 12px;
    }

    .manual-settle-summary :deep(.el-descriptions__content) {
        font-size: 13px;
    }
}

@media (max-width: 768px) {
    :deep(.manual-settle-dialog.el-dialog) {
        width: 96% !important;
        max-width: none;
        max-height: 94vh;
        margin: 3vh auto !important;
    }

    :deep(.manual-settle-dialog .el-dialog__header) {
        padding: 10px 12px;
    }

    :deep(.manual-settle-dialog .el-dialog__body) {
        max-height: calc(94vh - 96px);
        padding: 12px 12px 14px;
    }

    :deep(.manual-settle-dialog .el-dialog__footer) {
        padding: 8px 10px 10px;
    }

    .manual-settle-summary {
        margin-bottom: 12px;
    }

    .manual-settle-form :deep(.el-form-item) {
        margin-bottom: 10px;
    }

    .manual-settle-split-form-item :deep(.el-form-item__label) {
        font-size: 13px;
        padding-bottom: 6px;
    }

    .manual-settle-form-item-full :deep(.el-form-item__content) {
        width: 100%;
        max-width: 100%;
        min-width: 0;
    }

    .manual-settle-split-block {
        max-width: 100%;
        min-width: 0;
        overflow: hidden;
        margin: 0;
        padding-bottom: 0;
    }

    .manual-settle-split-table-scroll.is-mobile {
        max-width: 100%;
    }

    .manual-settle-calc-collapse :deep(.el-collapse-item__header) {
        font-size: 12px;
    }

    .manual-settle-calc-list {
        font-size: 11px;
        padding-left: 16px;
    }

    .manual-settle-footer {
        flex-wrap: wrap;
        justify-content: stretch;
    }

    .manual-settle-footer .el-button {
        flex: 1;
        margin: 0;
    }

    :deep(.channel-record-dialog.el-dialog) {
        width: 96% !important;
        max-height: 94vh;
        margin: 3vh auto !important;
    }

    :deep(.channel-record-dialog .el-dialog__body) {
        max-height: calc(94vh - 52px);
        padding: 10px 10px 14px;
    }

    .channel-bet-summary {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 6px;
        margin-bottom: 10px;
    }

    .channel-bet-summary-card :deep(.el-card__body) {
        padding: 8px 4px;
    }

    .channel-bet-summary-card .label {
        font-size: 10px;
        line-height: 1.3;
    }

    .channel-bet-summary-card .value {
        margin-top: 4px;
        font-size: 13px;
        word-break: break-all;
    }

    .channel-bet-filter {
        padding: 8px 10px 0;
    }

    .channel-bet-filter :deep(.el-form-item) {
        display: flex;
        width: 100%;
        margin-right: 0;
    }

    .channel-bet-filter :deep(.el-form-item__label) {
        width: 72px !important;
        padding-right: 6px;
    }

    .channel-bet-filter :deep(.el-form-item__content) {
        flex: 1;
        min-width: 0;
    }

    .channel-bet-filter-input,
    .channel-bet-filter-input--short,
    .channel-bet-filter-select {
        width: 100%;
    }

    .channel-bet-filter :deep(.el-form-item:last-child .el-form-item__content) {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
    }

    .channel-record-pagination {
        justify-content: center;
    }

    .channel-record-pagination :deep(.el-pagination) {
        flex-wrap: wrap;
        justify-content: center;
        row-gap: 6px;
    }
}
</style>
