<script setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import BbModal from "../components/BbModal.vue";
import BbSelect from "../components/BbSelect.vue";
import { apiFetch, ensureMe, tokenRef, userRef } from "../lib/api";

const loggedIn = computed(() => Boolean(tokenRef.value));
const isAdmin = computed(() => userRef.value?.role === "admin");

const isDesktop = ref(true);
function syncViewport() {
  isDesktop.value = window.innerWidth >= 960;
}

const loading = ref(false);
const error = ref("");
const items = ref([]);

const users = ref([]);
const selectedUserId = ref("");
const selectedUser = computed(() => users.value.find((u) => u.id === selectedUserId.value) || null);

const showPasswords = ref(false);
const revealPasswords = computed(() => isAdmin.value || showPasswords.value);

function loadSessionFlag() {
  try {
    showPasswords.value = sessionStorage.getItem("bb_show_passwords") === "1";
  } catch {
    showPasswords.value = false;
  }
}

function toggleShowPasswords() {
  showPasswords.value = !showPasswords.value;
  try {
    sessionStorage.setItem("bb_show_passwords", showPasswords.value ? "1" : "0");
  } catch {
    // ignore
  }
}

async function loadUsers() {
  if (!isAdmin.value) return;
  users.value = await apiFetch("/admin/users");
  if (!selectedUserId.value && users.value.length) selectedUserId.value = users.value[0].id;
}

async function loadCredentials() {
  if (!loggedIn.value) return;
  loading.value = true;
  error.value = "";

  try {
    if (isAdmin.value) {
      if (!selectedUserId.value) {
        items.value = [];
        return;
      }
      const qs = revealPasswords.value ? "?includePassword=true" : "";
      items.value = await apiFetch(`/admin/users/${selectedUserId.value}/credentials${qs}`);
      return;
    }

    const qs = revealPasswords.value ? "?includePassword=true" : "";
    items.value = await apiFetch(`/credentials${qs}`);
  } catch (e) {
    error.value = e.message || String(e);
  } finally {
    loading.value = false;
  }
}


const editOpen = ref(false);
const editId = ref("");
const editSiteOrigin = ref("");
const editUsername = ref("");
const editPassword = ref("");
const editBusy = ref(false);

function startEdit(item) {
  editId.value = item.id;
  editSiteOrigin.value = item.siteOrigin || "";
  editUsername.value = item.username || "";
  editPassword.value = "";
  editOpen.value = true;
}

async function submitEdit() {
  const payload = {
    siteOrigin: editSiteOrigin.value.trim(),
    username: editUsername.value.trim()
  };
  if (editPassword.value) payload.password = editPassword.value;

  editBusy.value = true;
  error.value = "";
  try {
    if (isAdmin.value) {
      await apiFetch(`/admin/users/${selectedUserId.value}/credentials/${editId.value}`, {
        method: "PATCH",
        body: JSON.stringify(payload)
      });
    } else {
      await apiFetch(`/credentials/${editId.value}`, {
        method: "PATCH",
        body: JSON.stringify(payload)
      });
    }
    editOpen.value = false;
    await loadCredentials();
  } catch (e) {
    error.value = e.message || String(e);
  } finally {
    editBusy.value = false;
  }
}

const confirmOpen = ref(false);
const pendingDeleteId = ref("");
const deleteBusy = ref(false);

function askDelete(id) {
  pendingDeleteId.value = id;
  confirmOpen.value = true;
}

async function confirmDelete() {
  if (!pendingDeleteId.value) return;
  deleteBusy.value = true;
  error.value = "";
  try {
    if (isAdmin.value) {
      await apiFetch(`/admin/users/${selectedUserId.value}/credentials/${pendingDeleteId.value}`, { method: "DELETE" });
    } else {
      await apiFetch(`/credentials/${pendingDeleteId.value}`, { method: "DELETE" });
    }
    confirmOpen.value = false;
    pendingDeleteId.value = "";
    await loadCredentials();
  } catch (e) {
    error.value = e.message || String(e);
  } finally {
    deleteBusy.value = false;
  }
}

function cancelDelete() {
  confirmOpen.value = false;
  pendingDeleteId.value = "";
}

onMounted(async () => {
  syncViewport();
  window.addEventListener("resize", syncViewport);
  loadSessionFlag();
  if (loggedIn.value) await ensureMe();
  await loadUsers();
  await loadCredentials();
});

watch([() => selectedUserId.value, () => showPasswords.value], async () => {
  await loadCredentials();
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", syncViewport);
});
</script>

<template>
  <section class="bb-page">
    <div class="bb-pageHeader">
      <div>
        <h1 style="margin: 0;">密码管理</h1>
        <div class="bb-muted" style="margin-top: 4px;">仅 PC 显示。可管理已保存的网站账号密码。</div>
      </div>

      <div class="bb-row" style="gap: 8px;">
        <button v-if="!isAdmin" class="bb-btn bb-btn--secondary" type="button" @click="toggleShowPasswords">
          {{ showPasswords ? '隐藏明文' : '显示明文' }}
        </button>
      </div>
    </div>

    <div v-if="!isDesktop" class="bb-empty" style="margin-top: 12px;">
      <div style="font-weight: 900;">仅 PC 可见</div>
      <div class="bb-muted" style="margin-top: 6px;">请在电脑端访问此页面。</div>
    </div>

    <div v-else class="bb-card" style="margin-top: 12px;">
      <div v-if="isAdmin" class="bb-row" style="gap: 10px; margin-bottom: 12px;">
        <div style="min-width: 220px; flex: 1;">
          <BbSelect
            v-model="selectedUserId"
            :options="users.map((u) => ({ value: u.id, label: u.email }))"
            placeholder="选择用户"
          />
        </div>
        <div class="bb-muted">
          {{ selectedUser ? `当前：${selectedUser.email}` : '请选择用户' }}
        </div>
      </div>

      <p v-if="error" class="bb-alert bb-alert--error">{{ error }}</p>
      <p v-else-if="loading" class="bb-muted">加载中…</p>

      <div v-else-if="!items.length" class="bb-empty" style="margin-top: 12px;">
        <div style="font-weight: 700;">暂无记录</div>
        <div class="bb-muted" style="margin-top: 6px;">没有保存的账号密码。</div>
      </div>

      <div v-else class="bb-credList">
        <div v-for="c in items" :key="c.id" class="bb-card bb-card--interactive bb-credItem">
          <div class="bb-credRow">
            <div class="bb-credMeta">
              <div class="bb-credSite">{{ c.siteOrigin }}</div>
              <div class="bb-credUser">账号：{{ c.username }}</div>
            </div>
            <div class="bb-credActions">
              <button class="bb-btn bb-btn--secondary" type="button" @click="startEdit(c)">编辑</button>
              <button class="bb-btn bb-btn--danger" type="button" @click="askDelete(c.id)">删除</button>
            </div>
          </div>
          <div class="bb-credPwd">
            <span class="bb-muted">密码：</span>
            <span v-if="revealPasswords">{{ c.password || '（空）' }}</span>
            <span v-else class="bb-muted">已隐藏</span>
          </div>
        </div>
      </div>
    </div>

    <BbModal v-model="editOpen" title="编辑账号" max-width="560px">
      <div class="bb-modalForm">
        <input v-model="editSiteOrigin" class="bb-input" placeholder="网站来源 (https://example.com)" />
        <input v-model="editUsername" class="bb-input" placeholder="账号" />
        <input v-model="editPassword" class="bb-input" type="password" placeholder="新密码（可留空不改）" @keydown.enter.prevent="submitEdit" />
        <div class="bb-row" style="justify-content: flex-end; gap: 10px;">
          <button class="bb-btn bb-btn--secondary" type="button" @click="editOpen = false">取消</button>
          <button class="bb-btn" type="button" :disabled="editBusy" @click="submitEdit">保存</button>
        </div>
      </div>
    </BbModal>

    <BbModal :model-value="confirmOpen" title="删除账号密码" max-width="520px" @update:model-value="(v) => (v ? (confirmOpen = true) : cancelDelete())">
      <div class="bb-muted" style="line-height: 1.6;">确定删除该记录？</div>
      <div class="bb-row" style="justify-content: flex-end; gap: 10px; margin-top: 14px;">
        <button class="bb-btn bb-btn--secondary" type="button" @click="cancelDelete">取消</button>
        <button class="bb-btn bb-btn--danger" type="button" :disabled="deleteBusy" @click="confirmDelete">删除</button>
      </div>
    </BbModal>
  </section>
</template>

<style scoped>
.bb-credList { display: grid; gap: 10px; }
.bb-credItem { display: grid; gap: 8px; }
.bb-credRow { display: flex; gap: 12px; justify-content: space-between; align-items: center; flex-wrap: wrap; }
.bb-credMeta { display: grid; gap: 4px; min-width: 0; }
.bb-credSite { font-weight: 900; word-break: break-all; }
.bb-credUser { font-size: 13px; }
.bb-credActions { display: flex; gap: 8px; flex-wrap: wrap; }
.bb-credPwd { font-size: 13px; }
</style>
