import CardGiftcardOutlined from "@mui/icons-material/CardGiftcardOutlined";
import Inventory2Outlined from "@mui/icons-material/Inventory2Outlined";
import SearchOutlined from "@mui/icons-material/SearchOutlined";
import Checkbox from "@mui/material/Checkbox";
import InputAdornment from "@mui/material/InputAdornment";
import Tab from "@mui/material/Tab";
import Tabs from "@mui/material/Tabs";
import TextField from "@mui/material/TextField";
import { useMemo, useState } from "react";
import {
    resourcePriceTypeLabels,
    resourceTypeFilters,
    resourceTypeLabels,
} from "@/features/resources/constants.js";
import { Button } from "@/shared/ui/Button.jsx";
import { SideDrawer } from "@/shared/ui/SideDrawer.jsx";
import styles from "@/features/resources/components/GiftResourceSelectDrawer.module.css";

const drawerZIndex = 1600;

export function GiftResourceSelectField({
    disabled = false,
    drawerTitle = "选择资源",
    excludedResourceIds = [],
    giftTypes = [],
    gifts = [],
    label = "资源",
    loading = false,
    onChange = () => {},
    placeholder = "请选择资源",
    required = true,
    resources = [],
    selectedResourceIds = [],
}) {
    const [open, setOpen] = useState(false);
    const [query, setQuery] = useState("");
    const [activeType, setActiveType] = useState("");
    const selectedIds = useMemo(() => selectedResourceIds.map((id) => String(id)), [selectedResourceIds]);
    const selectedIdSet = useMemo(() => new Set(selectedIds), [selectedIds]);
    const excludedIds = useMemo(() => excludedResourceIds.map((id) => String(id)), [excludedResourceIds]);
    const excludedIdSet = useMemo(() => new Set(excludedIds), [excludedIds]);
    const giftsByResourceId = useMemo(() => {
        const items = new Map();
        gifts.forEach((gift) => {
            if (gift?.resourceId) {
                items.set(String(gift.resourceId), gift);
            }
        });
        return items;
    }, [gifts]);
    const resourceItems = useMemo(
        () => buildResourceItems(resources, giftsByResourceId),
        [giftsByResourceId, resources],
    );
    const visibleResourceItems = useMemo(
        () =>
            resourceItems.filter((item) => {
                const resourceId = String(item.resource.resourceId);
                return !excludedIdSet.has(resourceId) || selectedIdSet.has(resourceId);
            }),
        [excludedIdSet, resourceItems, selectedIdSet],
    );
    const visibleResources = useMemo(() => visibleResourceItems.map((item) => item.resource), [visibleResourceItems]);
    const itemCounts = useMemo(() => countResourceItems(visibleResourceItems), [visibleResourceItems]);
    const categoryOptions = useMemo(
        () => buildCategoryOptions(giftTypes, visibleResources, visibleResourceItems),
        [giftTypes, visibleResourceItems, visibleResources],
    );
    const activeCategory = categoryOptions.some((item) => item.value === activeType)
        ? activeType
        : categoryOptions.find((item) => itemCounts.get(item.value))?.value || categoryOptions[0]?.value || "";
    const resourcesById = useMemo(() => {
        const items = new Map();
        resourceItems.forEach((item) => {
            items.set(String(item.resource.resourceId), item);
        });
        return items;
    }, [resourceItems]);
    const displayValue = useMemo(() => {
        if (!selectedIds.length) {
            return "";
        }
        const labels = selectedIds.map((resourceId) => resourceName(resourcesById.get(resourceId), resourceId));
        if (labels.length <= 3) {
            return labels.join("，");
        }
        return `${labels.slice(0, 3).join("，")} 等 ${labels.length} 个资源`;
    }, [resourcesById, selectedIds]);
    const filteredResources = useMemo(() => {
        const keyword = query.trim().toLowerCase();
        return visibleResourceItems.filter((item) => {
            if (activeCategory && item.categoryValue !== activeCategory) {
                return false;
            }
            if (!keyword) {
                return true;
            }
            const resource = item.resource || {};
            const gift = item.gift || {};
            const haystack = [
                resource.name,
                resource.resourceCode,
                resource.resourceId,
                resource.resourceType,
                gift.name,
                gift.giftId,
                gift.giftTypeCode,
            ]
                .filter(Boolean)
                .join(" ")
                .toLowerCase();
            return haystack.includes(keyword);
        });
    }, [activeCategory, query, visibleResourceItems]);

    const openDrawer = () => {
        if (!disabled && !loading) {
            setOpen(true);
        }
    };

    const toggleResource = (item) => {
        if (!item?.resource?.resourceId || disabled) {
            return;
        }
        const resourceId = String(item.resource.resourceId);
        if (selectedIdSet.has(resourceId)) {
            onChange(selectedIds.filter((selectedId) => selectedId !== resourceId));
            return;
        }
        onChange([...selectedIds, resourceId]);
    };

    return (
        <>
            <TextField
                fullWidth
                className={styles.field}
                disabled={disabled || loading}
                label={label}
                placeholder={loading ? "资源加载中" : placeholder}
                required={required}
                slotProps={{ htmlInput: { "aria-haspopup": "dialog", readOnly: true, role: "button" } }}
                value={displayValue}
                onClick={openDrawer}
                onKeyDown={(event) => {
                    if (event.key === "Enter" || event.key === " ") {
                        event.preventDefault();
                        openDrawer();
                    }
                }}
            />
            <SideDrawer
                actions={
                    <Button type="button" variant="primary" onClick={() => setOpen(false)}>
                        完成
                    </Button>
                }
                className={styles.drawer}
                contentClassName={styles.drawerBody}
                drawerProps={{ sx: { zIndex: drawerZIndex } }}
                open={open}
                title={drawerTitle}
                width="wide"
                onClose={() => setOpen(false)}
            >
                <div className={styles.filters}>
                    <TextField
                        className={styles.search}
                        placeholder="搜索资源名称、ID"
                        slotProps={{
                            input: {
                                startAdornment: (
                                    <InputAdornment position="start">
                                        <SearchOutlined fontSize="small" />
                                    </InputAdornment>
                                ),
                            },
                        }}
                        value={query}
                        onChange={(event) => setQuery(event.target.value)}
                    />
                    {categoryOptions.length ? (
                        <Tabs
                            aria-label="资源分类"
                            className={styles.tabs}
                            value={activeCategory}
                            variant="scrollable"
                            onChange={(_, value) => setActiveType(value)}
                        >
                            {categoryOptions.map((item) => (
                                <Tab key={item.value} label={item.label} value={item.value} />
                            ))}
                        </Tabs>
                    ) : null}
                </div>
                <div className={styles.grid}>
                    {filteredResources.map((item) => {
                        const resourceId = String(item.resource.resourceId);
                        const selected = selectedIdSet.has(resourceId);
                        const name = resourceName(item);
                        return (
                            <button
                                aria-pressed={selected}
                                className={[styles.card, selected ? styles.cardSelected : ""]
                                    .filter(Boolean)
                                    .join(" ")}
                                key={resourceId}
                                type="button"
                                onClick={() => toggleResource(item)}
                            >
                                <Checkbox
                                    checked={selected}
                                    className={styles.checkbox}
                                    inputProps={{
                                        "aria-label": `${selected ? "取消选择" : "选择"} ${name}`,
                                        readOnly: true,
                                    }}
                                    tabIndex={-1}
                                />
                                <ResourceThumb item={item} />
                                <span className={styles.name}>{name}</span>
                                <span className={styles.meta}>
                                    {item.resource.resourceCode || `资源 ${item.resource.resourceId || "-"}`}
                                </span>
                                <span className={styles.tags}>
                                    <span className={styles.tag}>{categoryLabel(item, categoryOptions)}</span>
                                    <span className={styles.tag}>{resourcePriceLabel(item)}</span>
                                </span>
                            </button>
                        );
                    })}
                    {!filteredResources.length ? <div className={styles.empty}>当前无可选资源</div> : null}
                </div>
            </SideDrawer>
        </>
    );
}

function buildResourceItems(resources, giftsByResourceId) {
    const seen = new Set();
    return resources
        .filter((resource) => resource?.resourceId)
        .filter((resource) => {
            const resourceId = String(resource.resourceId);
            if (seen.has(resourceId)) {
                return false;
            }
            seen.add(resourceId);
            return true;
        })
        .map((resource) => {
            const gift = giftsByResourceId.get(String(resource.resourceId));
            const category = categoryForResource(resource, gift);
            return {
                categoryLabel: category.label,
                categoryValue: category.value,
                gift,
                resource,
            };
        });
}

function buildCategoryOptions(giftTypes, resources, resourceItems) {
    const options = [];
    const resourceTypes = new Set(resources.map((resource) => resource?.resourceType).filter(Boolean));
    resourceTypeFilters.forEach(([type, label], index) => {
        if (!type) {
            return;
        }
        if (type === "gift") {
            options.push(...buildGiftCategoryOptions(giftTypes, resourceItems, index));
            if (resourceItems.some((item) => item.categoryValue === "resource:gift")) {
                options.push({ label: resourceTypeLabels.gift || "礼物", order: index * 100, value: "resource:gift" });
            }
            return;
        }
        options.push({ label, order: index * 100, value: `resource:${type}` });
        resourceTypes.delete(type);
    });
    resourceTypes.forEach((type) => {
        options.push({
            label: resourceTypeLabels[type] || type,
            order: options.length * 100,
            value: `resource:${type}`,
        });
    });
    return dedupeCategories(options);
}

function buildGiftCategoryOptions(giftTypes, resourceItems, resourceTypeOrder) {
    const options = [];
    const knownGiftTypes = new Set();
    giftTypes
        .filter((item) => item?.status !== "disabled")
        .forEach((item) => {
            const value = String(item.tabKey || item.typeCode || "").trim();
            if (!value) {
                return;
            }
            knownGiftTypes.add(value);
            options.push({
                label: item.displayName || item.tabName || value,
                order: resourceTypeOrder * 100 + Number(item.sortOrder || 0),
                value: `gift:${value}`,
            });
        });
    resourceItems.forEach((item) => {
        const value = String(item.gift?.giftTypeCode || "").trim();
        if (value && !knownGiftTypes.has(value)) {
            knownGiftTypes.add(value);
            options.push({
                label: value,
                order: resourceTypeOrder * 100 + 1000 + options.length,
                value: `gift:${value}`,
            });
        }
    });
    return options;
}

function dedupeCategories(options) {
    const byValue = new Map();
    options.forEach((item) => {
        if (!byValue.has(item.value)) {
            byValue.set(item.value, item);
        }
    });
    return Array.from(byValue.values()).sort((left, right) => left.order - right.order);
}

function categoryForResource(resource, gift) {
    if (resource.resourceType === "gift" && gift?.giftTypeCode) {
        return { value: `gift:${gift.giftTypeCode}` };
    }
    const type = resource.resourceType || "unknown";
    return {
        label: resourceTypeLabels[type] || type,
        value: `resource:${type}`,
    };
}

function categoryLabel(item, categoryOptions) {
    return categoryOptions.find((option) => option.value === item.categoryValue)?.label || item.categoryLabel || "资源";
}

function countResourceItems(resourceItems) {
    const counts = new Map();
    resourceItems.forEach((item) => {
        counts.set(item.categoryValue, (counts.get(item.categoryValue) || 0) + 1);
    });
    return counts;
}

function ResourceThumb({ item }) {
    const imageUrl = imageURL(item.resource.previewUrl || item.resource.assetUrl || item.resource.animationUrl);
    return (
        <span className={styles.thumb}>
            {imageUrl ? (
                <img alt="" src={imageUrl} />
            ) : item.resource.resourceType === "gift" ? (
                <CardGiftcardOutlined fontSize="small" />
            ) : (
                <Inventory2Outlined fontSize="small" />
            )}
        </span>
    );
}

function resourceName(item, fallbackResourceId = "") {
    const resource = item?.resource || {};
    const gift = item?.gift || {};
    return gift.name || resource.name || resource.resourceCode || `资源 #${fallbackResourceId || resource.resourceId || "-"}`;
}

function resourcePriceLabel(item = {}) {
    const resource = item.resource || {};
    const gift = item.gift || {};
    if (resource.resourceType === "gift" && (gift.chargeAssetType === "COIN" || Number(gift.coinPrice || 0) > 0)) {
        return `${formatNumber(gift.coinPrice)}金币`;
    }
    if (resource.priceType === "coin") {
        return `${formatNumber(resource.coinPrice)}金币`;
    }
    if (resource.priceType === "free") {
        return resourcePriceTypeLabels.free;
    }
    return "未配置价格";
}

function imageURL(value) {
    const url = String(value || "").trim();
    return /\.(avif|gif|jpe?g|png|webp)(\?|#|$)/i.test(url) ? url : "";
}

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