import { useEffect, useRef, useState } from 'react';
import {
  AlertCircle,
  BellRing,
  CalendarClock,
  CheckCircle2,
  Clock,
  Database,
  Download,
  Folder,
  Mail,
  MessageSquare,
  PlayCircle,
  RefreshCw,
  Send,
  SlidersHorizontal,
  Upload,
  Wifi,
  XCircle
} from 'lucide-react';
import { fetchMetadataStatus, saveConfig } from '../api/config';
import { deriveTaskState } from '../constants';
import {
  buildConfigBackup,
  createBackupFilename,
  isBackupSupported,
  parseConfigBackup,
  restoreConfigFromBackup,
  triggerJsonDownload
} from '../utils/configBackup';

const METADATA_SERVICE_KEYS = [
  'acoustid',
  'musicbrainz',
  'netease',
  'qq',
  'spotify',
  'discogs',
  'lastfm',
  'genius'
];

const DEFAULT_CRON = '0 2 * * *';
const DEFAULT_TIME = '02:00';
const SCHEDULE_TYPE = {
  DAILY: 'daily',
  WEEKLY: 'weekly',
  CRON: 'cron'
};
const WEEKDAY_OPTIONS = [
  { value: '1', label: '周一' },
  { value: '2', label: '周二' },
  { value: '3', label: '周三' },
  { value: '4', label: '周四' },
  { value: '5', label: '周五' },
  { value: '6', label: '周六' },
  { value: '0', label: '周日' }
];
function padCronSegment(value) {
  return String(value).padStart(2, '0');
}

function isCronNumber(value, min, max) {
  if (!/^\d+$/.test(value)) {
    return false;
  }
  const numericValue = Number(value);
  return numericValue >= min && numericValue <= max;
}

function formatTimeFromCron(hour, minute) {
  return `${padCronSegment(hour)}:${padCronSegment(minute)}`;
}

function buildDailyCron(time) {
  const [hour, minute] = time.split(':');
  return `${Number(minute)} ${Number(hour)} * * *`;
}

function buildWeeklyCron(day, time) {
  const [hour, minute] = time.split(':');
  return `${Number(minute)} ${Number(hour)} * * ${day}`;
}

function normalizeSchedule(schedule) {
  const nextSchedule = {
    enabled: true,
    type: SCHEDULE_TYPE.DAILY,
    dayOfWeek: '1',
    time: DEFAULT_TIME,
    cron: DEFAULT_CRON,
    ...schedule
  };
  const normalizedCron =
    typeof nextSchedule.cron === 'string' && nextSchedule.cron.trim()
      ? nextSchedule.cron.trim()
      : DEFAULT_CRON;
  const parts = normalizedCron.split(/\s+/);

  if (parts.length === 5) {
    const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
    const hasSimpleTime = isCronNumber(minute, 0, 59) && isCronNumber(hour, 0, 23);

    if (hasSimpleTime) {
      nextSchedule.time = nextSchedule.time || formatTimeFromCron(hour, minute);
    }

    if (
      !schedule?.type &&
      hasSimpleTime &&
      dayOfMonth === '*' &&
      month === '*' &&
      dayOfWeek === '*'
    ) {
      nextSchedule.type = SCHEDULE_TYPE.DAILY;
      nextSchedule.time = formatTimeFromCron(hour, minute);
    } else if (
      !schedule?.type &&
      hasSimpleTime &&
      dayOfMonth === '*' &&
      month === '*' &&
      ['0', '1', '2', '3', '4', '5', '6', '7'].includes(dayOfWeek)
    ) {
      nextSchedule.type = SCHEDULE_TYPE.WEEKLY;
      nextSchedule.dayOfWeek = dayOfWeek === '7' ? '0' : dayOfWeek;
      nextSchedule.time = formatTimeFromCron(hour, minute);
    } else if (!schedule?.type) {
      nextSchedule.type = SCHEDULE_TYPE.CRON;
    }
  }

  if (!nextSchedule.time) {
    nextSchedule.time = DEFAULT_TIME;
  }

  if (!nextSchedule.dayOfWeek) {
    nextSchedule.dayOfWeek = '1';
  }

  nextSchedule.cron = normalizedCron;
  return nextSchedule;
}

function getScheduleSummary(schedule) {
  const normalizedSchedule = normalizeSchedule(schedule);

  if (normalizedSchedule.type === SCHEDULE_TYPE.DAILY) {
    return `系统将在 每天 ${normalizedSchedule.time || DEFAULT_TIME} 自动触发入库。`;
  }

  if (normalizedSchedule.type === SCHEDULE_TYPE.WEEKLY) {
    const weekdayLabel =
      WEEKDAY_OPTIONS.find((option) => option.value === normalizedSchedule.dayOfWeek)?.label ||
      '周一';
    return `系统将在 每${weekdayLabel} ${normalizedSchedule.time || DEFAULT_TIME} 自动触发入库。`;
  }

  return `按照 Cron 规则执行: ${normalizedSchedule.cron || DEFAULT_CRON}`;
}

function createIdleNetStatus() {
  return METADATA_SERVICE_KEYS.reduce((accumulator, key) => {
    accumulator[key] = { status: 'idle', latencyMs: null, message: '未检测' };
    return accumulator;
  }, {});
}

function createCheckingNetStatus() {
  return METADATA_SERVICE_KEYS.reduce((accumulator, key) => {
    accumulator[key] = { status: 'checking', latencyMs: null, message: '探测中' };
    return accumulator;
  }, {});
}

function createClosedImportDialogState() {
  return {
    isOpen: false,
    stage: 'password',
    password: '',
    fileName: '',
    exportedAt: '',
    payload: null,
    decryptedConfig: null,
    isSubmitting: false
  };
}

function formatBackupTimestamp(value) {
  if (!value) {
    return '未知';
  }

  const timestamp = new Date(value);
  if (Number.isNaN(timestamp.getTime())) {
    return value;
  }

  return timestamp.toLocaleString('zh-CN', {
    hour12: false
  });
}

export default function SettingsPage({ config, setConfig, setTaskState }) {
  const fileInputRef = useRef(null);
  const metadataStatusAbortRef = useRef(null);
  const netStatusRequestIdRef = useRef(0);
  const [localConfig, setLocalConfig] = useState({
    ...config,
    schedule: normalizeSchedule(config.schedule)
  });
  const [isSaving, setIsSaving] = useState(false);
  const [isExportDialogOpen, setIsExportDialogOpen] = useState(false);
  const [isExporting, setIsExporting] = useState(false);
  const [exportPassword, setExportPassword] = useState('');
  const [exportPasswordConfirm, setExportPasswordConfirm] = useState('');
  const [importDialog, setImportDialog] = useState(createClosedImportDialogState);
  const [netStatus, setNetStatus] = useState(createIdleNetStatus);
  const resolvedNetStatusRef = useRef(createIdleNetStatus());
  const [toast, setToast] = useState(null);
  const toastTimeoutRef = useRef(null);

  useEffect(() => {
    setLocalConfig({
      ...config,
      schedule: normalizeSchedule(config.schedule)
    });
  }, [config]);

  useEffect(
    () => () => {
      metadataStatusAbortRef.current?.abort();
      metadataStatusAbortRef.current = null;
      if (toastTimeoutRef.current) {
        clearTimeout(toastTimeoutRef.current);
      }
    },
    []
  );

  const showToast = (nextToast) => {
    if (toastTimeoutRef.current) {
      clearTimeout(toastTimeoutRef.current);
    }

    setToast(nextToast);
    toastTimeoutRef.current = setTimeout(() => {
      setToast(null);
      toastTimeoutRef.current = null;
    }, 3000);
  };

  const cancelMetadataStatusProbe = () => {
    metadataStatusAbortRef.current?.abort();
    metadataStatusAbortRef.current = null;
  };

  const beginNetStatusRequest = () => {
    const requestId = netStatusRequestIdRef.current + 1;
    netStatusRequestIdRef.current = requestId;
    setNetStatus(createCheckingNetStatus());
    return requestId;
  };

  const isCurrentNetStatusRequest = (requestId) => netStatusRequestIdRef.current === requestId;

  const commitNetStatus = (requestId, nextStatus) => {
    if (!isCurrentNetStatusRequest(requestId)) {
      return false;
    }

    resolvedNetStatusRef.current = nextStatus;
    setNetStatus(nextStatus);
    return true;
  };

  const restoreNetStatus = (requestId) => {
    if (!isCurrentNetStatusRequest(requestId)) {
      return false;
    }

    setNetStatus(resolvedNetStatusRef.current);
    return true;
  };

  useEffect(() => {
    const requestId = beginNetStatusRequest();
    const abortController = new AbortController();
    metadataStatusAbortRef.current = abortController;

    async function loadMetadataStatus() {
      try {
        const response = await fetchMetadataStatus({ signal: abortController.signal });
        if (metadataStatusAbortRef.current === abortController) {
          metadataStatusAbortRef.current = null;
        }
        commitNetStatus(requestId, response.metadataStatus);
      } catch (error) {
        if (metadataStatusAbortRef.current === abortController) {
          metadataStatusAbortRef.current = null;
        }

        if (error.name === 'AbortError') {
          return;
        }

        if (restoreNetStatus(requestId)) {
          showToast({ type: 'error', message: `API 连通性检测失败：${error.message}` });
        }
      }
    }

    loadMetadataStatus();

    return () => {
      if (metadataStatusAbortRef.current === abortController) {
        abortController.abort();
        metadataStatusAbortRef.current = null;
      }
    };
  }, []);

  const handleSave = async () => {
    cancelMetadataStatusProbe();
    const requestId = beginNetStatusRequest();
    setIsSaving(true);

    try {
      const response = await saveConfig(localConfig);
      setConfig(response.config);
      setTaskState(deriveTaskState(response.config));
      setLocalConfig({
        ...response.config,
        schedule: normalizeSchedule(response.config.schedule)
      });
      commitNetStatus(requestId, response.metadataStatus);
      showToast({ type: 'success', message: '配置已保存，服务状态已刷新。' });
    } catch (error) {
      restoreNetStatus(requestId);
      showToast({ type: 'error', message: `保存失败：${error.message}` });
    } finally {
      setIsSaving(false);
    }
  };

  const handleOpenExportDialog = () => {
    if (!isBackupSupported()) {
      showToast({ type: 'error', message: '当前浏览器环境不支持配置加密导出。' });
      return;
    }

    setExportPassword('');
    setExportPasswordConfirm('');
    setIsExportDialogOpen(true);
  };

  const handleCloseExportDialog = (forceClose = false) => {
    if (!forceClose && isExporting) {
      return;
    }

    setIsExportDialogOpen(false);
    setExportPassword('');
    setExportPasswordConfirm('');
  };

  const handleExportConfig = async () => {
    if (!exportPassword.trim()) {
      showToast({ type: 'error', message: '请输入导出口令。' });
      return;
    }

    if (exportPassword !== exportPasswordConfirm) {
      showToast({ type: 'error', message: '两次输入的导出口令不一致。' });
      return;
    }

    setIsExporting(true);

    try {
      const backupPayload = await buildConfigBackup(localConfig, exportPassword);
      triggerJsonDownload(createBackupFilename(), backupPayload);
      handleCloseExportDialog(true);
      showToast({ type: 'success', message: '配置已导出，请妥善保管导出文件与口令。' });
    } catch (error) {
      showToast({ type: 'error', message: `导出失败：${error.message}` });
    } finally {
      setIsExporting(false);
    }
  };

  const handleImportButtonClick = () => {
    if (!isBackupSupported()) {
      showToast({ type: 'error', message: '当前浏览器环境不支持配置解密导入。' });
      return;
    }

    fileInputRef.current?.click();
  };

  const handleImportFileChange = async (event) => {
    const [file] = event.target.files || [];
    event.target.value = '';

    if (!file) {
      return;
    }

    try {
      const fileText = await file.text();
      const backupPayload = parseConfigBackup(fileText);
      setImportDialog({
        isOpen: true,
        stage: 'password',
        password: '',
        fileName: file.name,
        exportedAt: backupPayload.exportedAt || '',
        payload: backupPayload,
        decryptedConfig: null,
        isSubmitting: false
      });
    } catch (error) {
      showToast({ type: 'error', message: `导入失败：${error.message}` });
    }
  };

  const handleCloseImportDialog = () => {
    if (importDialog.isSubmitting) {
      return;
    }

    setImportDialog(createClosedImportDialogState());
  };

  const handleImportDecrypt = async () => {
    if (!importDialog.password.trim()) {
      showToast({ type: 'error', message: '请输入解密口令。' });
      return;
    }

    setImportDialog((currentDialog) => ({
      ...currentDialog,
      isSubmitting: true
    }));

    try {
      const restoredConfig = await restoreConfigFromBackup(
        importDialog.payload,
        importDialog.password
      );
      setImportDialog((currentDialog) => ({
        ...currentDialog,
        stage: 'confirm',
        decryptedConfig: restoredConfig,
        isSubmitting: false
      }));
    } catch (error) {
      setImportDialog((currentDialog) => ({
        ...currentDialog,
        isSubmitting: false
      }));
      showToast({ type: 'error', message: error.message });
    }
  };

  const handleImportConfirm = async () => {
    if (!importDialog.decryptedConfig) {
      showToast({ type: 'error', message: '导入内容不存在，请重新选择配置文件。' });
      return;
    }

    cancelMetadataStatusProbe();
    const requestId = beginNetStatusRequest();
    setImportDialog((currentDialog) => ({
      ...currentDialog,
      isSubmitting: true
    }));

    try {
      const response = await saveConfig(importDialog.decryptedConfig);
      setConfig(response.config);
      setTaskState(deriveTaskState(response.config));
      setLocalConfig({
        ...response.config,
        schedule: normalizeSchedule(response.config.schedule)
      });
      commitNetStatus(requestId, response.metadataStatus);
      setImportDialog(createClosedImportDialogState());
      showToast({ type: 'success', message: '配置已导入并完成全量替换。' });
    } catch (error) {
      restoreNetStatus(requestId);
      setImportDialog((currentDialog) => ({
        ...currentDialog,
        isSubmitting: false
      }));
      showToast({ type: 'error', message: `导入保存失败：${error.message}` });
    }
  };

  const renderNetStatus = (serviceStatus) => {
    if (serviceStatus.status === 'checking') {
      return (
        <span className="flex items-center rounded border border-slate-700/50 bg-slate-800/50 px-2 py-0.5 text-xs text-slate-400">
          <RefreshCw className="mr-1.5 h-3 w-3 animate-spin" /> 探测中
        </span>
      );
    }
    if (serviceStatus.status === 'online') {
      return (
        <span className="flex items-center rounded border border-emerald-500/20 bg-emerald-500/10 px-2 py-0.5 text-xs text-emerald-400">
          <Wifi className="mr-1.5 h-3 w-3" />
          {serviceStatus.latencyMs ? `可达 (${serviceStatus.latencyMs}ms)` : serviceStatus.message}
        </span>
      );
    }
    if (serviceStatus.status === 'warning') {
      return (
        <span className="flex items-center rounded border border-amber-500/20 bg-amber-500/10 px-2 py-0.5 text-xs text-amber-400">
          <AlertCircle className="mr-1.5 h-3 w-3" />
          {serviceStatus.latencyMs
            ? `高延迟 (${serviceStatus.latencyMs}ms)`
            : serviceStatus.message}
        </span>
      );
    }
    if (serviceStatus.status === 'offline') {
      return (
        <span className="flex items-center rounded border border-rose-500/20 bg-rose-500/10 px-2 py-0.5 text-xs text-rose-400">
          <XCircle className="mr-1.5 h-3 w-3" /> {serviceStatus.message}
        </span>
      );
    }
    if (serviceStatus.status === 'idle') {
      return (
        <span className="flex items-center rounded border border-slate-700 bg-slate-800 px-2 py-0.5 text-xs text-slate-500">
          尚未检测
        </span>
      );
    }
    return (
      <span className="flex items-center rounded border border-slate-700 bg-slate-800 px-2 py-0.5 text-xs text-slate-500">
        {serviceStatus.message}
      </span>
    );
  };

  const updateSchedule = (updater) => {
    setLocalConfig((currentConfig) => {
      const currentSchedule = normalizeSchedule(currentConfig.schedule);
      const nextSchedule =
        typeof updater === 'function'
          ? normalizeSchedule(updater(currentSchedule))
          : normalizeSchedule(updater);

      return {
        ...currentConfig,
        schedule: nextSchedule
      };
    });
  };

  const handleScheduleEnabledChange = (enabled) => {
    updateSchedule((currentSchedule) => ({
      ...currentSchedule,
      enabled
    }));
  };

  const handleScheduleTypeChange = (type) => {
    updateSchedule((currentSchedule) => {
      if (type === SCHEDULE_TYPE.DAILY) {
        return {
          ...currentSchedule,
          type,
          cron: buildDailyCron(currentSchedule.time || DEFAULT_TIME)
        };
      }

      if (type === SCHEDULE_TYPE.WEEKLY) {
        const dayOfWeek = currentSchedule.dayOfWeek || '1';
        return {
          ...currentSchedule,
          type,
          dayOfWeek,
          cron: buildWeeklyCron(dayOfWeek, currentSchedule.time || DEFAULT_TIME)
        };
      }

      return {
        ...currentSchedule,
        type,
        cron: currentSchedule.cron || DEFAULT_CRON
      };
    });
  };

  const handleScheduleTimeChange = (time) => {
    updateSchedule((currentSchedule) => ({
      ...currentSchedule,
      time,
      cron:
        currentSchedule.type === SCHEDULE_TYPE.WEEKLY
          ? buildWeeklyCron(currentSchedule.dayOfWeek || '1', time)
          : buildDailyCron(time)
    }));
  };

  const handleScheduleDayChange = (dayOfWeek) => {
    updateSchedule((currentSchedule) => ({
      ...currentSchedule,
      dayOfWeek,
      cron: buildWeeklyCron(dayOfWeek, currentSchedule.time || DEFAULT_TIME)
    }));
  };

  const handleScheduleCronChange = (cron) => {
    updateSchedule((currentSchedule) => ({
      ...currentSchedule,
      cron
    }));
  };

  return (
    <div className="w-full py-6">
      <div className="mb-8 flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
        <div>
          <h2 className="mb-2 text-2xl font-bold text-white">系统运行配置</h2>
          <p className="text-slate-400">全局基础目录设定及核心入库引擎的高级策略配置。</p>
        </div>
        <div className="flex flex-wrap items-center gap-3">
          <button
            type="button"
            onClick={handleImportButtonClick}
            disabled={isSaving}
            className="flex items-center whitespace-nowrap rounded-lg border border-slate-700 bg-slate-900 px-4 py-2.5 text-sm font-medium text-slate-200 transition hover:border-blue-500/50 hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-60"
          >
            <Upload className="mr-2 h-4 w-4" />
            导入配置
          </button>
          <button
            type="button"
            onClick={handleOpenExportDialog}
            disabled={isSaving}
            className="flex items-center whitespace-nowrap rounded-lg border border-slate-700 bg-slate-900 px-4 py-2.5 text-sm font-medium text-slate-200 transition hover:border-emerald-500/50 hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-60"
          >
            <Download className="mr-2 h-4 w-4" />
            导出配置
          </button>
          <button
            type="button"
            onClick={handleSave}
            disabled={isSaving}
            className="flex items-center whitespace-nowrap rounded-lg bg-blue-600 px-6 py-2.5 text-sm font-medium text-white shadow-lg shadow-blue-900/20 transition hover:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-70"
          >
            {isSaving ? (
              <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
            ) : (
              <CheckCircle2 className="mr-2 h-4 w-4" />
            )}
            {isSaving ? '校验并保存...' : '保存系统配置'}
          </button>
        </div>
      </div>

      <input
        ref={fileInputRef}
        type="file"
        accept=".json,application/json"
        className="hidden"
        onChange={handleImportFileChange}
      />

      {toast && (
        <div
          className={`fixed left-1/2 top-6 z-[100] flex -translate-x-1/2 items-center rounded-xl border px-5 py-3 shadow-2xl backdrop-blur-md animate-in slide-in-from-top-4 fade-in duration-300 ${
            toast.type === 'success'
              ? 'border-emerald-500/50 bg-emerald-950/90 text-emerald-400'
              : 'border-rose-500/50 bg-rose-950/90 text-rose-400'
          }`}
        >
          {toast.type === 'success' ? (
            <CheckCircle2 className="mr-2 h-5 w-5" />
          ) : (
            <XCircle className="mr-2 h-5 w-5" />
          )}
          <span className="text-sm font-medium">{toast.message}</span>
        </div>
      )}

      <div className="mb-8 space-y-6">
        <div className="rounded-xl border border-slate-800 bg-slate-900 p-6 shadow-lg">
          <h3 className="mb-5 flex items-center border-b border-slate-800 pb-3 text-base font-semibold text-white">
            <Folder className="mr-2 h-5 w-5 text-blue-400" />
            基础核心目录
          </h3>
          <div className="grid grid-cols-1 gap-6 md:grid-cols-3">
            <div>
              <label className="mb-2 flex items-center text-sm font-medium text-white">输入目录 (待处理源)</label>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-200 focus:border-blue-500 focus:outline-none focus:ring-blue-500"
                value={localConfig.input}
                onChange={(e) => setLocalConfig({ ...localConfig, input: e.target.value })}
              />
            </div>
            <div>
              <label className="mb-2 flex items-center text-sm font-medium text-white">输出目录 (Navidrome主库)</label>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-200 focus:border-emerald-500 focus:outline-none focus:ring-emerald-500"
                value={localConfig.output}
                onChange={(e) => setLocalConfig({ ...localConfig, output: e.target.value })}
              />
            </div>
            <div>
              <label className="mb-2 flex items-center text-sm font-medium text-white">回收站目录 (异常与重复隔离)</label>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-200 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                value={localConfig.trash}
                onChange={(e) => setLocalConfig({ ...localConfig, trash: e.target.value })}
              />
            </div>
          </div>
        </div>

        <div className="rounded-xl border border-slate-800 bg-slate-900 p-6 shadow-lg">
          <h3 className="mb-5 flex items-center border-b border-slate-800 pb-3 text-base font-semibold text-white">
            <SlidersHorizontal className="mr-2 h-5 w-5 text-purple-400" />
            高级运行策略 (Advanced Strategy)
          </h3>
          <div className="grid grid-cols-1 gap-6 md:grid-cols-3">
            <label className="group flex h-full cursor-pointer items-start space-x-3 rounded-lg border border-slate-800/50 bg-slate-950/50 p-4 transition-colors hover:border-blue-500/30 hover:bg-slate-900">
              <input
                type="checkbox"
                checked={localConfig.advancedStrategy?.metadataFallback ?? true}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    advancedStrategy: {
                      ...localConfig.advancedStrategy,
                      metadataFallback: e.target.checked
                    }
                  })
                }
                className="mt-1 shrink-0 cursor-pointer rounded border-slate-700 bg-slate-950 text-blue-500 focus:ring-blue-500"
              />
              <div>
                <span className="block text-sm font-medium text-white transition-colors group-hover:text-blue-400">开启多源元数据轮询回退</span>
                <span className="mt-1.5 block text-xs leading-relaxed text-slate-500">仅控制 Netease / QQ / Spotify 的身份兜底查询；AcoustID 与 MusicBrainz 主链路始终参与匹配。</span>
              </div>
            </label>
            <label className="group flex h-full cursor-pointer items-start space-x-3 rounded-lg border border-slate-800/50 bg-slate-950/50 p-4 transition-colors hover:border-blue-500/30 hover:bg-slate-900">
              <input
                type="checkbox"
                checked={localConfig.advancedStrategy?.downloadAssets ?? true}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    advancedStrategy: {
                      ...localConfig.advancedStrategy,
                      downloadAssets: e.target.checked
                    }
                  })
                }
                className="mt-1 shrink-0 cursor-pointer rounded border-slate-700 bg-slate-950 text-blue-500 focus:ring-blue-500"
              />
              <div>
                <span className="block text-sm font-medium text-white transition-colors group-hover:text-blue-400">自动下载并补全资产 (封面/歌词)</span>
                <span className="mt-1.5 block text-xs leading-relaxed text-slate-500">仅控制 Discogs / Last.fm / Genius 的增强信息查询与来源决策，本轮不会真实下载文件。</span>
              </div>
            </label>
            <label className="group flex h-full cursor-pointer items-start space-x-3 rounded-lg border border-slate-800/50 bg-slate-950/50 p-4 transition-colors hover:border-blue-500/30 hover:bg-slate-900">
              <input
                type="checkbox"
                checked={localConfig.advancedStrategy?.replaceLowQualityDuplicates ?? false}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    advancedStrategy: {
                      ...localConfig.advancedStrategy,
                      replaceLowQualityDuplicates: e.target.checked
                    }
                  })
                }
                className="mt-1 shrink-0 cursor-pointer rounded border-slate-700 bg-slate-950 text-blue-500 focus:ring-blue-500"
              />
              <div>
                <span className="block text-sm font-medium text-white transition-colors group-hover:text-blue-400">重复项自动替换低音质 (慎用)</span>
                <span className="mt-1.5 block text-xs leading-relaxed text-slate-500">若发现重复曲目且新文件比特率更高，自动覆盖库中旧文件，而非移入回收站产生冲突。</span>
              </div>
            </label>
          </div>
        </div>

        <div className="bg-slate-900 border border-slate-800 rounded-xl p-6 shadow-lg">
          <div className="flex justify-between items-center mb-5 border-b border-slate-800 pb-3">
            <h3 className="text-base font-semibold text-white flex items-center">
              <CalendarClock className="w-5 h-5 mr-2 text-amber-400" />
              自动化定时任务
            </h3>
            <label className="flex items-center cursor-pointer">
              <div className="relative">
                <input
                  type="checkbox"
                  className="sr-only"
                  checked={localConfig.schedule?.enabled}
                  onChange={(e) => handleScheduleEnabledChange(e.target.checked)}
                />
                <div className={`block w-10 h-6 rounded-full transition-colors ${localConfig.schedule?.enabled ? 'bg-amber-500' : 'bg-slate-700'}`}></div>
                <div className={`dot absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform ${localConfig.schedule?.enabled ? 'transform translate-x-4' : ''}`}></div>
              </div>
              <span className="ml-3 text-sm font-medium text-slate-300">
                {localConfig.schedule?.enabled ? '已启用自动入库' : '已暂停自动入库'}
              </span>
            </label>
          </div>

          <div className={`flex flex-col gap-4 transition-opacity ${localConfig.schedule?.enabled ? 'opacity-100' : 'opacity-40 pointer-events-none'}`}>
            <div className="flex flex-wrap gap-4 items-end">
              <div className="w-44 shrink-0">
                <label className="flex items-center text-xs font-medium text-slate-400 mb-1.5">执行频率</label>
                <select
                  className="w-full px-3 py-2 rounded bg-slate-950 border border-slate-700 text-slate-200 text-sm focus:ring-amber-500 focus:border-amber-500 focus:outline-none"
                  value={localConfig.schedule?.type || SCHEDULE_TYPE.DAILY}
                  onChange={(e) => handleScheduleTypeChange(e.target.value)}
                >
                  <option value={SCHEDULE_TYPE.DAILY}>每天执行</option>
                  <option value={SCHEDULE_TYPE.WEEKLY}>每周执行</option>
                  <option value={SCHEDULE_TYPE.CRON}>专家模式 (Cron)</option>
                </select>
              </div>

              {localConfig.schedule?.type === SCHEDULE_TYPE.WEEKLY && (
                <div className="w-32 shrink-0">
                  <label className="flex items-center text-xs font-medium text-slate-400 mb-1.5">星期</label>
                  <select
                    className="w-full px-3 py-2 rounded bg-slate-950 border border-slate-700 text-slate-200 text-sm focus:ring-amber-500 focus:border-amber-500 focus:outline-none"
                    value={localConfig.schedule?.dayOfWeek || '1'}
                    onChange={(e) => handleScheduleDayChange(e.target.value)}
                  >
                    <option value="1">星期一</option>
                    <option value="2">星期二</option>
                    <option value="3">星期三</option>
                    <option value="4">星期四</option>
                    <option value="5">星期五</option>
                    <option value="6">星期六</option>
                    <option value="0">星期日</option>
                  </select>
                </div>
              )}

              {localConfig.schedule?.type !== SCHEDULE_TYPE.CRON && (
                <div className="w-32 shrink-0">
                  <label className="flex items-center text-xs font-medium text-slate-400 mb-1.5">具体时间</label>
                  <input
                    type="time"
                    className="w-full px-3 py-2 rounded bg-slate-950 border border-slate-700 text-slate-200 text-sm font-mono focus:ring-amber-500 focus:border-amber-500 focus:outline-none"
                    style={{ colorScheme: 'dark' }}
                    value={localConfig.schedule?.time || DEFAULT_TIME}
                    onChange={(e) => handleScheduleTimeChange(e.target.value)}
                  />
                </div>
              )}

              {localConfig.schedule?.type === SCHEDULE_TYPE.CRON && (
                <div className="flex-1 min-w-[200px]">
                  <label className="flex items-center text-xs font-medium text-slate-400 mb-1.5">Cron 表达式</label>
                  <input
                    type="text"
                    className="w-full px-3 py-2 rounded bg-slate-950 border border-slate-700 text-amber-400 text-sm font-mono focus:ring-amber-500 focus:border-amber-500 focus:outline-none"
                    value={localConfig.schedule?.cron || DEFAULT_CRON}
                    onChange={(e) => handleScheduleCronChange(e.target.value)}
                    placeholder="例如: 0 2 * * *"
                  />
                </div>
              )}
            </div>

            <div className="flex items-center justify-between gap-4 rounded-xl border border-slate-800/90 bg-[#0b1328] px-4 py-3.5">
              <div className="flex min-w-0 items-center text-sm">
                <Clock className="mr-2 h-4 w-4 shrink-0 text-amber-400" />
                <span className="mr-2 shrink-0 text-slate-200">解析结果:</span>
                <span className="truncate font-medium text-amber-400">
                  {getScheduleSummary(localConfig.schedule)}
                </span>
              </div>
              <button className="flex shrink-0 items-center justify-center rounded-lg border border-slate-600 bg-slate-700/70 px-4 py-2 text-sm font-medium text-slate-100 shadow-inner shadow-slate-950/30 transition hover:bg-slate-600/80">
                <PlayCircle className="mr-1.5 h-4 w-4" /> 立即运行测试
              </button>
            </div>
          </div>
        </div>

        <div className="rounded-xl border border-slate-800 bg-slate-900 p-6 shadow-lg">
          <h3 className="mb-5 flex items-center border-b border-slate-800 pb-3 text-base font-semibold text-white">
            <BellRing className="mr-2 h-5 w-5 text-sky-400" />
            消息推送通知 (Webhooks / Notifications)
          </h3>
          <p className="mb-6 text-xs text-slate-400">当自动入库批次任务完成，或产生大量异常记录时，系统将通过以下渠道向您发送详细报告。</p>

          <div className="grid grid-cols-1 gap-8 md:grid-cols-3">
            <div className="flex flex-col gap-4 rounded-lg border border-slate-800/50 bg-slate-950/50 p-5">
              <h4 className="flex items-center text-sm font-semibold text-white">
                <MessageSquare className="mr-2 h-4 w-4 text-sky-500" />
                钉钉机器人 (DingTalk)
              </h4>
              <div>
                <label className="mb-1.5 block text-xs font-medium text-slate-400">Webhook 地址</label>
                <input
                  type="text"
                  className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                  placeholder="https://oapi.dingtalk.com/robot/send?access_token=..."
                  value={localConfig.notifications?.dingtalkWebhook}
                  onChange={(e) =>
                    setLocalConfig({
                      ...localConfig,
                      notifications: {
                        ...localConfig.notifications,
                        dingtalkWebhook: e.target.value
                      }
                    })
                  }
                />
              </div>
              <div>
                <label className="mb-1.5 block text-xs font-medium text-slate-400">加签密钥 (Secret - 可选)</label>
                <input
                  type="password"
                  className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                  placeholder="SEC..."
                  value={localConfig.notifications?.dingtalkSecret}
                  onChange={(e) =>
                    setLocalConfig({
                      ...localConfig,
                      notifications: {
                        ...localConfig.notifications,
                        dingtalkSecret: e.target.value
                      }
                    })
                  }
                />
              </div>
            </div>

            <div className="flex flex-col gap-4 rounded-lg border border-slate-800/50 bg-slate-950/50 p-5">
              <h4 className="flex items-center text-sm font-semibold text-white">
                <Send className="mr-2 h-4 w-4 text-sky-500" />
                Telegram Bot
              </h4>
              <div>
                <label className="mb-1.5 block text-xs font-medium text-slate-400">Bot Token</label>
                <input
                  type="password"
                  className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                  placeholder="123456789:ABCdefGHIjkl..."
                  value={localConfig.notifications?.telegramBotToken}
                  onChange={(e) =>
                    setLocalConfig({
                      ...localConfig,
                      notifications: {
                        ...localConfig.notifications,
                        telegramBotToken: e.target.value
                      }
                    })
                  }
                />
              </div>
              <div>
                <label className="mb-1.5 block text-xs font-medium text-slate-400">Chat ID (接收者)</label>
                <input
                  type="text"
                  className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                  placeholder="例如: 12345678"
                  value={localConfig.notifications?.telegramChatId}
                  onChange={(e) =>
                    setLocalConfig({
                      ...localConfig,
                      notifications: {
                        ...localConfig.notifications,
                        telegramChatId: e.target.value
                      }
                    })
                  }
                />
              </div>
            </div>

            <div className="flex flex-col gap-4 rounded-lg border border-slate-800/50 bg-slate-950/50 p-5">
              <h4 className="flex items-center text-sm font-semibold text-white">
                <Mail className="mr-2 h-4 w-4 text-sky-500" />
                电子邮件 (Email)
              </h4>
              <div className="grid grid-cols-2 gap-3">
                <div className="col-span-2">
                  <label className="mb-1.5 block text-xs font-medium text-slate-400">SMTP 服务器</label>
                  <input
                    type="text"
                    className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                    placeholder="smtp.example.com:465"
                    value={localConfig.notifications?.emailSmtp}
                    onChange={(e) =>
                      setLocalConfig({
                        ...localConfig,
                        notifications: {
                          ...localConfig.notifications,
                          emailSmtp: e.target.value
                        }
                      })
                    }
                  />
                </div>
                <div className="col-span-2 flex gap-3">
                  <div className="flex-1">
                    <label className="mb-1.5 block text-xs font-medium text-slate-400">发件账号</label>
                    <input
                      type="text"
                      className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                      placeholder="bot@example.com"
                      value={localConfig.notifications?.emailUser}
                      onChange={(e) =>
                        setLocalConfig({
                          ...localConfig,
                          notifications: {
                            ...localConfig.notifications,
                            emailUser: e.target.value
                          }
                        })
                      }
                    />
                  </div>
                  <div className="flex-1">
                    <label className="mb-1.5 block text-xs font-medium text-slate-400">授权密码</label>
                    <input
                      type="password"
                      className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                      placeholder="********"
                      value={localConfig.notifications?.emailPass}
                      onChange={(e) =>
                        setLocalConfig({
                          ...localConfig,
                          notifications: {
                            ...localConfig.notifications,
                            emailPass: e.target.value
                          }
                        })
                      }
                    />
                  </div>
                </div>
                <div className="col-span-2">
                  <label className="mb-1.5 block text-xs font-medium text-slate-400">目标收件人</label>
                  <input
                    type="text"
                    className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-xs font-mono text-slate-200 focus:border-sky-500 focus:outline-none focus:ring-sky-500"
                    placeholder="admin@example.com"
                    value={localConfig.notifications?.emailTo}
                    onChange={(e) =>
                      setLocalConfig({
                        ...localConfig,
                        notifications: {
                          ...localConfig.notifications,
                          emailTo: e.target.value
                        }
                      })
                    }
                  />
                </div>
              </div>
            </div>
          </div>
        </div>

        <div className="rounded-xl border border-slate-800 bg-slate-900 p-6 shadow-lg">
          <h3 className="mb-5 flex items-center border-b border-slate-800 pb-3 text-base font-semibold text-white">
            <Database className="mr-2 h-5 w-5 text-rose-400" />
            元数据服务源配置
          </h3>
          <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
            <MetadataCard label="AcoustID (Chromaprint 指纹主链路)" status={renderNetStatus(netStatus.acoustid)}>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-400 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="API 地址"
                value={localConfig.metadata?.acoustidUrl}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, acoustidUrl: e.target.value }
                  })
                }
              />
              <input
                type="password"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="Client Key"
                value={localConfig.metadata?.acoustidClientKey || ''}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, acoustidClientKey: e.target.value }
                  })
                }
              />
              <p className="text-[11px] leading-tight text-slate-500">未填写 Key 时会自动跳过联网指纹查找，不影响 MusicBrainz 文本匹配。</p>
            </MetadataCard>

            <MetadataCard label="MusicBrainz (开放服务 - 默认推荐)" status={renderNetStatus(netStatus.musicbrainz)}>
              <input
                type="text"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                value={localConfig.metadata?.musicbrainz}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, musicbrainz: e.target.value }
                  })
                }
              />
            </MetadataCard>

            <MetadataCard label="网易云音乐 API (需自建服务代理)" status={renderNetStatus(netStatus.netease)}>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="例如: http://localhost:3000"
                value={localConfig.metadata?.netease}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, netease: e.target.value }
                  })
                }
              />
              <p className="mt-auto text-[11px] leading-tight text-slate-500">建议使用 NeteaseCloudMusicApi 部署本地服务后填入地址。</p>
            </MetadataCard>

            <MetadataCard label="QQ音乐 API (需自建服务代理)" status={renderNetStatus(netStatus.qq)}>
              <input
                type="text"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="例如: http://localhost:3300"
                value={localConfig.metadata?.qq}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, qq: e.target.value }
                  })
                }
              />
            </MetadataCard>

            <MetadataCard label="Spotify (官方 API)" status={renderNetStatus(netStatus.spotify)}>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-400 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="API 地址"
                value={localConfig.metadata?.spotifyUrl}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, spotifyUrl: e.target.value }
                  })
                }
              />
              <input
                type="text"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="Client ID"
                value={localConfig.metadata?.spotifyClientId}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, spotifyClientId: e.target.value }
                  })
                }
              />
              <input
                type="password"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="Client Secret"
                value={localConfig.metadata?.spotifySecret}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, spotifySecret: e.target.value }
                  })
                }
              />
            </MetadataCard>

            <MetadataCard label="Discogs (高精度实体唱片库)" status={renderNetStatus(netStatus.discogs)}>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-400 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="API 地址"
                value={localConfig.metadata?.discogsUrl}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, discogsUrl: e.target.value }
                  })
                }
              />
              <input
                type="password"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="Personal Access Token"
                value={localConfig.metadata?.discogsToken || ''}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, discogsToken: e.target.value }
                  })
                }
              />
            </MetadataCard>

            <MetadataCard label="Last.fm (丰富的流派与标签库)" status={renderNetStatus(netStatus.lastfm)}>
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-400 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="API 地址"
                value={localConfig.metadata?.lastfmUrl}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, lastfmUrl: e.target.value }
                  })
                }
              />
              <input
                type="password"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="API Key"
                value={localConfig.metadata?.lastfmKey || ''}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, lastfmKey: e.target.value }
                  })
                }
              />
            </MetadataCard>

            <MetadataCard
              label="Genius (精准歌词支持)"
              status={renderNetStatus(netStatus.genius)}
              className="md:col-span-2 lg:col-span-1"
            >
              <input
                type="text"
                className="w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-400 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="API 地址"
                value={localConfig.metadata?.geniusUrl}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, geniusUrl: e.target.value }
                  })
                }
              />
              <input
                type="password"
                className="mt-auto w-full rounded border border-slate-700 bg-slate-950 px-3 py-2 text-sm font-mono text-slate-300 focus:border-rose-500 focus:outline-none focus:ring-rose-500"
                placeholder="Client Access Token"
                value={localConfig.metadata?.geniusToken || ''}
                onChange={(e) =>
                  setLocalConfig({
                    ...localConfig,
                    metadata: { ...localConfig.metadata, geniusToken: e.target.value }
                  })
                }
              />
            </MetadataCard>
          </div>
        </div>
      </div>

      {isExportDialogOpen && (
        <SettingsDialog
          title="导出系统配置"
          description="导出当前页面中的配置快照。敏感凭据会单独加密，导出文件不会明文包含密钥。"
          onClose={handleCloseExportDialog}
          footer={
            <DialogFooter>
              <button
                type="button"
                onClick={() => handleCloseExportDialog()}
                disabled={isExporting}
                className="rounded-lg border border-slate-700 bg-slate-900 px-4 py-2 text-sm font-medium text-slate-300 transition hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-60"
              >
                取消
              </button>
              <button
                type="button"
                onClick={handleExportConfig}
                disabled={isExporting}
                className="flex items-center rounded-lg bg-emerald-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:cursor-not-allowed disabled:opacity-70"
              >
                {isExporting ? (
                  <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Download className="mr-2 h-4 w-4" />
                )}
                {isExporting ? '导出中...' : '确认导出'}
              </button>
            </DialogFooter>
          }
        >
          <div className="rounded-lg border border-emerald-500/20 bg-emerald-950/20 px-4 py-3 text-sm text-emerald-300">
            导出范围包含当前页面尚未保存的修改。请单独保管导出文件和口令。
          </div>
          <div>
            <label className="mb-2 block text-sm font-medium text-white">导出口令</label>
            <input
              type="password"
              className="w-full rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-sm text-slate-200 focus:border-emerald-500 focus:outline-none focus:ring-emerald-500"
              placeholder="请输入用于加密敏感字段的口令"
              value={exportPassword}
              onChange={(event) => setExportPassword(event.target.value)}
            />
          </div>
          <div>
            <label className="mb-2 block text-sm font-medium text-white">确认口令</label>
            <input
              type="password"
              className="w-full rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-sm text-slate-200 focus:border-emerald-500 focus:outline-none focus:ring-emerald-500"
              placeholder="请再次输入相同口令"
              value={exportPasswordConfirm}
              onChange={(event) => setExportPasswordConfirm(event.target.value)}
            />
          </div>
        </SettingsDialog>
      )}

      {importDialog.isOpen && (
        <SettingsDialog
          title={importDialog.stage === 'password' ? '导入系统配置' : '确认导入配置'}
          description={
            importDialog.stage === 'password'
              ? '仅支持导入由本系统导出的 JSON 配置文件。'
              : '导入会调用现有保存接口，并用导入内容整体覆盖当前系统配置。'
          }
          onClose={handleCloseImportDialog}
          footer={
            <DialogFooter>
              <button
                type="button"
                onClick={handleCloseImportDialog}
                disabled={importDialog.isSubmitting}
                className="rounded-lg border border-slate-700 bg-slate-900 px-4 py-2 text-sm font-medium text-slate-300 transition hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-60"
              >
                取消
              </button>
              <button
                type="button"
                onClick={
                  importDialog.stage === 'password' ? handleImportDecrypt : handleImportConfirm
                }
                disabled={importDialog.isSubmitting}
                className="flex items-center rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-70"
              >
                {importDialog.isSubmitting ? (
                  <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <Upload className="mr-2 h-4 w-4" />
                )}
                {importDialog.stage === 'password'
                  ? importDialog.isSubmitting
                    ? '解密中...'
                    : '验证口令'
                  : importDialog.isSubmitting
                    ? '导入中...'
                    : '确认导入'}
              </button>
            </DialogFooter>
          }
        >
          <div className="rounded-lg border border-slate-800 bg-slate-950/80 px-4 py-3 text-sm text-slate-300">
            <div className="flex flex-wrap items-center gap-x-4 gap-y-2">
              <span>
                文件名:
                <span className="ml-2 font-mono text-slate-200">{importDialog.fileName}</span>
              </span>
              <span>
                导出时间:
                <span className="ml-2 font-mono text-slate-200">
                  {formatBackupTimestamp(importDialog.exportedAt)}
                </span>
              </span>
            </div>
          </div>

          {importDialog.stage === 'password' ? (
            <div>
              <label className="mb-2 block text-sm font-medium text-white">解密口令</label>
              <input
                type="password"
                className="w-full rounded-lg border border-slate-700 bg-slate-950 px-3 py-2 text-sm text-slate-200 focus:border-blue-500 focus:outline-none focus:ring-blue-500"
                placeholder="请输入导出时使用的口令"
                value={importDialog.password}
                onChange={(event) =>
                  setImportDialog((currentDialog) => ({
                    ...currentDialog,
                    password: event.target.value
                  }))
                }
              />
            </div>
          ) : (
            <>
              <div className="rounded-lg border border-amber-500/30 bg-amber-950/20 px-4 py-3 text-sm text-amber-200">
                当前页面中的未保存修改会被丢弃，后端已保存配置也会被导入文件整体替换。
              </div>
              <div className="grid gap-3 rounded-lg border border-slate-800 bg-slate-950/80 p-4 text-sm text-slate-300 md:grid-cols-3">
                <div>
                  <div className="mb-1 text-xs uppercase tracking-wide text-slate-500">输入目录</div>
                  <div className="break-all font-mono text-slate-200">
                    {importDialog.decryptedConfig?.input || '-'}
                  </div>
                </div>
                <div>
                  <div className="mb-1 text-xs uppercase tracking-wide text-slate-500">输出目录</div>
                  <div className="break-all font-mono text-slate-200">
                    {importDialog.decryptedConfig?.output || '-'}
                  </div>
                </div>
                <div>
                  <div className="mb-1 text-xs uppercase tracking-wide text-slate-500">回收站目录</div>
                  <div className="break-all font-mono text-slate-200">
                    {importDialog.decryptedConfig?.trash || '-'}
                  </div>
                </div>
              </div>
            </>
          )}
        </SettingsDialog>
      )}
    </div>
  );
}

function MetadataCard({ label, status, children, className = '' }) {
  return (
    <div className={`flex h-full flex-col gap-3 rounded-lg border border-slate-800/50 bg-slate-950/50 p-5 ${className}`}>
      <div className="mb-1 flex items-center justify-between">
        <label className="text-sm font-medium text-white">{label}</label>
        {status}
      </div>
      {children}
    </div>
  );
}

function SettingsDialog({ title, description, onClose, children, footer }) {
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/80 p-6 backdrop-blur-sm">
      <div className="w-full max-w-lg overflow-hidden rounded-2xl border border-slate-700 bg-slate-900 shadow-2xl">
        <div className="border-b border-slate-800 bg-slate-900/80 px-6 py-4">
          <div className="flex items-start justify-between gap-4">
            <div>
              <h3 className="text-lg font-semibold text-white">{title}</h3>
              <p className="mt-1 text-sm leading-relaxed text-slate-400">{description}</p>
            </div>
            <button
              type="button"
              onClick={onClose}
              className="rounded-lg border border-slate-700 px-3 py-1.5 text-xs font-medium text-slate-400 transition hover:bg-slate-800 hover:text-white"
            >
              关闭
            </button>
          </div>
        </div>
        <div className="space-y-4 px-6 py-5">{children}</div>
        {footer}
      </div>
    </div>
  );
}

function DialogFooter({ children }) {
  return (
    <div className="flex items-center justify-end gap-3 border-t border-slate-800 bg-slate-950/50 px-6 py-4">
      {children}
    </div>
  );
}
