<template>
  <div v-if="isOpen" class="overlay" @click.self="close">
    <div class="dialog">
      <div class="dialog-header">
        <h2>☁️ 云同步设置</h2>
        <button class="close-button" @click="close">&times;</button>
      </div>

      <div class="dialog-body">
        <div class="section">
          <div class="section-title">同步开关</div>
          <label class="checkbox-row">
            <input type="checkbox" v-model="localEnabled" @change="onToggleEnabled" />
            <span>启用云同步（v1.2.0：仅支持登录后拉取任务）</span>
          </label>
          <div class="hint">
            启用后，主界面将以云端任务为准并进入只读展示；本地编辑/新增将在后续版本补齐。
          </div>
        </div>

        <div class="section">
          <div class="section-title">服务端地址</div>
          <div class="form-row">
            <input
              v-model="serverUrlInput"
              class="text-input"
              type="text"
              placeholder="例如：https://example.com"
              autocomplete="off"
            />
            <button class="btn btn-secondary" :disabled="isProbing" @click="saveServerUrl">
              {{ isProbing ? '探测中...' : '保存并探测' }}
            </button>
          </div>
          <div v-if="serverUrlSaved" class="hint">
            已保存：<span class="mono">{{ serverUrlSaved }}</span>
          </div>
          <div v-if="probeResult" class="probe" :class="probeResult.type">
            <div class="probe-title">{{ probeResult.title }}</div>
            <div class="probe-desc">{{ probeResult.desc }}</div>
          </div>
        </div>

        <div class="section">
          <div class="section-title">登录</div>
          <div v-if="isLoggedIn" class="logged-in">
            <div class="hint">
              已登录：<span class="mono">{{ sessionSummary }}</span>
            </div>
            <div class="button-row">
              <button class="btn btn-secondary" @click="logout">登出</button>
              <button class="btn btn-primary" :disabled="!localEnabled" @click="pullTasks">
                拉取任务
              </button>
            </div>
          </div>

          <div v-else class="login-form">
            <div class="form-row">
              <input
                v-model="userName"
                class="text-input"
                type="text"
                placeholder="用户名"
                autocomplete="username"
              />
              <input
                v-model="password"
                class="text-input"
                type="password"
                placeholder="密码"
                autocomplete="current-password"
              />
              <button class="btn btn-primary" :disabled="!canLogin" @click="login">
                {{ isLoggingIn ? '登录中...' : '登录' }}
              </button>
            </div>
            <div class="hint">
              说明：服务端使用 Bearer 会话（AccessToken=SessionId）。会话默认仅保存在本次运行（sessionStorage）。
            </div>
          </div>
        </div>
      </div>

      <div class="dialog-footer">
        <button class="btn btn-secondary" @click="close">关闭</button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import CloudSyncStorage from '../services/cloudSyncStorage';
import cloudSyncApi from '../api/cloudSync';

type ProbeType = 'success' | 'warn' | 'error';
interface ProbeResult {
  type: ProbeType;
  title: string;
  desc: string;
}

const isOpen = ref(false);
const localEnabled = ref(false);
const serverUrlInput = ref('');
const serverUrlSaved = ref('');
const isProbing = ref(false);
const probeResult = ref<ProbeResult | null>(null);

const userName = ref('');
const password = ref('');
const isLoggingIn = ref(false);

const loadLocalState = () => {
  const settings = CloudSyncStorage.loadSettings();
  localEnabled.value = settings.enabled;
  serverUrlSaved.value = settings.serverUrl;
  serverUrlInput.value = settings.serverUrl;
};

const isLoggedIn = computed(() => Boolean(CloudSyncStorage.loadSession()?.accessToken));
const sessionSummary = computed(() => {
  const s = CloudSyncStorage.loadSession();
  if (!s) return '';
  const shortUserId = s.userId ? s.userId.slice(0, 8) : '';
  return `${s.role || 'User'}@${shortUserId}`;
});

const canLogin = computed(() => {
  if (!localEnabled.value) return false;
  if (!serverUrlSaved.value) return false;
  if (!userName.value.trim() || !password.value) return false;
  return !isLoggingIn.value;
});

const showToast = (message: string, type: 'error' | 'success' = 'error') => {
  if ((window as any).showToast) {
    (window as any).showToast(message, type);
  } else {
    window.alert(message);
  }
};

const normalizeServerUrl = (raw: string): { ok: boolean; normalized?: string; message?: string; warn?: string } => {
  const trimmed = raw.trim();
  if (!trimmed) return { ok: false, message: '请输入服务端地址' };

  let url: URL;
  try {
    url = new URL(trimmed);
  } catch {
    return { ok: false, message: '地址格式不正确，请包含协议（http:// 或 https://）' };
  }

  if (url.protocol !== 'http:' && url.protocol !== 'https:') {
    return { ok: false, message: '仅支持 http:// 或 https:// 地址' };
  }

  if (!url.hostname) {
    return { ok: false, message: '地址缺少主机名（host）' };
  }

  const origin = url.origin;
  const pathWarn = url.pathname && url.pathname !== '/' ? '已忽略地址中的路径部分，仅保留 origin。' : undefined;
  return { ok: true, normalized: origin.replace(/\/+$/, ''), warn: pathWarn };
};

const probeReachability = async (serverUrl: string): Promise<ProbeResult> => {
  const u = new URL(serverUrl);
  const isHttps = u.protocol === 'https:';
  const loginUrl = `${serverUrl}/auth/login`;

  const controller = new AbortController();
  const timeout = window.setTimeout(() => controller.abort(), 4000);
  try {
    const res = await fetch(loginUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userName: '__probe__', password: '__probe__' }),
      signal: controller.signal,
    });

    if (!isHttps) {
      return {
        type: 'warn',
        title: '可达（存在风险）',
        desc: '服务端可访问，但当前为 HTTP（非加密）。建议使用 HTTPS。',
      };
    }

    return {
      type: 'success',
      title: '可达',
      desc: `已探测到服务端响应（HTTP ${res.status}）。可继续登录。`,
    };
  } catch {
    if (!isHttps) {
      return {
        type: 'warn',
        title: '存在风险',
        desc: '当前为 HTTP 且探测失败。请检查地址是否可达，或改用 HTTPS。',
      };
    }

    return {
      type: 'warn',
      title: '存在风险',
      desc: '探测失败（可能是网络不可达 / 证书异常 / 跨域被阻止）。仍可保存地址并稍后重试登录。',
    };
  } finally {
    window.clearTimeout(timeout);
  }
};

const emitCloudSyncStateChanged = () => {
  const settings = CloudSyncStorage.loadSettings();
  const session = CloudSyncStorage.loadSession();
  const event = new CustomEvent('cloudSyncStateChanged', {
    detail: {
      enabled: settings.enabled,
      serverUrl: settings.serverUrl,
      isLoggedIn: Boolean(session?.accessToken),
    },
  });
  window.dispatchEvent(event);
};

const onToggleEnabled = () => {
  if (localEnabled.value) {
    if (!serverUrlSaved.value) {
      localEnabled.value = false;
      showToast('启用云同步前请先配置并保存服务端地址', 'error');
      return;
    }
  }

  CloudSyncStorage.saveSettings({
    serverUrl: serverUrlSaved.value,
    enabled: localEnabled.value,
  });
  emitCloudSyncStateChanged();
};

const saveServerUrl = async () => {
  const parsed = normalizeServerUrl(serverUrlInput.value);
  if (!parsed.ok || !parsed.normalized) {
    showToast(parsed.message || '地址不合法', 'error');
    return;
  }

  serverUrlSaved.value = parsed.normalized;
  CloudSyncStorage.saveSettings({
    serverUrl: serverUrlSaved.value,
    enabled: localEnabled.value,
  });

  if (parsed.warn) {
    showToast(parsed.warn, 'success');
  } else {
    showToast('地址已保存', 'success');
  }

  isProbing.value = true;
  try {
    probeResult.value = await probeReachability(serverUrlSaved.value);
  } finally {
    isProbing.value = false;
  }

  emitCloudSyncStateChanged();
};

const login = async () => {
  if (!canLogin.value) return;
  isLoggingIn.value = true;
  try {
    await cloudSyncApi.login({
      userName: userName.value.trim(),
      password: password.value,
    });
    showToast('登录成功', 'success');
    emitCloudSyncStateChanged();
    await pullTasks();
  } finally {
    isLoggingIn.value = false;
  }
};

const logout = () => {
  cloudSyncApi.logout();
  showToast('已登出', 'success');
  emitCloudSyncStateChanged();
};

const pullTasks = async () => {
  const event = new CustomEvent('cloudSyncPullTasksRequested');
  window.dispatchEvent(event);
};

function handleOpenSettings() {
  loadLocalState();
  probeResult.value = null;
  isOpen.value = true;
}

function close() {
  isOpen.value = false;
}

onMounted(() => {
  window.addEventListener('openCloudSyncSettings', handleOpenSettings);
});
</script>

<style scoped>
.overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.dialog {
  background: white;
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  width: 92%;
  max-width: 720px;
  overflow: hidden;
}

.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #e5e7eb;
}

.dialog-header h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 650;
  color: #111827;
}

.close-button {
  background: none;
  border: none;
  font-size: 28px;
  color: #6b7280;
  cursor: pointer;
  padding: 0;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  transition: background 0.2s;
}

.close-button:hover {
  background: #f3f4f6;
  color: #111827;
}

.dialog-body {
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.section {
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  padding: 14px;
  background: #ffffff;
}

.section-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #6b7280;
  text-transform: uppercase;
  margin-bottom: 10px;
}

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  user-select: none;
}

.checkbox-row input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: #3b82f6;
}

.hint {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.5;
  color: #6b7280;
}

.mono {
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 12px;
}

.form-row {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.text-input {
  flex: 1;
  min-width: 240px;
  padding: 10px 12px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  font-size: 14px;
  background: white;
  transition: border-color 0.2s, box-shadow 0.2s;
}

.text-input:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

.probe {
  margin-top: 10px;
  border-radius: 10px;
  padding: 10px 12px;
  border: 1px solid #e5e7eb;
  background: #f9fafb;
}

.probe.success {
  border-color: rgba(34, 197, 94, 0.25);
  background: rgba(34, 197, 94, 0.08);
}

.probe.warn {
  border-color: rgba(245, 158, 11, 0.25);
  background: rgba(245, 158, 11, 0.08);
}

.probe.error {
  border-color: rgba(239, 68, 68, 0.25);
  background: rgba(239, 68, 68, 0.08);
}

.probe-title {
  font-size: 13px;
  font-weight: 650;
  color: #111827;
}

.probe-desc {
  font-size: 12px;
  color: #374151;
  margin-top: 4px;
  line-height: 1.4;
}

.button-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid #e5e7eb;
  background: #f9fafb;
}

.btn {
  padding: 10px 14px;
  border: none;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-primary {
  background: #3b82f6;
  color: white;
}

.btn-primary:hover:enabled {
  background: #2563eb;
}

.btn-secondary {
  background: white;
  color: #374151;
  border: 1px solid #d1d5db;
}

.btn-secondary:hover:enabled {
  background: #f3f4f6;
  border-color: #9ca3af;
}
</style>
