<template>
    <el-dialog
        class="ba-operate-dialog withdraw-review-dialog"
        :close-on-click-modal="false"
        :model-value="isOpen"
        width="640px"
        @close="onDialogClose"
    >
        <template #header>
            <div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
                {{ step === 'reject' ? t('order.withdrawOrder.review_reject_title') : t('order.withdrawOrder.review_title') }}
            </div>
        </template>

        <el-scrollbar v-loading="loading" class="ba-table-form-scrollbar">
            <div class="ba-operate-form ba-edit-form" :style="config.layout.shrink ? '' : 'width: calc(100% - ' + (baTable.form.labelWidth ?? 120) / 2 + 'px)'">
                <!-- 第一页：关联信息 + 申请金额 / 手续费 -->
                <el-form
                    v-if="!loading && step === 'review'"
                    ref="reviewFormRef"
                    :model="form"
                    :rules="reviewRules"
                    :label-position="config.layout.shrink ? 'top' : 'right'"
                    :label-width="(baTable.form.labelWidth ?? 120) + 'px'"
                    @submit.prevent=""
                >
                    <el-form-item :label="t('order.withdrawOrder.order_no')">
                        <el-input v-model="form.order_no" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.user_username')">
                        <el-input :model-value="form.user_text" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.channel_name')">
                        <el-input :model-value="form.channel_text" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.status')">
                        <el-tag :type="statusTagType" effect="dark" size="small">{{ statusLabel }}</el-tag>
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.create_time')">
                        <el-input :model-value="form.create_time_text" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.pay_channel')">
                        <el-input :model-value="form.pay_channel || '-'" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.receive_type')">
                        <el-input :model-value="form.receive_type || '-'" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.receive_account')">
                        <el-input :model-value="form.receive_account || '-'" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.receiver_name')">
                        <el-input :model-value="form.receiver_name || '-'" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.receiver_email')">
                        <el-input :model-value="form.receiver_email || '-'" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.receiver_mobile')">
                        <el-input :model-value="form.receiver_mobile || '-'" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.idempotency_key')">
                        <el-input :model-value="form.idempotency_key || '-'" readonly />
                    </el-form-item>

                    <el-form-item :label="t('order.withdrawOrder.amount')" prop="amount">
                        <el-input-number
                            v-model="form.amount"
                            :min="0"
                            :precision="2"
                            :step="1"
                            :controls="false"
                            :disabled="!isPending"
                            style="width: 100%"
                        />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.fee')" prop="fee">
                        <el-input-number
                            v-model="form.fee"
                            :min="0"
                            :precision="2"
                            :step="0.1"
                            :controls="false"
                            :disabled="!isPending"
                            style="width: 100%"
                        />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.actual_amount')">
                        <el-input :model-value="actualAmountText" readonly />
                    </el-form-item>

                    <el-form-item v-if="!isPending" :label="t('order.withdrawOrder.review_admin_username')">
                        <el-input :model-value="form.review_admin_text" readonly />
                    </el-form-item>
                    <el-form-item v-if="!isPending" :label="t('order.withdrawOrder.review_time')">
                        <el-input :model-value="form.review_time_text" readonly />
                    </el-form-item>
                    <el-form-item v-if="!isPending" :label="t('order.withdrawOrder.remark')">
                        <el-input v-model="form.remark" type="textarea" :rows="2" readonly />
                    </el-form-item>
                </el-form>

                <!-- 第二页：拒绝 -> 必填备注 -->
                <el-form
                    v-if="!loading && step === 'reject'"
                    ref="rejectFormRef"
                    :model="rejectForm"
                    :rules="rejectRules"
                    :label-position="config.layout.shrink ? 'top' : 'right'"
                    :label-width="(baTable.form.labelWidth ?? 120) + 'px'"
                    @submit.prevent=""
                >
                    <el-alert
                        class="review-reject-hint"
                        type="warning"
                        show-icon
                        :closable="false"
                        :title="t('order.withdrawOrder.review_reject_tip')"
                    />
                    <el-form-item :label="t('order.withdrawOrder.order_no')">
                        <el-input v-model="form.order_no" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.amount')">
                        <el-input :model-value="amountText" readonly />
                    </el-form-item>
                    <el-form-item :label="t('order.withdrawOrder.remark')" prop="remark">
                        <el-input
                            v-model="rejectForm.remark"
                            type="textarea"
                            :rows="4"
                            maxlength="255"
                            show-word-limit
                            :placeholder="t('order.withdrawOrder.review_reject_placeholder')"
                        />
                    </el-form-item>
                </el-form>
            </div>
        </el-scrollbar>

        <template #footer>
            <div class="review-footer">
                <template v-if="step === 'review'">
                    <el-button @click="onDialogClose">{{ t('Cancel') }}</el-button>
                    <template v-if="isPending">
                        <el-button type="danger" :loading="submitting" @click="gotoReject">{{ t('order.withdrawOrder.review_btn_reject') }}</el-button>
                        <el-button type="primary" v-blur :loading="submitting" @click="submitApprove">{{ t('order.withdrawOrder.review_btn_approve') }}</el-button>
                    </template>
                </template>
                <template v-else>
                    <el-button @click="backToReview">{{ t('order.withdrawOrder.review_btn_back') }}</el-button>
                    <el-button type="danger" v-blur :loading="submitting" @click="submitReject">{{ t('order.withdrawOrder.review_btn_confirm_reject') }}</el-button>
                </template>
            </div>
        </template>
    </el-dialog>
</template>

<script setup lang="ts">
import type { FormInstance, FormItemRule } from 'element-plus'
import { ElMessage } from 'element-plus'
import { computed, inject, reactive, ref, useTemplateRef, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import createAxios from '/@/utils/axios'
import { useConfig } from '/@/stores/config'
import type baTableClass from '/@/utils/baTable'

const config = useConfig()
const baTable = inject('baTable') as baTableClass
const { t } = useI18n()

const reviewFormRef = useTemplateRef<FormInstance>('reviewFormRef')
const rejectFormRef = useTemplateRef<FormInstance>('rejectFormRef')

type Step = 'review' | 'reject'
const step = ref<Step>('review')
const loading = ref(false)
const submitting = ref(false)

const form = reactive({
    id: 0,
    order_no: '',
    user_text: '-',
    channel_text: '-',
    create_time_text: '',
    review_admin_text: '-',
    review_time_text: '-',
    idempotency_key: '',
    pay_channel: '',
    receive_type: '',
    receive_account: '',
    receiver_name: '',
    receiver_email: '',
    receiver_mobile: '',
    amount: 0,
    fee: 0,
    status: 0,
    remark: '',
})

const rejectForm = reactive({
    remark: '',
})

const isOpen = computed(() => ['Edit'].includes(baTable.form.operate ?? ''))
const isPending = computed(() => form.status === 0)

watch(
    isOpen,
    (visible) => {
        if (!visible) {
            return
        }
        step.value = 'review'
        rejectForm.remark = ''
    }
)

watch(
    () => ({ visible: isOpen.value, loadingState: baTable.form.loading, items: baTable.form.items }),
    ({ visible, loadingState }) => {
        if (!visible) return
        loading.value = loadingState === true
        if (loadingState) return
        hydrate()
    },
    { deep: true, immediate: true }
)

const hydrate = () => {
    const row = baTable.form.items as Record<string, unknown> | undefined
    if (!row || !row['id']) {
        return
    }
    form.id = Number(row['id'] ?? 0)
    form.order_no = String(row['order_no'] ?? '')
    form.amount = parseNumber(row['amount'])
    form.fee = parseNumber(row['fee'])
    form.status = Number(row['status'] ?? 0)
    form.remark = String(row['remark'] ?? '')
    form.idempotency_key = String(row['idempotency_key'] ?? '')
    form.pay_channel = String(row['pay_channel'] ?? '')
    form.receive_type = String(row['receive_type'] ?? '')
    form.receive_account = String(row['receive_account'] ?? '')
    form.receiver_name = String(row['ddpay_receiver_name'] ?? '')
    form.receiver_email = String(row['receiver_email'] ?? '')
    form.receiver_mobile = String(row['receiver_mobile'] ?? '')
    form.create_time_text = formatTime(row['create_time'])
    form.review_time_text = formatTime(row['review_time'])
    form.user_text = resolveRelationText(row, 'user', row['user_id'])
    form.channel_text = resolveRelationText(row, 'channel', row['channel_id'])
    form.review_admin_text = resolveRelationText(row, 'reviewAdmin', row['review_admin_id'])
}

const statusLabel = computed(() => t('order.withdrawOrder.status ' + form.status))
const statusTagType = computed(() => {
    switch (form.status) {
        case 1:
            return 'success'
        case 2:
            return 'danger'
        case 3:
            return 'success'
        default:
            return 'warning'
    }
})

const amountText = computed(() => formatAmount(form.amount))
const actualAmountText = computed(() => {
    const actual = Number((form.amount - form.fee).toFixed(2))
    return formatAmount(actual < 0 ? 0 : actual)
})

const reviewRules: Record<string, FormItemRule[]> = {
    amount: [
        {
            required: true,
            validator: (_r, value, cb) => {
                if (value === null || value === undefined || Number(value) <= 0) {
                    cb(new Error(t('order.withdrawOrder.amount_invalid')))
                    return
                }
                cb()
            },
        },
    ],
    fee: [
        {
            required: true,
            validator: (_r, value, cb) => {
                if (value === null || value === undefined || Number(value) < 0) {
                    cb(new Error(t('order.withdrawOrder.fee_invalid')))
                    return
                }
                if (Number(value) > Number(form.amount)) {
                    cb(new Error(t('order.withdrawOrder.fee_exceed_amount')))
                    return
                }
                cb()
            },
        },
    ],
}

const rejectRules: Record<string, FormItemRule[]> = {
    remark: [
        {
            required: true,
            validator: (_r, value, cb) => {
                const text = typeof value === 'string' ? value.trim() : ''
                if (text === '') {
                    cb(new Error(t('order.withdrawOrder.reject_reason_required')))
                    return
                }
                cb()
            },
            trigger: 'blur',
        },
    ],
}

const onDialogClose = () => {
    if (submitting.value) {
        return
    }
    step.value = 'review'
    baTable.toggleForm()
}

const gotoReject = async () => {
    step.value = 'reject'
    rejectForm.remark = ''
}

const backToReview = () => {
    step.value = 'review'
}

const submitApprove = async () => {
    if (!isPending.value) {
        ElMessage.warning(t('order.withdrawOrder.already_reviewed'))
        return
    }
    const formEl = reviewFormRef.value
    if (!formEl) return
    const valid = await formEl.validate().catch(() => false)
    if (!valid) return
    submitting.value = true
    try {
        await createAxios(
            {
                url: '/admin/order.WithdrawOrder/approve',
                method: 'POST',
                data: {
                    id: form.id,
                    amount: form.amount.toFixed(2),
                    fee: form.fee.toFixed(2),
                },
            },
            { showSuccessMessage: true }
        )
        baTable.onTableHeaderAction('refresh', {})
        baTable.toggleForm()
    } catch (_e) {
        // errors already surfaced by axios interceptor
    } finally {
        submitting.value = false
    }
}

const submitReject = async () => {
    const formEl = rejectFormRef.value
    if (!formEl) return
    const valid = await formEl.validate().catch(() => false)
    if (!valid) return
    submitting.value = true
    try {
        await createAxios(
            {
                url: '/admin/order.WithdrawOrder/reject',
                method: 'POST',
                data: {
                    id: form.id,
                    remark: rejectForm.remark.trim(),
                },
            },
            { showSuccessMessage: true }
        )
        baTable.onTableHeaderAction('refresh', {})
        baTable.toggleForm()
    } catch (_e) {
        // errors already surfaced by axios interceptor
    } finally {
        submitting.value = false
    }
}

function parseNumber(raw: unknown): number {
    if (raw === null || raw === undefined || raw === '') return 0
    const n = Number(raw)
    if (!Number.isFinite(n)) return 0
    return Number(n.toFixed(2))
}

function formatAmount(value: number): string {
    if (!Number.isFinite(value)) return '0.00'
    return value.toFixed(2)
}

function formatTime(raw: unknown): string {
    if (raw === null || raw === undefined || raw === '' || raw === 0) return '-'
    const sec = Number(raw)
    if (!Number.isFinite(sec) || sec <= 0) return '-'
    const d = new Date(sec * 1000)
    const pad = (n: number) => (n < 10 ? '0' + n : String(n))
    return (
        d.getFullYear() +
        '-' +
        pad(d.getMonth() + 1) +
        '-' +
        pad(d.getDate()) +
        ' ' +
        pad(d.getHours()) +
        ':' +
        pad(d.getMinutes()) +
        ':' +
        pad(d.getSeconds())
    )
}

function resolveRelationText(row: Record<string, unknown>, relationKey: string, fallbackId: unknown): string {
    const rel = row[relationKey]
    if (rel && typeof rel === 'object') {
        const r = rel as Record<string, unknown>
        const name = r['username'] ?? r['name']
        if (typeof name === 'string' && name !== '') {
            const id = fallbackId === null || fallbackId === undefined || fallbackId === '' ? '' : ' (ID: ' + String(fallbackId) + ')'
            return name + id
        }
    }
    if (fallbackId === null || fallbackId === undefined || fallbackId === '') {
        return '-'
    }
    return 'ID: ' + String(fallbackId)
}
</script>

<style scoped lang="scss">
.withdraw-review-dialog {
    :deep(.el-dialog__body) {
        padding-top: 8px;
    }

    .review-reject-hint {
        margin-bottom: 14px;
    }
}

.review-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

@media (max-width: 640px) {
    :deep(.withdraw-review-dialog) {
        width: calc(100vw - 24px) !important;
        max-width: 100vw;
    }
}
</style>
