<script setup lang="ts">
import { computed, onMounted, reactive, ref } from "vue";
import {
  CheckCircle2,
  ChevronLeft,
  ChevronRight,
  Database,
  FolderCog,
  LoaderCircle,
  LockKeyhole,
  ServerCog,
  ShieldCheck,
  TriangleAlert,
} from "lucide-vue-next";

type SetupStatus = {
  ok: boolean;
  initialized: boolean;
  baseDir: string;
  configPath: string;
  defaults?: {
    provider?: string;
    sqlitePath?: string;
    mysqlDsn?: string;
    baseUrl?: string;
  };
};

type TestResult = {
  ok: boolean;
  provider: string;
  normalized?: Record<string, unknown>;
  maskedDsn?: string;
  latencyMs?: number;
  message?: string;
};

const steps = [
  { title: "环境确认", description: "确认服务基准目录和公开地址", icon: ServerCog },
  { title: "数据库选择", description: "选择 SQLite 或 MySQL", icon: Database },
  { title: "连接配置", description: "填写对应数据库参数", icon: FolderCog },
  { title: "连接测试", description: "由后端真实测试连接", icon: ShieldCheck },
  { title: "完成确认", description: "写入配置并创建默认账号", icon: LockKeyhole },
];

const currentStep = ref(0);
const loading = ref(false);
const status = ref<SetupStatus | null>(null);
const testResult = ref<TestResult | null>(null);
const error = ref("");
const completed = ref(false);

const form = reactive({
  baseUrl: "https://update.ymhut.cn",
  provider: "sqlite",
  sqliteDir: "storage",
  sqliteFile: "unified.sqlite",
  mysql: {
    host: "127.0.0.1",
    port: 3306,
    database: "ymhut_unified",
    username: "",
    password: "",
    charset: "utf8mb4",
    parseTime: true,
    tls: "false",
  },
});

const sqlitePath = computed(() => {
  const dir = form.sqliteDir.trim().replace(/[\\/]+$/g, "") || "storage";
  const file = form.sqliteFile.trim() || "unified.sqlite";
  return `${dir}/${file}`.replace(/\\/g, "/");
});

const canContinue = computed(() => {
  if (currentStep.value === 0) return form.baseUrl.trim().length > 0;
  if (currentStep.value === 1) return form.provider === "sqlite" || form.provider === "mysql";
  if (currentStep.value === 2) {
    if (form.provider === "sqlite") return form.sqliteDir.trim() && form.sqliteFile.trim();
    return form.mysql.host.trim() && form.mysql.port > 0 && form.mysql.database.trim() && form.mysql.username.trim();
  }
  if (currentStep.value === 3) return testResult.value?.ok === true;
  return true;
});

const payload = computed(() => ({
  provider: form.provider,
  baseUrl: form.baseUrl.trim(),
  sqlitePath: sqlitePath.value,
  mysql: {
    host: form.mysql.host.trim(),
    port: Number(form.mysql.port || 3306),
    database: form.mysql.database.trim(),
    username: form.mysql.username.trim(),
    password: form.mysql.password,
    charset: form.mysql.charset.trim() || "utf8mb4",
    parseTime: form.mysql.parseTime,
    tls: form.mysql.tls.trim() || "false",
  },
}));

async function api<T>(target: string, init: RequestInit = {}): Promise<T> {
  const headers = new Headers(init.headers);
  if (init.body && !headers.has("Content-Type")) headers.set("Content-Type", "application/json");
  const res = await fetch(target, { ...init, headers });
  const data = await res.json().catch(() => ({}));
  if (!res.ok || data.ok === false) throw new Error(data.message || data.error || `HTTP ${res.status}`);
  return data as T;
}

async function loadStatus() {
  loading.value = true;
  error.value = "";
  try {
    status.value = await api<SetupStatus>("/api/setup/status");
    form.baseUrl = status.value.defaults?.baseUrl || form.baseUrl;
    form.provider = status.value.defaults?.provider || "sqlite";
    const defaultSQLite = status.value.defaults?.sqlitePath || "storage/unified.sqlite";
    const normalized = defaultSQLite.replace(/\\/g, "/");
    const index = normalized.lastIndexOf("/");
    if (index > -1) {
      form.sqliteDir = normalized.slice(0, index) || "storage";
      form.sqliteFile = normalized.slice(index + 1) || "unified.sqlite";
    }
  } catch (err) {
    error.value = err instanceof Error ? err.message : String(err);
  } finally {
    loading.value = false;
  }
}

function nextStep() {
  if (!canContinue.value) return;
  if (currentStep.value < steps.length - 1) currentStep.value += 1;
}

function previousStep() {
  if (currentStep.value > 0) currentStep.value -= 1;
}

async function testDatabase() {
  loading.value = true;
  error.value = "";
  testResult.value = null;
  try {
    testResult.value = await api<TestResult>("/api/setup/database/test", {
      method: "POST",
      body: JSON.stringify(payload.value),
    });
  } catch (err) {
    error.value = err instanceof Error ? err.message : String(err);
  } finally {
    loading.value = false;
  }
}

async function completeSetup() {
  loading.value = true;
  error.value = "";
  try {
    await api("/api/setup/complete", {
      method: "POST",
      body: JSON.stringify(payload.value),
    });
    completed.value = true;
  } catch (err) {
    error.value = err instanceof Error ? err.message : String(err);
  } finally {
    loading.value = false;
  }
}

onMounted(loadStatus);
</script>

<template>
  <main class="setup-shell">
    <section class="setup-card">
      <aside class="setup-aside">
        <p class="eyebrow">update.ymhut.cn</p>
        <h1>初始化统一管理服务端</h1>
        <p>使用分步向导确认运行目录、数据库连接和默认账号。所有连接测试都由服务端完成。</p>

        <ol class="step-list">
          <li v-for="(step, index) in steps" :key="step.title" :class="{ active: currentStep === index, done: currentStep > index || completed }">
            <span><component :is="step.icon" :size="18" /></span>
            <div>
              <strong>{{ step.title }}</strong>
              <small>{{ step.description }}</small>
            </div>
          </li>
        </ol>
      </aside>

      <section class="setup-main">
        <header class="section-head">
          <div>
            <p class="eyebrow">Step {{ currentStep + 1 }} / {{ steps.length }}</p>
            <h2>{{ steps[currentStep].title }}</h2>
          </div>
          <span v-if="loading" class="badge"><LoaderCircle :size="15" class="spin" />处理中</span>
        </header>

        <p v-if="error" class="alert bad"><TriangleAlert :size="17" />{{ error }}</p>

        <section v-if="completed" class="complete-panel">
          <CheckCircle2 :size="42" />
          <h2>初始化完成</h2>
          <p>配置已写入服务基准目录。请重启服务后打开 <code>/admin/login</code>，使用默认账号 <strong>admin/admin</strong> 登录并立即修改密码。</p>
        </section>

        <template v-else>
          <div v-if="currentStep === 0" class="form-grid">
            <label class="wide">服务基准目录<input :value="status?.baseDir || '-'" readonly /></label>
            <label class="wide">配置文件路径<input :value="status?.configPath || '-'" readonly /></label>
            <label class="wide">规范服务地址<input v-model.trim="form.baseUrl" placeholder="https://update.ymhut.cn" /></label>
            <p class="hint wide">相对路径会以服务基准目录为准。生产环境可继续通过反向代理把其他域名重定向到该地址。</p>
          </div>

          <div v-if="currentStep === 1" class="choice-grid">
            <button :class="{ selected: form.provider === 'sqlite' }" @click="form.provider = 'sqlite'; testResult = null">
              <Database :size="24" />
              <strong>SQLite</strong>
              <span>推荐单机或轻量部署。默认写入 storage/unified.sqlite。</span>
            </button>
            <button :class="{ selected: form.provider === 'mysql' }" @click="form.provider = 'mysql'; testResult = null">
              <ServerCog :size="24" />
              <strong>MySQL</strong>
              <span>适合远端热同步、迁移和多实例备份场景。</span>
            </button>
          </div>

          <div v-if="currentStep === 2 && form.provider === 'sqlite'" class="form-grid">
            <label>SQLite 目录<input v-model.trim="form.sqliteDir" placeholder="storage" /></label>
            <label>SQLite 文件名<input v-model.trim="form.sqliteFile" placeholder="unified.sqlite" /></label>
            <label class="wide">最终路径<input :value="sqlitePath" readonly /></label>
            <p class="hint wide">保存时仍会由后端校验并创建目录，不允许路径逃逸。</p>
          </div>

          <div v-if="currentStep === 2 && form.provider === 'mysql'" class="form-grid">
            <label>Host<input v-model.trim="form.mysql.host" placeholder="127.0.0.1" /></label>
            <label>Port<input v-model.number="form.mysql.port" type="number" min="1" /></label>
            <label>Database<input v-model.trim="form.mysql.database" placeholder="ymhut_unified" /></label>
            <label>Username<input v-model.trim="form.mysql.username" autocomplete="username" /></label>
            <label>Password<input v-model="form.mysql.password" type="password" autocomplete="new-password" /></label>
            <label>Charset<input v-model.trim="form.mysql.charset" placeholder="utf8mb4" /></label>
            <label>parseTime<select v-model="form.mysql.parseTime"><option :value="true">true</option><option :value="false">false</option></select></label>
            <label>TLS<select v-model="form.mysql.tls"><option>false</option><option>true</option><option>skip-verify</option><option>preferred</option></select></label>
          </div>

          <div v-if="currentStep === 3" class="test-panel">
            <div class="summary-box">
              <span>数据库类型</span><strong>{{ form.provider }}</strong>
              <span>SQLite 路径</span><strong>{{ form.provider === "sqlite" ? sqlitePath : "-" }}</strong>
              <span>MySQL 地址</span><strong>{{ form.provider === "mysql" ? `${form.mysql.host}:${form.mysql.port}/${form.mysql.database}` : "-" }}</strong>
            </div>
            <button class="btn primary" data-testid="setup-test-database" @click="testDatabase"><ShieldCheck :size="17" />执行连接测试</button>
            <div v-if="testResult" class="result good">
              <CheckCircle2 :size="20" />
              <div>
                <strong>连接测试通过</strong>
                <p>{{ testResult.provider }}，耗时 {{ testResult.latencyMs || 0 }}ms</p>
                <code v-if="testResult.maskedDsn">{{ testResult.maskedDsn }}</code>
              </div>
            </div>
          </div>

          <div v-if="currentStep === 4" class="confirm-panel">
            <div class="summary-box">
              <span>服务地址</span><strong>{{ form.baseUrl }}</strong>
              <span>数据库</span><strong>{{ form.provider }}</strong>
              <span>连接</span><strong>{{ form.provider === "sqlite" ? sqlitePath : `${form.mysql.host}:${form.mysql.port}/${form.mysql.database}` }}</strong>
              <span>默认账号</span><strong>admin / admin</strong>
            </div>
            <p class="alert warn"><TriangleAlert :size="17" />初始化不会在此处修改默认密码。进入后台后登录页会提示默认密码，请立即修改。</p>
            <button class="btn primary" data-testid="setup-complete" @click="completeSetup"><CheckCircle2 :size="17" />写入配置并完成初始化</button>
          </div>

          <footer class="setup-actions">
            <button class="btn ghost" data-testid="setup-prev" :disabled="currentStep === 0" @click="previousStep"><ChevronLeft :size="17" />上一步</button>
            <button v-if="currentStep < steps.length - 1" class="btn primary" data-testid="setup-next" :disabled="!canContinue" @click="nextStep">下一步<ChevronRight :size="17" /></button>
          </footer>
        </template>
      </section>
    </section>
  </main>
</template>
