import ContentCopyOutlined from "@mui/icons-material/ContentCopyOutlined";
import DownloadOutlined from "@mui/icons-material/DownloadOutlined";
import PersonOutlineOutlined from "@mui/icons-material/PersonOutlineOutlined";
import Tooltip from "@mui/material/Tooltip";
import { useEffect, useMemo, useState } from "react";
import { listRechargeBills } from "@/features/payment/api";
import {
    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 { IconButton } from "@/shared/ui/IconButton.jsx";
import { createRegionColumnFilter } from "@/shared/ui/RegionFilterControl.jsx";
import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx";
import { useRegionOptions } from "@/shared/hooks/useRegionOptions.js";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
import { formatMillis } from "@/shared/utils/time.js";
import styles from "@/features/payment/payment.module.css";

const pageSize = 50;
const exportPageSize = 100;
const statusOptions = [
    ["", "全部状态"],
    ["succeeded", "成功"],
];
const rechargeTypeOptions = [
    ["", "全部途径"],
    ["coin_seller_transfer", "币商充值"],
    ["google_play_recharge", "谷歌充值"],
];

const columns = [
    {
        key: "bill",
        label: "账单",
        width: "minmax(82px, 0.35fr)",
        render: (bill) => <BillCopyButton value={bill.transactionId} />,
    },
    {
        key: "userId",
        label: "用户信息",
        width: "minmax(190px, 1fr)",
        render: (bill) => <BillUser bill={bill} type="user" />,
    },
    {
        key: "sellerUserId",
        label: "币商信息",
        width: "minmax(190px, 1fr)",
        render: (bill) => <BillUser bill={bill} type="seller" />,
    },
    {
        key: "coinAmount",
        label: "金币",
        width: "minmax(120px, 0.6fr)",
        render: (bill) => formatNumber(bill.coinAmount),
    },
    {
        key: "money",
        label: "金额",
        width: "minmax(120px, 0.6fr)",
        render: (bill) => billMoneyText(bill),
    },
    {
        key: "region",
        label: "国家/区域",
        width: "minmax(150px, 0.75fr)",
        render: (bill, _index, context) => (
            <Stack
                primary={billCountryName(bill)}
                secondary={regionName(bill.targetRegionId, context?.regionNames)}
            />
        ),
    },
    {
        key: "rechargeType",
        label: "充值途径",
        width: "minmax(130px, 0.7fr)",
        render: (bill) => rechargeTypeLabel(bill.rechargeType),
    },
    {
        key: "status",
        label: "状态",
        width: "minmax(100px, 0.55fr)",
        render: (bill) => <StatusBadge status={bill.status} />,
    },
    {
        key: "time",
        label: "创建时间",
        width: "minmax(160px, 0.8fr)",
        render: (bill) => formatMillis(bill.createdAtMs),
    },
];

export function PaymentBillListPage() {
    const [page, setPage] = useState(1);
    const [keyword, setKeyword] = useState("");
    const [status, setStatus] = useState("");
    const [rechargeType, setRechargeType] = useState("");
    const [regionId, setRegionId] = useState("");
    const [userId, setUserId] = useState("");
    const [sellerUserId, setSellerUserId] = useState("");
    const [timeRange, setTimeRange] = useState({ endMs: "", startMs: "" });
    const [exporting, setExporting] = useState(false);
    const { loadingRegions, regionOptions } = useRegionOptions();
    const { showToast } = useToast();
    const regionNames = useMemo(() => regionNameMap(regionOptions), [regionOptions]);

    const filters = useMemo(
        () => ({
            end_at_ms: timeRange.endMs,
            keyword,
            recharge_type: rechargeType,
            region_id: regionId,
            seller_user_id: sellerUserId,
            start_at_ms: timeRange.startMs,
            status,
            user_id: userId,
        }),
        [keyword, rechargeType, regionId, sellerUserId, status, timeRange.endMs, timeRange.startMs, userId],
    );
    const query = usePaginatedQuery({
        errorMessage: "获取账单列表失败",
        fetcher: listRechargeBills,
        filters,
        page,
        pageSize,
        queryKey: ["payment-bills", filters, page],
    });
    const data = query.data || { items: [], total: 0, page, pageSize };
    const items = data.items || [];
    const total = data.total || 0;

    const resetPage = (setter) => (value) => {
        setter(value);
        setPage(1);
    };
    const changeTimeRange = (value) => {
        setTimeRange(value);
        setPage(1);
    };
    const downloadBills = async () => {
        setExporting(true);
        try {
            const bills = await fetchAllRechargeBills(filters);
            downloadTextFile(createBillsCsv(bills, regionNames), `hyapp-payment-bills-${filenameTimestamp()}.csv`);
            showToast(`已导出 ${bills.length} 条账单`, "success");
        } catch (err) {
            showToast(err?.message || "导出账单失败", "error");
        } finally {
            setExporting(false);
        }
    };

    const tableColumns = columns.map((column) => {
        if (column.key === "bill") {
            return {
                ...column,
                filter: createTextColumnFilter({
                    placeholder: "搜索账单号、命令号、外部单号",
                    value: keyword,
                    onChange: resetPage(setKeyword),
                }),
            };
        }
        if (column.key === "userId") {
            return {
                ...column,
                filter: createTextColumnFilter({
                    placeholder: "搜索用户 ID",
                    value: userId,
                    onChange: (value) => resetPage(setUserId)(digitsOnly(value)),
                }),
            };
        }
        if (column.key === "sellerUserId") {
            return {
                ...column,
                filter: createTextColumnFilter({
                    placeholder: "搜索币商 ID",
                    value: sellerUserId,
                    onChange: (value) => resetPage(setSellerUserId)(digitsOnly(value)),
                }),
            };
        }
        if (column.key === "rechargeType") {
            return {
                ...column,
                filter: createOptionsColumnFilter({
                    options: rechargeTypeOptions,
                    placeholder: "搜索充值途径",
                    value: rechargeType,
                    onChange: resetPage(setRechargeType),
                }),
            };
        }
        if (column.key === "region") {
            return {
                ...column,
                filter: createRegionColumnFilter({
                    loading: loadingRegions,
                    options: regionOptions,
                    value: regionId,
                    onChange: resetPage(setRegionId),
                }),
            };
        }
        if (column.key === "status") {
            return {
                ...column,
                filter: createOptionsColumnFilter({
                    options: statusOptions,
                    placeholder: "搜索状态",
                    value: status,
                    onChange: resetPage(setStatus),
                }),
            };
        }
        return column;
    });

    return (
        <AdminListPage>
            <AdminListToolbar
                actions={
                    <Button
                        disabled={exporting}
                        startIcon={<DownloadOutlined fontSize="small" />}
                        onClick={downloadBills}
                    >
                        {exporting ? "导出中" : "导出"}
                    </Button>
                }
                filters={
                    <TimeRangeFilter
                        disabled={exporting}
                        label="创建时间"
                        value={timeRange}
                        onChange={changeTimeRange}
                    />
                }
            />
            <DataState error={query.error} loading={query.loading} onRetry={query.reload}>
                <AdminListBody>
                    <DataTable
                        columns={tableColumns}
                        context={{ regionNames }}
                        items={items}
                        minWidth="1380px"
                        pagination={
                            total > 0
                                ? {
                                      page,
                                      pageSize: data.pageSize || pageSize,
                                      total,
                                      onPageChange: setPage,
                                  }
                                : undefined
                        }
                        rowKey={(bill) => bill.transactionId}
                    />
                </AdminListBody>
            </DataState>
        </AdminListPage>
    );
}

function Stack({ primary, secondary }) {
    return (
        <div className="cell-stack">
            <span>{primary || "-"}</span>
            <span className="muted">{secondary || "-"}</span>
        </div>
    );
}

function BillCopyButton({ value }) {
    const [copied, setCopied] = useState(false);

    useEffect(() => {
        if (!copied) {
            return undefined;
        }
        const timer = window.setTimeout(() => setCopied(false), 1200);
        return () => window.clearTimeout(timer);
    }, [copied]);

    const copyBill = async () => {
        if (!value) {
            return;
        }
        await copyText(String(value));
        setCopied(true);
    };

    return (
        <Tooltip arrow title={copied ? "已复制" : "复制账单"}>
            <span className={styles.copyWrap}>
                <IconButton disabled={!value} label="复制账单" onClick={copyBill}>
                    <ContentCopyOutlined fontSize="small" />
                </IconButton>
            </span>
        </Tooltip>
    );
}

function BillUser({ bill, type }) {
    const fallbackId = type === "seller" ? bill.sellerUserId : bill.userId;
    const profile = normalizeBillUser(type === "seller" ? bill.seller : bill.user, fallbackId);
    if (!profile.userId && !profile.displayUserId && !profile.username) {
        return "-";
    }

    const shortId = profile.displayUserId || profile.userId || "-";
    const name = profile.username || "-";
    return (
        <div className={styles.identity}>
            <span className={styles.avatar}>
                {profile.avatar ? <img alt="" src={profile.avatar} /> : <PersonOutlineOutlined fontSize="small" />}
            </span>
            <span className={styles.identityText}>
                <span className={styles.identityId}>{name}</span>
                <span className={styles.identityName}>{shortId}</span>
            </span>
        </div>
    );
}

function StatusBadge({ status }) {
    const tone = status === "succeeded" ? "succeeded" : status === "failed" ? "danger" : "stopped";
    return (
        <span className={`status-badge status-badge--${tone}`}>
            <span className="status-point" />
            {statusLabel(status)}
        </span>
    );
}

function rechargeTypeLabel(value) {
    return rechargeTypeOptions.find(([optionValue]) => optionValue === value)?.[1] || value || "-";
}

function statusLabel(value) {
    if (value === "succeeded") {
        return "成功";
    }
    if (value === "failed") {
        return "失败";
    }
    return value || "-";
}

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

function formatMoney(value, currency = "USD") {
    if (!(value === 0 || value)) {
        return "-";
    }
    return `${currency || "USD"} ${(Number(value) / 100).toLocaleString("zh-CN", {
        maximumFractionDigits: 2,
        minimumFractionDigits: 2,
    })}`;
}

function billMoneyText(bill) {
    if (bill?.rechargeType === "coin_seller_transfer") {
        return "";
    }
    return formatMoney(bill?.usdMinorAmount, bill?.currencyCode);
}

function normalizeBillUser(profile, fallbackId) {
    const source = profile || {};
    return {
        avatar: source.avatar || "",
        countryCode: source.countryCode || source.country_code || "",
        countryDisplayName: source.countryDisplayName || source.country_display_name || "",
        countryName: source.countryName || source.country_name || "",
        displayUserId: source.displayUserId || source.display_user_id || "",
        userId: String(source.userId || source.user_id || fallbackId || ""),
        username: source.username || source.name || "",
    };
}

function billCountryName(bill) {
    const user = normalizeBillUser(bill?.user, bill?.userId);
    return user.countryDisplayName || user.countryName || user.countryCode || "-";
}

function regionNameMap(regionOptions = []) {
    return Object.fromEntries(
        regionOptions.map((region) => [String(region.regionId || region.value), region.name || region.label]),
    );
}

function regionName(regionId, regionNames = {}) {
    if (!regionId) {
        return "-";
    }
    return regionNames[String(regionId)] || `区域 ${regionId}`;
}

async function fetchAllRechargeBills(filters) {
    const items = [];
    let page = 1;
    while (true) {
        const data = await listRechargeBills({ ...filters, page, page_size: exportPageSize });
        const batch = Array.isArray(data?.items) ? data.items : [];
        items.push(...batch);

        const total = Number(data?.total || 0);
        if (!batch.length || (total > 0 && items.length >= total) || batch.length < exportPageSize) {
            return items;
        }
        page += 1;
    }
}

function createBillsCsv(bills, regionNames) {
    const headers = [
        "账单",
        "命令号",
        "外部单号",
        "用户长ID",
        "用户短ID",
        "用户名称",
        "币商长ID",
        "币商短ID",
        "币商名称",
        "金币",
        "金额",
        "国家",
        "区域",
        "充值途径",
        "状态",
        "创建时间",
    ];
    const rows = bills.map((bill) => {
        const user = normalizeBillUser(bill.user, bill.userId);
        const seller = normalizeBillUser(bill.seller, bill.sellerUserId);
        return [
            bill.transactionId,
            bill.commandId,
            bill.externalRef,
            user.userId,
            user.displayUserId,
            user.username,
            seller.userId,
            seller.displayUserId,
            seller.username,
            formatNumber(bill.coinAmount),
            billMoneyText(bill),
            billCountryName(bill),
            regionName(bill.targetRegionId, regionNames),
            rechargeTypeLabel(bill.rechargeType),
            statusLabel(bill.status),
            formatMillis(bill.createdAtMs),
        ];
    });
    return [headers, ...rows].map((row) => row.map(csvCell).join(",")).join("\n");
}

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

function downloadTextFile(content, filename) {
    const blob = new Blob([`\uFEFF${content}`], { type: "text/csv;charset=utf-8" });
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = filename;
    link.click();
    window.URL.revokeObjectURL(url);
}

async function copyText(value) {
    if (navigator.clipboard?.writeText) {
        try {
            await navigator.clipboard.writeText(value);
            return;
        } catch {
            // 浏览器可能因权限或非安全上下文拒绝 Clipboard API，这里退回同步复制。
        }
    }

    const input = document.createElement("textarea");
    input.value = value;
    input.setAttribute("readonly", "");
    input.style.position = "fixed";
    input.style.opacity = "0";
    document.body.appendChild(input);
    input.select();
    document.execCommand("copy");
    input.remove();
}

function filenameTimestamp() {
    const now = new Date();
    return [
        now.getFullYear(),
        pad2(now.getMonth() + 1),
        pad2(now.getDate()),
        "-",
        pad2(now.getHours()),
        pad2(now.getMinutes()),
        pad2(now.getSeconds()),
    ].join("");
}

function pad2(value) {
    return String(value).padStart(2, "0");
}

function digitsOnly(value) {
    return value.replace(/\D/g, "");
}
