import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined";
import SearchOutlined from "@mui/icons-material/SearchOutlined";
import MenuItem from "@mui/material/MenuItem";
import TextField from "@mui/material/TextField";
import { useMemo, useState } from "react";
import { createCoinAdjustment, listCoinAdjustments, lookupCoinAdjustmentTarget } from "@/features/operations/api";
import { useCoinAdjustmentAbilities } from "@/features/operations/permissions.js";
import styles from "@/features/operations/operations.module.css";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import {
    AdminFormAmountField,
    AdminFormDialog,
    AdminFormFieldGrid,
    AdminFormSection,
} from "@/shared/ui/AdminFormDialog.jsx";
import {
    AdminActionIconButton,
    AdminFilterResetButton,
    AdminListBody,
    AdminListPage,
    AdminListToolbar,
} from "@/shared/ui/AdminListLayout.jsx";
import { Button } from "@/shared/ui/Button.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { AdminUserIdentity } from "@/shared/ui/AdminUserIdentity.jsx";
import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { createUserIdentityColumnFilter } from "@/shared/ui/tableFilters.js";
import { emptyUserIdentityFilter, isUserIdentityFilterEmpty, userIdentityFilterParams } from "@/shared/ui/userIdentityFilter.js";
import { formatMillis } from "@/shared/utils/time.js";

const pageSize = 50;

const adjustmentReasons = ["运营发放", "活动补发", "系统补偿", "异常扣回", "风控扣减"];

const emptyForm = () => ({
    amount: "",
    mode: "increase",
    reason: adjustmentReasons[0],
    remark: "",
    userKeyword: "",
});

const columns = [
    {
        key: "user",
        label: "接收用户",
        render: (item) => <AdjustmentUserCell item={item} />,
        width: "minmax(260px, 1.35fr)",
    },
    {
        key: "amount",
        label: "增减数量",
        render: (item) => <AdjustmentAmount item={item} />,
        width: "minmax(130px, 0.65fr)",
    },
    {
        key: "reason",
        label: "发放理由",
        render: (item) => item.reason || "-",
        width: "minmax(170px, 0.85fr)",
    },
    {
        key: "remark",
        label: "备注",
        render: (item) => item.remark || "-",
        width: "minmax(220px, 1fr)",
    },
    {
        key: "operator",
        label: "发放人",
        render: (item) => operatorName(item),
        width: "minmax(150px, 0.8fr)",
    },
    {
        key: "balance",
        label: "余额",
        render: (item) => formatNumber(item.availableAfter),
        width: "minmax(120px, 0.65fr)",
    },
    {
        key: "createdAtMs",
        label: "时间",
        render: (item) => formatMillis(item.createdAtMs),
        width: "minmax(170px, 0.85fr)",
    },
];

export function CoinAdjustmentPage() {
    const abilities = useCoinAdjustmentAbilities();
    const { showToast } = useToast();
    const [page, setPage] = useState(1);
    const [userFilter, setUserFilter] = useState(emptyUserIdentityFilter);
    const [timeRange, setTimeRange] = useState({ endMs: "", startMs: "" });
    const [dialogOpen, setDialogOpen] = useState(false);
    const [form, setForm] = useState(emptyForm);
    const [targetUser, setTargetUser] = useState(null);
    const [lookupLoading, setLookupLoading] = useState(false);
    const [submitting, setSubmitting] = useState(false);

    const filters = useMemo(
        () => ({
            end_at_ms: timeRange.endMs || "",
            start_at_ms: timeRange.startMs || "",
            ...userIdentityFilterParams(userFilter),
        }),
        [timeRange.endMs, timeRange.startMs, userFilter],
    );
    const query = usePaginatedQuery({
        errorMessage: "获取金币增减列表失败",
        fetcher: listCoinAdjustments,
        filters,
        page,
        pageSize,
        queryKey: ["coin-adjustments", filters, page],
    });
    const data = query.data || { items: [], total: 0, page, pageSize };
    const items = data.items || [];
    const total = data.total || 0;

    const tableColumns = columns.map((column) =>
        column.key === "user"
            ? {
                  ...column,
                  filter: createUserIdentityColumnFilter({
                      value: userFilter,
                      onChange: (value) => {
                          setUserFilter(value);
                          setPage(1);
                      },
                  }),
              }
            : column,
    );

    const resetFilters = () => {
        setUserFilter(emptyUserIdentityFilter);
        setTimeRange({ endMs: "", startMs: "" });
        setPage(1);
    };
    const changeTimeRange = (nextRange) => {
        setTimeRange(nextRange);
        setPage(1);
    };
    const openDialog = () => {
        setForm(emptyForm());
        setTargetUser(null);
        setDialogOpen(true);
    };
    const closeDialog = () => {
        if (submitting) {
            return;
        }
        setDialogOpen(false);
        setTargetUser(null);
    };
    const changeForm = (patch) => {
        setForm((current) => ({ ...current, ...patch }));
    };
    const searchTargetUser = async () => {
        const keyword = form.userKeyword.trim();
        if (!keyword) {
            showToast("请输入用户 ID", "error");
            return;
        }
        setLookupLoading(true);
        try {
            const user = await lookupCoinAdjustmentTarget(keyword);
            setTargetUser(user);
        } catch (err) {
            setTargetUser(null);
            showToast(err.message || "查询用户失败", "error");
        } finally {
            setLookupLoading(false);
        }
    };
    const submitAdjustment = async (event) => {
        event.preventDefault();
        if (!targetUser?.userId) {
            showToast("请先搜索用户", "error");
            return;
        }
        let payload;
        try {
            payload = buildAdjustmentPayload(form, targetUser);
        } catch (err) {
            showToast(err.message || "金币增减参数不正确", "error");
            return;
        }
        setSubmitting(true);
        try {
            await createCoinAdjustment(payload);
            showToast("金币已调整", "success");
            setForm(emptyForm());
            setTargetUser(null);
            setDialogOpen(false);
            await query.reload();
        } catch (err) {
            showToast(err.message || "金币调整失败", "error");
        } finally {
            setSubmitting(false);
        }
    };

    return (
        <AdminListPage>
            <AdminListToolbar
                actions={
                    abilities.canCreate ? (
                        <AdminActionIconButton label="金币增减" primary onClick={openDialog}>
                            <MonetizationOnOutlined fontSize="small" />
                        </AdminActionIconButton>
                    ) : null
                }
                filters={
                    <>
                        <TimeRangeFilter value={timeRange} onChange={changeTimeRange} />
                        <AdminFilterResetButton
                            disabled={isUserIdentityFilterEmpty(userFilter) && !timeRange.startMs && !timeRange.endMs}
                            onClick={resetFilters}
                        />
                    </>
                }
            />
            <DataState error={query.error} loading={query.loading} onRetry={query.reload}>
                <AdminListBody>
                    <DataTable
                        columns={tableColumns}
                        items={items}
                        minWidth="1230px"
                        pagination={
                            total > 0
                                ? {
                                      page,
                                      pageSize: data.pageSize || pageSize,
                                      total,
                                      onPageChange: setPage,
                                  }
                                : undefined
                        }
                        rowKey={(item) => item.entryId}
                    />
                </AdminListBody>
            </DataState>
            <AdminFormDialog
                disabled={!abilities.canCreate}
                loading={submitting}
                open={dialogOpen}
                size="large"
                submitDisabled={!abilities.canCreate || submitting || !targetUser?.userId}
                submitLabel="确认"
                title="金币增减"
                onClose={closeDialog}
                onSubmit={submitAdjustment}
            >
                <AdminFormSection title="接收用户">
                    <div className={styles.lookupRow}>
                        <TextField
                            disabled={!abilities.canCreate || submitting}
                            label="用户 ID"
                            required
                            value={form.userKeyword}
                            onChange={(event) => {
                                changeForm({ userKeyword: event.target.value });
                                setTargetUser(null);
                            }}
                            onKeyDown={(event) => {
                                if (event.key === "Enter") {
                                    event.preventDefault();
                                    searchTargetUser();
                                }
                            }}
                        />
                        <Button
                            disabled={!abilities.canCreate || lookupLoading || submitting}
                            startIcon={<SearchOutlined fontSize="small" />}
                            onClick={searchTargetUser}
                        >
                            搜索
                        </Button>
                    </div>
                    {targetUser ? <TargetUserPreview user={targetUser} /> : null}
                </AdminFormSection>
                <AdminFormSection title="备注">
                    <TextField
                        disabled={!abilities.canCreate || submitting}
                        fullWidth
                        label="备注"
                        multiline
                        required
                        rows={3}
                        slotProps={{ htmlInput: { maxLength: 512 } }}
                        value={form.remark}
                        onChange={(event) => changeForm({ remark: event.target.value })}
                    />
                </AdminFormSection>
                <AdminFormSection title="金币信息">
                    <AdminFormFieldGrid columns="repeat(3, minmax(0, 1fr))">
                        <TextField
                            disabled={!abilities.canCreate || submitting}
                            label="类型"
                            required
                            select
                            value={form.mode}
                            onChange={(event) => changeForm({ mode: event.target.value })}
                        >
                            <MenuItem value="increase">增加</MenuItem>
                            <MenuItem value="decrease">扣减</MenuItem>
                        </TextField>
                        <AdminFormAmountField
                            disabled={!abilities.canCreate || submitting}
                            inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }}
                            label="发放数量"
                            required
                            unit="金币"
                            value={form.amount}
                            onChange={(event) => changeForm({ amount: event.target.value })}
                        />
                        <TextField
                            disabled={!abilities.canCreate || submitting}
                            label="发放理由"
                            required
                            select
                            value={form.reason}
                            onChange={(event) => changeForm({ reason: event.target.value })}
                        >
                            {adjustmentReasons.map((reason) => (
                                <MenuItem key={reason} value={reason}>
                                    {reason}
                                </MenuItem>
                            ))}
                        </TextField>
                    </AdminFormFieldGrid>
                </AdminFormSection>
            </AdminFormDialog>
        </AdminListPage>
    );
}

function AdjustmentUserCell({ item }) {
    const user = item.user || {};
    return <AdminUserIdentity openInAppUserDetail user={{ ...user, userId: user.userId || item.userId }} />;
}

function TargetUserPreview({ user }) {
    return <AdminUserIdentity openInAppUserDetail className={styles.targetPreview} user={user} />;
}

function AdjustmentAmount({ item }) {
    const delta = Number(item.availableDelta ?? item.amount ?? 0);
    const expense = delta < 0;
    const sign = expense ? "-" : "+";

    return (
        <span
            className={`${styles.amount} ${styles.adjustmentAmount} ${
                expense ? styles.amountExpense : styles.amountIncome
            }`}
        >
            {sign}
            {formatNumber(Math.abs(delta))}
        </span>
    );
}

function buildAdjustmentPayload(form, targetUser) {
    const rawAmount = String(form.amount || "").trim();
    if (!/^[1-9]\d*$/.test(rawAmount)) {
        throw new Error("请输入金币数量");
    }
    const amount = Number(rawAmount);
    if (!Number.isSafeInteger(amount)) {
        throw new Error("金币数量过大");
    }
    const signedAmount = form.mode === "decrease" ? -amount : amount;
    const reason = String(form.reason || "").trim();
    if (!reason) {
        throw new Error("请选择发放理由");
    }
    const remark = String(form.remark || "").trim();
    if (!remark) {
        throw new Error("请输入备注");
    }
    if (remark.length > 512) {
        throw new Error("备注不能超过 512 个字符");
    }
    return {
        amount: signedAmount,
        commandId: `coin-adjustment-${Date.now()}`,
        reason,
        remark,
        targetUserId: String(targetUser.userId),
    };
}

function operatorName(item) {
    const operator = item.operator || {};
    return operator.name || operator.username || item.operatorUserId || "-";
}

function formatNumber(value) {
    return Number(value || 0).toLocaleString("zh-CN");
}
