<script setup lang="ts">
import { computed, reactive, watch } from "vue";
import type { SystemSetting } from "../types";

const props = defineProps<{
  settings: SystemSetting[];
  saveState: "idle" | "saving" | "saved" | "error";
}>();

defineEmits<{
  saveSettings: [settings: SystemSetting[]];
}>();

const draft = reactive<Record<string, SystemSetting>>({});

const groups = [
  {
    title: "基础",
    eyebrow: "general",
    keys: ["site.title"],
  },
  {
    title: "认证",
    eyebrow: "auth",
    keys: ["auth.allow_email_login", "auth.allow_github_login", "auth.allow_registration"],
  },
  {
    title: "SMTP",
    eyebrow: "mail",
    keys: ["smtp.host", "smtp.port", "smtp.username", "smtp.password", "smtp.sender_email"],
  },
  {
    title: "GitHub",
    eyebrow: "github",
    keys: ["github.api_base_url", "github.web_base_url", "github.oauth_client_id", "github.oauth_client_secret"],
  },
];

const labels: Record<string, string> = {
  "site.title": "CMS 标题",
  "auth.allow_email_login": "允许邮箱登录",
  "auth.allow_github_login": "允许 GitHub 登录",
  "auth.allow_registration": "开放注册",
  "smtp.host": "SMTP 地址",
  "smtp.port": "SMTP 端口",
  "smtp.username": "SMTP 用户名",
  "smtp.password": "SMTP 密码",
  "smtp.sender_email": "发件人邮箱",
  "github.api_base_url": "GitHub API 地址",
  "github.web_base_url": "GitHub Web 地址",
  "github.oauth_client_id": "OAuth Client ID",
  "github.oauth_client_secret": "OAuth Client Secret",
};

const booleanKeys = new Set([
  "auth.allow_email_login",
  "auth.allow_github_login",
  "auth.allow_registration",
]);

watch(
  () => props.settings,
  (settings) => {
    Object.keys(draft).forEach((key) => delete draft[key]);
    settings.forEach((setting) => {
      draft[setting.key] = { ...setting };
    });
  },
  { immediate: true },
);

const draftSettings = computed(() => Object.values(draft));

function getSetting(key: string) {
  if (!draft[key]) {
    draft[key] = {
      key,
      value: "",
      encrypted: key.includes("password") || key.includes("secret"),
      updatedAt: "",
    };
  }

  return draft[key];
}

function isBooleanKey(key: string) {
  return booleanKeys.has(key);
}
</script>

<template>
  <section class="panel is-visible">
    <div class="settings-toolbar">
      <p class="save-status" :class="`is-${saveState}`">
        <template v-if="saveState === 'saved'">系统设置已保存</template>
        <template v-else-if="saveState === 'error'">保存失败，请查看日志</template>
        <template v-else-if="saveState === 'saving'">正在保存系统设置</template>
        <template v-else>系统设置保存到 SQLite 数据库</template>
      </p>
      <button class="primary-button" type="button" @click="$emit('saveSettings', draftSettings)">
        {{ saveState === "saving" ? "保存中" : "保存设置" }}
      </button>
    </div>

    <div class="settings-grid">
      <section v-for="group in groups" :key="group.title" class="management-card">
        <p class="eyebrow">{{ group.eyebrow }}</p>
        <h3>{{ group.title }}</h3>
        <label
          v-for="key in group.keys"
          :key="key"
          :class="{ 'toggle-row': isBooleanKey(key) }"
        >
          <span>{{ labels[key] || key }}</span>
          <input
            v-if="isBooleanKey(key)"
            :checked="getSetting(key).value === 'true'"
            type="checkbox"
            @change="getSetting(key).value = ($event.target as HTMLInputElement).checked ? 'true' : 'false'"
          />
          <input
            v-else
            v-model="getSetting(key).value"
            :placeholder="getSetting(key).encrypted ? '留空表示不修改敏感值' : ''"
            :type="getSetting(key).encrypted ? 'password' : 'text'"
          />
        </label>
      </section>
    </div>
  </section>
</template>
