<template>
  <PageContainer title="平台用户管理">
    <QueryToolbar>
      <el-input
        v-model="keyword"
        placeholder="Search name / phone / email"
        clearable
        class="w-input-md"
        @keyup.enter="handleSearch"
      />
      <el-button @click="handleSearch">Search</el-button>
      <el-button @click="handleResetSearch">Reset</el-button>
      <el-button v-if="canManage" @click="openImportDialog">Batch Import</el-button>
      <el-button v-if="canManage" @click="downloadPlatformUserTemplate">Download Template</el-button>
      <el-button v-if="canManage" type="primary" @click="openCreateDrawer">Create User</el-button>
      <el-button v-if="canManage" @click="load">Refresh</el-button>
    </QueryToolbar>

    <el-table :data="rows" class="mt-md" empty-text="No data">
      <el-table-column prop="userName" label="Name" />
      <el-table-column prop="phone" label="Phone" />
      <el-table-column prop="email" label="Email" />
      <el-table-column prop="status" label="Status" width="120" :formatter="statusFormatter" />
      <el-table-column label="Validity" width="340">
        <template #default="{ row }">
          <span>{{ row.validFrom || "-" }} ~ {{ row.validTo || "-" }}</span>
        </template>
      </el-table-column>
      <el-table-column label="Role" width="280">
        <template #default="{ row }">
          <el-select v-model="roleMap[row.id]" class="w-input-sm" placeholder="Select role" clearable>
            <el-option v-for="role in roles" :key="role.id" :label="role.roleName" :value="role.id" />
          </el-select>
          <el-button
            v-if="canManage"
            size="small"
            class="ml-sm"
            :disabled="!roleMap[row.id]"
            @click="handleAssignRole(row.id)"
          >
            Assign
          </el-button>
        </template>
      </el-table-column>
      <el-table-column label="Actions" width="380">
        <template #default="{ row }">
          <el-button v-if="canManage" size="small" @click="openEditDrawer(row)">Edit</el-button>
          <el-button
            v-if="canManage"
            size="small"
            type="success"
            :disabled="row.status === 'ENABLED'"
            @click="handleEnable(row.id)"
          >
            Enable
          </el-button>
          <el-button
            v-if="canManage"
            size="small"
            type="warning"
            :disabled="row.status !== 'ENABLED'"
            @click="handleDisable(row.id)"
          >
            Disable
          </el-button>
          <el-button v-if="canManage" size="small" @click="handleResetPassword(row.id)">Reset Password</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-drawer
      v-model="drawerVisible"
      :title="isEditMode ? 'Edit Platform User' : 'Create Platform User'"
      :size="DRAWER_SIZE.md"
      destroy-on-close
      :close-on-click-modal="false"
    >
      <el-form ref="formRef" :model="form" label-position="left" :label-width="LABEL_WIDTH.md" :rules="formRules">
        <el-form-item label="Name" prop="userName">
          <el-input v-model="form.userName" />
        </el-form-item>
        <el-form-item label="Phone" prop="phone">
          <el-input v-model="form.phone" />
        </el-form-item>
        <el-form-item :label="isEditMode ? 'Password (leave blank to keep)' : 'Password'" prop="password">
          <el-input
            v-model="form.password"
            type="password"
            show-password
            :placeholder="isEditMode ? 'Leave blank to keep current password' : 'Enter password'"
          />
        </el-form-item>
        <el-form-item label="Email" prop="email">
          <el-input v-model="form.email" />
        </el-form-item>
        <el-form-item label="Valid From">
          <el-date-picker v-model="form.validFrom" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" />
        </el-form-item>
        <el-form-item label="Valid To">
          <el-date-picker v-model="form.validTo" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="drawerVisible = false">Cancel</el-button>
        <el-button v-if="canManage" type="primary" @click="handleSubmit">
          {{ isEditMode ? "Save" : "Create" }}
        </el-button>
      </template>
    </el-drawer>

    <el-dialog v-model="importVisible" title="Batch Import Platform Users" :width="DIALOG_WIDTH.lg" destroy-on-close>
      <div class="text-secondary mb-sm">
        Supports `.csv` or tab-delimited text. Header order:
        `userName, phone, password, email, validFrom, validTo, roleCode`
      </div>
      <div v-if="roles.length" class="text-secondary mb-sm">
        Available role codes: {{ roleCodeText }}
      </div>
      <el-upload
        :auto-upload="false"
        :show-file-list="false"
        accept=".csv,.txt"
        :on-change="handleImportFileChange"
      >
        <el-button>Select File</el-button>
      </el-upload>
      <div v-if="importFileName" class="mt-sm text-secondary">Selected file: {{ importFileName }}</div>
      <el-input
        v-model="importText"
        type="textarea"
        :rows="10"
        class="mt-md"
        placeholder="You can also paste CSV content here. The first row must contain headers."
        @input="syncImportPreview"
      />
      <div v-if="importPreview.length" class="mt-md">
        <div class="mb-sm">Preview first {{ importPreview.length }} rows:</div>
        <el-table :data="importPreview" size="small" max-height="240">
          <el-table-column prop="userName" label="Name" />
          <el-table-column prop="phone" label="Phone" />
          <el-table-column prop="email" label="Email" />
          <el-table-column prop="roleCode" label="Role Code" />
        </el-table>
      </div>
      <div v-if="lastImportResult" class="mt-md">
        <el-alert
          :title="`Import result: success ${lastImportResult.success}, failed ${lastImportResult.failed}`"
          :type="lastImportResult.failed ? 'warning' : 'success'"
          show-icon
          :closable="false"
        />
        <el-button v-if="lastImportResult.errors?.length" class="mt-sm" @click="downloadImportErrorSnapshot">
          Download Failed Snapshot
        </el-button>
        <el-table v-if="lastImportResult.errors?.length" :data="lastImportResult.errors" size="small" class="mt-sm" max-height="220">
          <el-table-column prop="rowNo" label="Row" width="90" />
          <el-table-column prop="identifier" label="Identifier" width="220" />
          <el-table-column prop="message" label="Reason" />
        </el-table>
      </div>
      <template #footer>
        <el-button @click="importVisible = false">Close</el-button>
        <el-button @click="downloadPlatformUserTemplate">Download Template</el-button>
        <el-button type="primary" :loading="importLoading" @click="submitImportUsers">Start Import</el-button>
      </template>
    </el-dialog>
  </PageContainer>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { useRoute, useRouter } from "vue-router";
import PageContainer from "../../components/PageContainer.vue";
import QueryToolbar from "../../components/QueryToolbar.vue";
import { DRAWER_SIZE, DIALOG_WIDTH, LABEL_WIDTH } from "../../constants/ui";
import {
  assignPlatformUserRole,
  batchImportPlatformUsers,
  createPlatformUser,
  disablePlatformUser,
  enablePlatformUser,
  fetchPlatformRoles,
  fetchPlatformUsers,
  resetPlatformUserPassword,
  updatePlatformUser,
} from "../../api/modules";
import { PERMS } from "../../constants/permissions";
import { useAuthStore } from "../../stores/auth";
import { toZhStatus } from "../../utils/status";
import {
  downloadCsvRows,
  downloadCsvTemplate,
  findMissingHeaders,
  parseDelimitedText,
  readTextFile,
} from "../../utils/batchImport";

type PlatformImportRow = {
  userName: string;
  phone: string;
  password: string;
  email: string;
  validFrom: string;
  validTo: string;
  roleCode: string;
};

const rows = ref<any[]>([]);
const roles = ref<any[]>([]);
const roleMap = ref<Record<number, number | undefined>>({});
const authStore = useAuthStore();
const canManage = computed(() => authStore.hasPermission(PERMS.platform.userManage));
const drawerVisible = ref(false);
const isEditMode = ref(false);
const editingId = ref<number | null>(null);
const formRef = ref<FormInstance>();
const keyword = ref("");
const route = useRoute();
const router = useRouter();

const importVisible = ref(false);
const importLoading = ref(false);
const importText = ref("");
const importFileName = ref("");
const importPreview = ref<Array<{ userName: string; phone: string; email: string; roleCode: string }>>([]);
const lastImportResult = ref<any | null>(null);
const lastImportedUsers = ref<PlatformImportRow[] | null>(null);

const emptyForm = () => ({
  userName: "",
  phone: "",
  password: "",
  email: "",
  validFrom: "",
  validTo: "",
});

const form = ref(emptyForm());

const formRules = computed<FormRules>(() => ({
  userName: [{ required: true, message: "Please enter name", trigger: "blur" }],
  phone: [{ required: true, message: "Please enter phone", trigger: "blur" }],
  password: isEditMode.value ? [] : [{ required: true, message: "Please enter password", trigger: "blur" }],
}));

const roleCodeText = computed(() => {
  const codes = roles.value.map((item: any) => item?.roleCode).filter(Boolean);
  return codes.length ? codes.join(", ") : "-";
});

const statusFormatter = (_row: any, _column: any, value: unknown) => toZhStatus(value);

const openCreateDrawer = () => {
  isEditMode.value = false;
  editingId.value = null;
  form.value = emptyForm();
  drawerVisible.value = true;
};

const openEditDrawer = (row: any) => {
  isEditMode.value = true;
  editingId.value = row.id;
  form.value = {
    userName: row.userName || "",
    phone: row.phone || "",
    password: "",
    email: row.email || "",
    validFrom: row.validFrom || "",
    validTo: row.validTo || "",
  };
  drawerVisible.value = true;
};

const openImportDialog = () => {
  importVisible.value = true;
  importText.value = "";
  importFileName.value = "";
  importPreview.value = [];
  lastImportResult.value = null;
  lastImportedUsers.value = null;
};

const load = async () => {
  if (!canManage.value) {
    rows.value = [];
    roles.value = [];
    return;
  }
  const [userResp, roleResp] = await Promise.all([
    fetchPlatformUsers({ keyword: keyword.value.trim() || undefined }),
    fetchPlatformRoles(),
  ]);
  rows.value = userResp?.data?.list || [];
  roles.value = roleResp?.data?.list || [];
};

const syncKeywordFromRoute = async () => {
  const nextKeyword = String(route.query.keyword || "").trim();
  if (keyword.value !== nextKeyword) {
    keyword.value = nextKeyword;
  }
  await load();
};

const pushKeywordQuery = async () => {
  const nextKeyword = keyword.value.trim();
  const nextQuery = { ...route.query } as Record<string, any>;
  if (nextKeyword) {
    nextQuery.keyword = nextKeyword;
  } else {
    delete nextQuery.keyword;
  }
  await router.push({ path: route.path, query: nextQuery });
};

const handleSearch = async () => {
  await pushKeywordQuery();
};

const handleResetSearch = async () => {
  keyword.value = "";
  await pushKeywordQuery();
};

const handleSubmit = async () => {
  if (!formRef.value) {
    return;
  }
  const valid = await formRef.value.validate().catch(() => false);
  if (!valid) {
    return;
  }

  if (isEditMode.value && editingId.value) {
    await updatePlatformUser(editingId.value, form.value);
    ElMessage.success("Platform user updated");
  } else {
    await createPlatformUser(form.value);
    ElMessage.success("Platform user created");
  }
  drawerVisible.value = false;
  await load();
};

const handleAssignRole = async (userId: number) => {
  const roleId = roleMap.value[userId];
  if (!roleId) {
    return;
  }
  await assignPlatformUserRole({ userId, roleId });
  ElMessage.success("Role assigned");
};

const handleEnable = async (userId: number) => {
  await enablePlatformUser(userId);
  ElMessage.success("Platform user enabled");
  await load();
};

const handleDisable = async (userId: number) => {
  await disablePlatformUser(userId);
  ElMessage.success("Platform user disabled");
  await load();
};

const handleResetPassword = async (userId: number) => {
  const dialog = await ElMessageBox.prompt("Enter a new password", "Reset Platform User Password", {
    confirmButtonText: "Confirm",
    cancelButtonText: "Cancel",
    inputValue: "123456",
  }).catch(() => null);
  if (!dialog) {
    return;
  }
  await resetPlatformUserPassword(userId, { newPassword: dialog.value });
  ElMessage.success("Password reset");
};

const downloadPlatformUserTemplate = () => {
  downloadCsvTemplate(
    "platform-user-import-template.csv",
    ["userName", "phone", "password", "email", "validFrom", "validTo", "roleCode"],
    [["Platform Admin", "13800138000", "Abc12345!", "admin@example.com", "2026-04-20 09:00:00", "2099-12-31 23:59:59", "PLATFORM_ADMIN"]],
  );
};

const handleImportFileChange = async (uploadFile: any) => {
  const file = uploadFile?.raw as File | undefined;
  if (!file) {
    return;
  }
  importFileName.value = file.name;
  importText.value = await readTextFile(file);
  syncImportPreview();
};

const parseImportRows = (text: string): PlatformImportRow[] => {
  const rows = parseDelimitedText(text);
  if (!rows.length) {
    return [];
  }
  const [header, ...dataRows] = rows;
  const missingHeaders = findMissingHeaders(header, ["userName", "phone", "password"]);
  if (missingHeaders.length) {
    return [];
  }
  const headerIndex = new Map<string, number>();
  header.forEach((name, index) => {
    headerIndex.set(String(name || "").trim(), index);
  });
  return dataRows
    .filter((row) => row.some((cell) => String(cell || "").trim().length > 0))
    .map((row) => ({
      userName: row[headerIndex.get("userName") ?? 0] || "",
      phone: row[headerIndex.get("phone") ?? 1] || "",
      password: row[headerIndex.get("password") ?? 2] || "",
      email: row[headerIndex.get("email") ?? 3] || "",
      validFrom: row[headerIndex.get("validFrom") ?? 4] || "",
      validTo: row[headerIndex.get("validTo") ?? 5] || "",
      roleCode: row[headerIndex.get("roleCode") ?? 6] || "",
    }))
    .map((item) => ({
      ...item,
      userName: item.userName.trim(),
      phone: item.phone.trim(),
      password: item.password.trim(),
      email: item.email.trim(),
      validFrom: item.validFrom.trim(),
      validTo: item.validTo.trim(),
      roleCode: item.roleCode.trim(),
    }));
};

const syncImportPreview = () => {
  const parsed = parseImportRows(importText.value);
  importPreview.value = parsed.slice(0, 5).map((item) => ({
    userName: item.userName,
    phone: item.phone,
    email: item.email,
    roleCode: item.roleCode,
  }));
};

const validateImportHeaders = (text: string) => {
  const rows = parseDelimitedText(text);
  if (!rows.length) {
    return { ok: false, missingHeaders: ["userName", "phone", "password"] };
  }
  const [header] = rows;
  const missingHeaders = findMissingHeaders(header, ["userName", "phone", "password"]);
  return { ok: missingHeaders.length === 0, missingHeaders };
};

const submitImportUsers = async () => {
  const headerValidation = validateImportHeaders(importText.value);
  if (!headerValidation.ok) {
    ElMessage.warning(`Missing headers: ${headerValidation.missingHeaders.join(", ")}`);
    return;
  }
  const users = parseImportRows(importText.value);
  if (!users.length) {
    ElMessage.warning("Please provide import content first");
    return;
  }
  lastImportedUsers.value = users;
  importLoading.value = true;
  try {
    const resp = await batchImportPlatformUsers({ users });
    lastImportResult.value = resp?.data || null;
    if ((resp?.data?.failed || 0) > 0) {
      ElMessage.warning(`Import completed: success ${resp?.data?.success || 0}, failed ${resp?.data?.failed || 0}`);
    } else {
      ElMessage.success(`Import completed: success ${resp?.data?.success || 0}`);
    }
    await load();
  } finally {
    importLoading.value = false;
  }
};

const downloadImportErrorSnapshot = () => {
  const errors = lastImportResult.value?.errors || [];
  const sourceRows = lastImportedUsers.value || [];
  if (!errors.length || !sourceRows.length) {
    ElMessage.warning("No failed snapshot available");
    return;
  }
  const exportRows: string[][] = [[
    "userName",
    "phone",
    "password",
    "email",
    "validFrom",
    "validTo",
    "roleCode",
    "__error",
  ]];
  errors.forEach((error: any) => {
    const rowIndex = Number(error?.rowNo || 0) - 2;
    const item = sourceRows[rowIndex];
    if (!item) {
      return;
    }
    exportRows.push([
      item.userName || "",
      item.phone || "",
      item.password || "",
      item.email || "",
      item.validFrom || "",
      item.validTo || "",
      item.roleCode || "",
      String(error?.message || ""),
    ]);
  });
  downloadCsvRows("platform-user-import-error-snapshot.csv", exportRows);
};

watch(
  () => route.query.keyword,
  () => {
    syncKeywordFromRoute();
  },
);

onMounted(async () => {
  await syncKeywordFromRoute();
});
</script>
