import Add from "@mui/icons-material/Add";
import EditOutlined from "@mui/icons-material/EditOutlined";
import FileUploadOutlined from "@mui/icons-material/FileUploadOutlined";
import HelpOutlineOutlined from "@mui/icons-material/HelpOutlineOutlined";
import Inventory2Outlined from "@mui/icons-material/Inventory2Outlined";
import CircularProgress from "@mui/material/CircularProgress";
import MenuItem from "@mui/material/MenuItem";
import { AdminSwitch } from "@/shared/ui/AdminSwitch.jsx";
import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import { useRef, useState } from "react";
import {
    AdminFormDialog,
    AdminFormFieldGrid,
    AdminFormSection,
    AdminFormSwitchField,
} from "@/shared/ui/AdminFormDialog.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { UploadField } from "@/shared/ui/UploadField.jsx";
import {
    AdminActionIconButton,
    AdminListBody,
    AdminListPage,
    AdminRowActions,
    AdminListToolbar,
} from "@/shared/ui/AdminListLayout.jsx";
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
import { formatMillis } from "@/shared/utils/time.js";
import {
    badgeKindLabels,
    badgeKindOptions,
    badgeLevelTrackLabels,
    badgeLevelTrackOptions,
    badgeFormLabels,
    badgeFormOptions,
    resourceBatchUploadRoleLabels,
    resourceStatusFilters,
    resourcePriceTypeLabels,
    resourcePriceTypeOptions,
    resourceTypeFilters,
    resourceTypeLabels,
} from "@/features/resources/constants.js";
import { createResource } from "@/features/resources/api";
import {
    parseResourceFolderFiles,
    resourceBatchUploadSize,
    resourcePlanToPayload,
    translateResourceCodes,
} from "@/features/resources/batchUpload.js";
import { useResourceListPage } from "@/features/resources/hooks/useResourcePages.js";
import {
    detectProfileCardLayout,
    mergeProfileCardLayoutMetadata,
    profileCardLayoutFromMetadata,
} from "@/features/resources/profileCardLayout.js";
import { uploadFilesBatch } from "@/shared/api/upload";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import styles from "@/features/resources/resources.module.css";

const resourceTypeOptions = resourceTypeFilters.filter(([value]) => value && value !== "emoji_pack");

const baseColumns = [
    {
        key: "resource",
        label: "资源",
        width: "minmax(260px, 1.5fr)",
        render: (resource) => <ResourceIdentity resource={resource} />,
    },
    {
        key: "type",
        label: "类型",
        width: "minmax(120px, 0.7fr)",
        render: (resource) => resourceTypeLabels[resource.resourceType] || resource.resourceType || "-",
    },
    {
        key: "price",
        label: "价格",
        width: "minmax(120px, 0.65fr)",
        render: (resource) => resourcePriceLabel(resource),
    },
    {
        key: "badgeForm",
        label: "徽章属性",
        width: "minmax(120px, 0.65fr)",
        render: (resource) => badgeFormLabel(resource),
    },
    {
        key: "status",
        label: "状态",
        width: "minmax(92px, 0.55fr)",
    },
    {
        key: "time",
        label: "更新时间",
        width: "minmax(170px, 0.9fr)",
        render: (resource) => formatMillis(resource.updatedAtMs || resource.createdAtMs),
    },
    {
        key: "actions",
        label: "操作",
        width: "minmax(76px, 0.4fr)",
    },
];

export function ResourceListPage() {
    const page = useResourceListPage();
    const { showToast } = useToast();
    const folderInputRef = useRef(null);
    const [batchOpen, setBatchOpen] = useState(false);
    const [batchPlan, setBatchPlan] = useState({ errors: [], resources: [] });
    const [batchProgress, setBatchProgress] = useState({ label: "", running: false });
    const items = page.data.items || [];
    const total = page.data.total || 0;
    const createDisabled = !page.abilities.canCreate || !page.abilities.canUpload;
    const columns = baseColumns.map((column) =>
        column.key === "resource"
            ? {
                  ...column,
                  filter: createTextColumnFilter({
                      placeholder: "搜索资源名称、资源编码",
                      value: page.query,
                      onChange: page.changeQuery,
                  }),
              }
            : column.key === "type"
              ? {
                    ...column,
                    filter: createOptionsColumnFilter({
                        options: resourceTypeFilters,
                        placeholder: "搜索类型",
                        value: page.resourceType,
                        onChange: page.changeResourceType,
                    }),
                }
              : column.key === "status"
                ? {
                      ...column,
                      filter: createOptionsColumnFilter({
                          options: resourceStatusFilters,
                          placeholder: "搜索状态",
                          value: page.status,
                          onChange: page.changeStatus,
                      }),
                      render: (resource) => <ResourceStatusSwitch page={page} resource={resource} />,
                  }
                : column.key === "actions"
                  ? {
                        ...column,
                        render: (resource) => <ResourceRowActions page={page} resource={resource} />,
                    }
                  : column,
    );

    const openBatchDialog = () => {
        setBatchPlan({ errors: [], resources: [] });
        setBatchProgress({ label: "", running: false });
        setBatchOpen(true);
    };

    const closeBatchDialog = () => {
        if (!batchProgress.running) {
            setBatchOpen(false);
        }
    };

    const handleFolderChange = (event) => {
        const plan = parseResourceFolderFiles(event.target.files);
        event.target.value = "";
        setBatchPlan(plan);
        setBatchProgress({ label: "", running: false });
    };

    const submitBatchUpload = async (event) => {
        event.preventDefault();
        if (!batchPlan.resources.length || batchProgress.running) {
            return;
        }

        const resources = batchPlan.resources.map((item) => ({ ...item }));
        const uploadEntries = resources.flatMap((resource, resourceIndex) => [
            { file: resource.coverFile, resourceIndex, role: "cover" },
            { file: resource.animationFile, resourceIndex, role: "animation" },
        ]);

        setBatchProgress({ label: "解析资料卡内容高度", running: true });
        try {
            for (const resource of resources) {
                if (resource.resourceType !== "profile_card") {
                    continue;
                }
                try {
                    const layout = await detectProfileCardLayout(resource.animationFile);
                    resource.metadataJson = mergeProfileCardLayoutMetadata(resource.metadataJson, layout);
                } catch {
                    showToast(`${resource.name} 内容高度解析失败`, "error");
                }
            }

            setBatchProgress({ label: "上传素材 0/" + uploadEntries.length, running: true });
            for (let index = 0; index < uploadEntries.length; index += resourceBatchUploadSize) {
                const chunk = uploadEntries.slice(index, index + resourceBatchUploadSize);
                setBatchProgress({
                    label: `上传素材 ${index + 1}-${index + chunk.length}/${uploadEntries.length}`,
                    running: true,
                });
                const results = await uploadFilesBatch(chunk.map((entry) => entry.file));
                results.forEach((result, resultIndex) => {
                    const entry = chunk[resultIndex];
                    resources[entry.resourceIndex][entry.role === "cover" ? "coverUrl" : "animationUrl"] = result.url;
                });
            }

            setBatchProgress({ label: "翻译资源编码", running: true });
            const translatedResources = await translateResourceCodes(resources);

            for (let index = 0; index < translatedResources.length; index += 1) {
                setBatchProgress({ label: `创建资源 ${index + 1}/${translatedResources.length}`, running: true });
                await createResource(resourcePlanToPayload(translatedResources[index]));
            }

            showToast(`批量上传完成，共创建 ${translatedResources.length} 个资源`, "success");
            setBatchOpen(false);
            setBatchPlan({ errors: [], resources: [] });
            await page.reload();
        } catch (err) {
            showToast(err.message || "批量上传失败", "error");
        } finally {
            setBatchProgress({ label: "", running: false });
        }
    };

    return (
        <AdminListPage>
            <AdminListToolbar
                actions={
                    page.abilities.canCreate ? (
                        <>
                            <AdminActionIconButton
                                disabled={createDisabled}
                                label="批量上传资源"
                                onClick={openBatchDialog}
                            >
                                <FileUploadOutlined fontSize="small" />
                            </AdminActionIconButton>
                            <AdminActionIconButton label="添加资源" primary onClick={page.openCreateResource}>
                                <Add fontSize="small" />
                            </AdminActionIconButton>
                        </>
                    ) : null
                }
            />
            <DataState error={page.error} loading={page.loading} onRetry={page.reload}>
                <AdminListBody>
                    <DataTable
                        columns={columns}
                        items={items}
                        minWidth="940px"
                        pagination={
                            total > 0
                                ? {
                                      page: page.page,
                                      pageSize: page.data.pageSize || 50,
                                      total,
                                      onPageChange: page.setPage,
                                  }
                                : undefined
                        }
                        rowKey={(resource) => resource.resourceId}
                    />
                </AdminListBody>
            </DataState>
            <ResourceFormDialog
                disabled={page.activeAction === "edit" ? !page.abilities.canUpdate : createDisabled}
                form={page.form}
                loading={
                    page.activeAction === "edit"
                        ? page.loadingAction === "resource-edit"
                        : page.loadingAction === "resource-create"
                }
                mode={page.activeAction === "edit" ? "edit" : "create"}
                open={page.activeAction === "create" || page.activeAction === "edit"}
                setForm={page.setForm}
                uploadDisabled={!page.abilities.canUpload}
                onClose={page.closeAction}
                onSubmit={page.submitResource}
            />
            <ResourceBatchUploadDialog
                disabled={createDisabled}
                fileInputRef={folderInputRef}
                open={batchOpen}
                plan={batchPlan}
                progress={batchProgress}
                onClose={closeBatchDialog}
                onFileChange={handleFolderChange}
                onSubmit={submitBatchUpload}
            />
        </AdminListPage>
    );
}

function ResourceBatchUploadDialog({ disabled, fileInputRef, onClose, onFileChange, onSubmit, open, plan, progress }) {
    const submitDisabled = disabled || progress.running || !plan.resources.length;

    return (
        <AdminFormDialog
            loading={progress.running}
            open={open}
            size="wide"
            submitDisabled={submitDisabled}
            submitLabel="开始上传"
            title="批量上传资源"
            onClose={onClose}
            onSubmit={onSubmit}
        >
            <AdminFormSection
                actions={
                    <div className={styles.batchActions}>
                        <Tooltip arrow placement="top" title={<ResourceBatchRules />}>
                            <span className={styles.batchHelp} aria-label="文件规则" role="button" tabIndex={0}>
                                <HelpOutlineOutlined fontSize="small" />
                            </span>
                        </Tooltip>
                        <button
                            className={styles.batchPickButton}
                            disabled={disabled || progress.running}
                            type="button"
                            onClick={() => fileInputRef.current?.click()}
                        >
                            <FileUploadOutlined fontSize="small" />
                            选择文件夹
                        </button>
                    </div>
                }
                title="文件夹资源"
            >
                <input
                    ref={fileInputRef}
                    className={styles.batchInput}
                    directory=""
                    multiple
                    type="file"
                    webkitdirectory=""
                    onChange={onFileChange}
                />
                {progress.running ? (
                    <div className={styles.batchProgress}>
                        <CircularProgress color="inherit" size={16} />
                        {progress.label}
                    </div>
                ) : null}
                <ResourceBatchPreview resources={plan.resources} />
            </AdminFormSection>
        </AdminFormDialog>
    );
}

function ResourceBatchRules() {
    return (
        <div className={styles.batchRules}>
            <div>只读取符合命名规则且同时存在 cover/animation 的资源，其他文件会被忽略。</div>
            <div>头像框_名称_价格_天数_cover / animation</div>
            <div>坐骑_名称_价格_天数_cover / animation</div>
            <div>礼物_名称_价格_cover / animation</div>
            <div>气泡_名称_cover / animation</div>
            <div>勋章_名称_长_cover / animation</div>
            <div>飘窗_名称_cover / animation</div>
            <div>mic声波_名称_cover / animation</div>
            <div>背景卡_名称_cover / animation</div>
            <div>天数字段会忽略；勋章不写“长”时按短徽章处理。</div>
            <div>服务端单批最多上传 10 个素材，前端会自动分批串行上传。</div>
        </div>
    );
}

function ResourceBatchPreview({ resources }) {
    if (!resources.length) {
        return <div className={styles.batchEmpty}>尚未选择资源文件夹</div>;
    }

    return (
        <div className={styles.batchTable}>
            <div className={styles.batchTableHead}>
                <span>资源</span>
                <span>类型</span>
                <span>价格</span>
                <span>素材</span>
            </div>
            {resources.map((resource) => (
                <div className={styles.batchTableRow} key={resource.resourceCode}>
                    <span>{resource.name}</span>
                    <span>{resourceTypeLabels[resource.resourceType] || resource.resourceType}</span>
                    <span>{resource.price > 0 ? `金币 ${resource.price}` : "免费"}</span>
                    <span>
                        {resourceBatchUploadRoleLabels.cover} / {resourceBatchUploadRoleLabels.animation}
                    </span>
                </div>
            ))}
        </div>
    );
}

function ResourceRowActions({ page, resource }) {
    return (
        <AdminRowActions>
            <AdminActionIconButton
                disabled={!page.abilities.canUpdate}
                label="编辑资源"
                onClick={() => page.openEditResource(resource)}
            >
                <EditOutlined fontSize="small" />
            </AdminActionIconButton>
        </AdminRowActions>
    );
}

function ResourceFormDialog({ disabled, form, loading, mode, onClose, onSubmit, open, setForm, uploadDisabled }) {
    const submitDisabled = disabled || loading;
    const { showToast } = useToast();
    const profileCardLayout =
        form.resourceType === "profile_card" ? profileCardLayoutFromMetadata(form.metadataJson) : null;
    const handleProfileCardAnimationSelected = async (file) => {
        if (form.resourceType !== "profile_card") {
            return;
        }
        try {
            const layout = await detectProfileCardLayout(file);
            setForm((previous) =>
                previous.resourceType === "profile_card"
                    ? {
                          ...previous,
                          metadataJson: mergeProfileCardLayoutMetadata(previous.metadataJson, layout),
                      }
                    : previous,
            );
        } catch (err) {
            showToast(err.message || "资料卡内容高度解析失败", "error");
        }
    };
    return (
        <AdminFormDialog
            loading={loading}
            open={open}
            submitDisabled={submitDisabled}
            title={mode === "edit" ? "编辑资源" : "添加资源"}
            onClose={onClose}
            onSubmit={onSubmit}
        >
            <AdminFormSection title="基础信息">
                <AdminFormFieldGrid>
                    <TextField
                        disabled={disabled}
                        label="资源名称"
                        required
                        value={form.name}
                        onChange={(event) => setForm({ ...form, name: event.target.value })}
                    />
                    <TextField
                        disabled={disabled}
                        label="资源编码"
                        required
                        value={form.resourceCode}
                        onChange={(event) => setForm({ ...form, resourceCode: event.target.value })}
                    />
                    <TextField
                        disabled={disabled}
                        label="资源类型"
                        required
                        select
                        value={form.resourceType}
                        onChange={(event) => {
                            const resourceType = event.target.value;
                            setForm((previous) => ({
                                ...previous,
                                badgeForm: resourceType === "badge" ? previous.badgeForm || "tile" : previous.badgeForm,
                                badgeKind: resourceType === "badge" ? previous.badgeKind || "normal" : "normal",
                                levelTrack: resourceType === "badge" ? previous.levelTrack || "" : "",
                                metadataJson: resourceType === "profile_card" ? previous.metadataJson : "",
                                resourceType,
                                walletAssetAmount: "",
                            }));
                        }}
                    >
                        {resourceTypeOptions.map(([value, label]) => (
                            <MenuItem key={value} value={value}>
                                {label}
                            </MenuItem>
                        ))}
                    </TextField>
                    {form.resourceType === "coin" ? (
                        <TextField
                            disabled={disabled}
                            label="金币数量"
                            required
                            type="number"
                            value={form.walletAssetAmount}
                            onChange={(event) => setForm({ ...form, walletAssetAmount: event.target.value })}
                        />
                    ) : null}
                    {form.resourceType === "badge" ? (
                        <>
                            <TextField
                                disabled={disabled}
                                label="徽章属性"
                                required
                                select
                                value={form.badgeForm}
                                onChange={(event) => setForm({ ...form, badgeForm: event.target.value })}
                            >
                                {badgeFormOptions.map(([value, label]) => (
                                    <MenuItem key={value} value={value}>
                                        {label}
                                    </MenuItem>
                                ))}
                            </TextField>
                            <TextField
                                disabled={disabled}
                                label="徽章类型"
                                required
                                select
                                value={form.badgeKind}
                                onChange={(event) =>
                                    setForm({
                                        ...form,
                                        badgeKind: event.target.value,
                                        levelTrack: event.target.value === "level" ? form.levelTrack : "",
                                    })
                                }
                            >
                                {badgeKindOptions.map(([value, label]) => (
                                    <MenuItem key={value} value={value}>
                                        {label}
                                    </MenuItem>
                                ))}
                            </TextField>
                            {form.badgeKind === "level" ? (
                                <TextField
                                    disabled={disabled}
                                    label="所属等级"
                                    required
                                    select
                                    value={form.levelTrack}
                                    onChange={(event) => setForm({ ...form, levelTrack: event.target.value })}
                                >
                                    {badgeLevelTrackOptions.map(([value, label]) => (
                                        <MenuItem key={value} value={value}>
                                            {label}
                                        </MenuItem>
                                    ))}
                                </TextField>
                            ) : null}
                        </>
                    ) : null}
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="价格">
                <AdminFormFieldGrid columns="repeat(2, minmax(0, 1fr))">
                    <TextField
                        disabled={disabled}
                        label="价格类型"
                        required
                        select
                        value={form.priceType}
                        onChange={(event) =>
                            setForm({
                                ...form,
                                coinPrice: event.target.value === "free" ? "0" : form.coinPrice,
                                priceType: event.target.value,
                            })
                        }
                    >
                        {resourcePriceTypeOptions.map(([value, label]) => (
                            <MenuItem key={value} value={value}>
                                {label}
                            </MenuItem>
                        ))}
                    </TextField>
                    <TextField
                        disabled={disabled || form.priceType === "free"}
                        label="价格"
                        required={form.priceType === "coin"}
                        type="number"
                        value={form.priceType === "free" ? "0" : form.coinPrice}
                        onChange={(event) => setForm({ ...form, coinPrice: event.target.value })}
                    />
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="素材">
                <AdminFormFieldGrid columns="repeat(2, minmax(0, 1fr))">
                    <UploadField
                        disabled={disabled || uploadDisabled}
                        kind="file"
                        label="资源封面"
                        value={form.previewUrl}
                        onChange={(previewUrl) => setForm((previous) => ({ ...previous, previewUrl }))}
                    />
                    <UploadField
                        disabled={disabled || uploadDisabled}
                        kind="file"
                        label="动效素材"
                        value={form.animationUrl}
                        onChange={(animationUrl) => setForm((previous) => ({ ...previous, animationUrl }))}
                        onFileSelected={handleProfileCardAnimationSelected}
                    />
                </AdminFormFieldGrid>
                {profileCardLayout ? (
                    <AdminFormFieldGrid columns="repeat(2, minmax(0, 1fr))">
                        <TextField disabled label="content_top" value={String(profileCardLayout.content_top)} />
                        <TextField disabled label="内容高度" value={String(profileCardLayout.content_height)} />
                    </AdminFormFieldGrid>
                ) : null}
            </AdminFormSection>
            <AdminFormSection title="状态">
                <AdminFormSwitchField
                    checked={form.enabled}
                    checkedLabel="启用"
                    disabled={disabled}
                    label="资源状态"
                    uncheckedLabel="禁用"
                    onChange={(checked) => setForm({ ...form, enabled: checked })}
                />
            </AdminFormSection>
        </AdminFormDialog>
    );
}

function ResourceIdentity({ resource }) {
    const preview = imageURL(resource.previewUrl || resource.assetUrl);
    return (
        <div className={styles.identity}>
            <span className={styles.thumb}>
                {preview ? <img src={preview} alt="" /> : <Inventory2Outlined fontSize="small" />}
            </span>
            <div className={styles.identityText}>
                <span className={styles.name}>{resource.name || "-"}</span>
                <span className={styles.meta}>{resource.resourceCode || resource.resourceId}</span>
            </div>
        </div>
    );
}

function ResourceStatusSwitch({ page, resource }) {
    const checked = resource.status === "active";
    return (
        <AdminSwitch
            checked={checked}
            disabled={!page.abilities.canUpdate || page.loadingAction === `resource-status-${resource.resourceId}`}
            inputProps={{ "aria-label": checked ? "禁用资源" : "启用资源" }}
            onChange={(event) => page.toggleResource(resource, event.target.checked)}
        />
    );
}

function resourcePriceLabel(resource) {
    if (resource.priceType === "free") {
        return resourcePriceTypeLabels.free;
    }
    if (resource.priceType === "coin") {
        return `金币 ${formatNumber(resource.coinPrice)}`;
    }
    return "未配置";
}

function badgeFormLabel(resource) {
    if (resource.resourceType !== "badge") {
        return "-";
    }
    const formLabel = badgeFormLabels[resource.badgeForm || badgeFormFromMetadata(resource.metadataJson)] || "未配置";
    const kind = resource.badgeKind || badgeKindFromMetadata(resource.metadataJson) || "normal";
    const kindLabel = badgeKindLabels[kind] || badgeKindLabels.normal;
    const track = resource.levelTrack || levelTrackFromMetadata(resource.metadataJson);
    const trackLabel = kind === "level" && track ? badgeLevelTrackLabels[track] : "";
    return [formLabel, kindLabel, trackLabel].filter(Boolean).join(" · ");
}

function badgeFormFromMetadata(metadataJson) {
    if (!metadataJson) {
        return "";
    }
    try {
        const metadata = JSON.parse(metadataJson);
        const badgeForm = String(metadata?.badge_form || "")
            .trim()
            .toLowerCase();
        return badgeForm === "strip" || badgeForm === "tile" ? badgeForm : "";
    } catch {
        return "";
    }
}

function badgeKindFromMetadata(metadataJson) {
    if (!metadataJson) {
        return "";
    }
    try {
        const metadata = JSON.parse(metadataJson);
        return String(metadata?.badge_kind || "").trim().toLowerCase() === "level" ? "level" : "normal";
    } catch {
        return "";
    }
}

function levelTrackFromMetadata(metadataJson) {
    if (!metadataJson) {
        return "";
    }
    try {
        const metadata = JSON.parse(metadataJson);
        const levelTrack = String(metadata?.level_track || "")
            .trim()
            .toLowerCase();
        return levelTrack === "wealth" || levelTrack === "game" || levelTrack === "charm" ? levelTrack : "";
    } catch {
        return "";
    }
}

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

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