<script setup lang="ts">
import { computed, onMounted, reactive, ref } from "vue";
import {
  ElMessage,
  ElMessageBox,
  type FormInstance,
  type FormRules
} from "element-plus";
import {
  createEmployee,
  deleteEmployee,
  getEmployee,
  listEmployees,
  listRoles,
  listStores,
  updateEmployee,
  updateEmployeeStatus,
  type Employee,
  type EmployeePayload,
  type EmployeeStatus,
  type RoleOption,
  type StoreOption
} from "@/api/access";

import Plus from "~icons/ep/plus";
import Search from "~icons/ep/search";
import Refresh from "~icons/ep/refresh";
import EditPen from "~icons/ep/edit-pen";
import Delete from "~icons/ep/delete";
import CircleCheck from "~icons/ep/circle-check";
import CircleClose from "~icons/ep/circle-close";

defineOptions({
  name: "EmployeeManagement"
});

/** 表单状态复用后端员工 payload，id 用来切换创建/更新接口。 */
type EmployeeFormState = EmployeePayload & {
  id?: number;
};

/** 员工手机号按中国大陆手机号做前端第一层校验，最终唯一性仍由后端保证。 */
const phonePattern = /^1[3-9]\d{9}$/;
const tableLoading = ref(false);
const catalogLoading = ref(false);
const submitLoading = ref(false);
const dialogVisible = ref(false);
const formRef = ref<FormInstance>();
const employees = ref<Employee[]>([]);
const stores = ref<StoreOption[]>([]);
const roles = ref<RoleOption[]>([]);

const query = reactive({
  storeId: undefined as number | undefined,
  status: undefined as EmployeeStatus | undefined,
  keyword: "",
  page: 1,
  pageSize: 20
});

/** 员工列表由后端分页，这里只保存当前查询返回的分页摘要。 */
const pagination = reactive({
  total: 0,
  totalPages: 0
});

const form = reactive<EmployeeFormState>({
  storeId: undefined as unknown as number,
  name: "",
  phone: "",
  status: "ACTIVE",
  remark: "",
  roleIds: []
});

const rules: FormRules<EmployeeFormState> = {
  storeId: [{ required: true, message: "请选择所属门店", trigger: "change" }],
  name: [
    { required: true, message: "请输入员工姓名", trigger: "blur" },
    { max: 50, message: "员工姓名不能超过 50 个字符", trigger: "blur" }
  ],
  phone: [
    { required: true, message: "请输入手机号", trigger: "blur" },
    {
      pattern: phonePattern,
      message: "请输入正确的中国大陆手机号",
      trigger: "blur"
    }
  ],
  status: [{ required: true, message: "请选择员工状态", trigger: "change" }],
  roleIds: [{ type: "array", message: "请选择角色", trigger: "change" }],
  remark: [{ max: 500, message: "备注不能超过 500 个字符", trigger: "blur" }]
};

const activeCount = computed(
  () => employees.value.filter(item => item.status === "ACTIVE").length
);
const inactiveCount = computed(
  () => employees.value.filter(item => item.status === "INACTIVE").length
);
const dialogTitle = computed(() => (form.id ? "编辑员工" : "新增员工"));

function getErrorMessage(error: unknown, fallback: string) {
  const message = (
    error as { response?: { data?: { error?: { message?: string } } } }
  )?.response?.data?.error?.message;

  if (message) return message;
  if (error instanceof Error && error.message) return error.message;
  return fallback;
}

function formatTime(value: string) {
  return new Date(value).toLocaleString("zh-CN", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit"
  });
}

function resetFormState() {
  Object.assign(form, {
    id: undefined,
    storeId: stores.value[0]?.id,
    name: "",
    phone: "",
    status: "ACTIVE",
    remark: "",
    roleIds: []
  });
  formRef.value?.clearValidate();
}

/** 清理提交数据，避免把仅包含空格的备注写入后端。 */
function buildPayload(): EmployeePayload {
  return {
    storeId: form.storeId,
    name: form.name.trim(),
    phone: form.phone.trim(),
    status: form.status,
    remark: form.remark?.trim() ? form.remark.trim() : null,
    roleIds: form.roleIds
  };
}

/** 门店和角色是员工表单的基础字典，打开弹窗前必须先加载。 */
async function fetchCatalog() {
  catalogLoading.value = true;
  try {
    const [storeResult, roleResult] = await Promise.all([
      listStores(),
      listRoles()
    ]);
    stores.value = storeResult.data;
    roles.value = roleResult.data;
  } catch (error) {
    ElMessage.error(getErrorMessage(error, "加载门店和角色选项失败"));
  } finally {
    catalogLoading.value = false;
  }
}

/** 员工列表筛选、分页都交给后端，前端只传递当前查询条件。 */
async function fetchEmployees() {
  tableLoading.value = true;
  try {
    const result = await listEmployees({
      storeId: query.storeId,
      status: query.status,
      keyword: query.keyword.trim() || undefined,
      page: query.page,
      pageSize: query.pageSize
    });
    employees.value = result.data.items;
    pagination.total = result.data.pagination.total;
    pagination.totalPages = result.data.pagination.totalPages;
  } catch (error) {
    ElMessage.error(getErrorMessage(error, "加载员工列表失败"));
  } finally {
    tableLoading.value = false;
  }
}

function handleSearch() {
  query.page = 1;
  fetchEmployees();
}

function handleReset() {
  query.storeId = undefined;
  query.status = undefined;
  query.keyword = "";
  query.page = 1;
  query.pageSize = 20;
  fetchEmployees();
}

function handlePageChange(page: number) {
  query.page = page;
  fetchEmployees();
}

function handleSizeChange(pageSize: number) {
  query.page = 1;
  query.pageSize = pageSize;
  fetchEmployees();
}

function openCreateDialog() {
  resetFormState();
  dialogVisible.value = true;
}

/** 编辑前重新拉详情，确保角色绑定不是来自列表摘要的过期数据。 */
async function openEditDialog(row: Employee) {
  try {
    const result = await getEmployee(row.id);
    const employee = result.data;
    Object.assign(form, {
      id: employee.id,
      storeId: employee.storeId,
      name: employee.name,
      phone: employee.phone,
      status: employee.status,
      remark: employee.remark ?? "",
      roleIds: employee.roles.map(role => role.id)
    });
    dialogVisible.value = true;
    formRef.value?.clearValidate();
  } catch (error) {
    ElMessage.error(getErrorMessage(error, "加载员工详情失败"));
  }
}

async function submitForm() {
  await formRef.value?.validate();
  submitLoading.value = true;

  try {
    const payload = buildPayload();

    if (form.id) {
      await updateEmployee(form.id, payload);
      ElMessage.success("员工信息已更新");
    } else {
      await createEmployee(payload);
      ElMessage.success("员工已创建");
    }

    dialogVisible.value = false;
    fetchEmployees();
  } catch (error) {
    ElMessage.error(getErrorMessage(error, "保存员工失败"));
  } finally {
    submitLoading.value = false;
  }
}

async function toggleStatus(row: Employee) {
  const nextStatus: EmployeeStatus =
    row.status === "ACTIVE" ? "INACTIVE" : "ACTIVE";
  const action = nextStatus === "ACTIVE" ? "启用" : "停用";

  try {
    await ElMessageBox.confirm(
      `确认${action}员工「${row.name}」？`,
      "状态变更",
      {
        type: "warning",
        confirmButtonText: action,
        cancelButtonText: "取消"
      }
    );
    await updateEmployeeStatus(row.id, nextStatus);
    ElMessage.success(`已${action}`);
    fetchEmployees();
  } catch (error) {
    if (error !== "cancel") {
      ElMessage.error(getErrorMessage(error, "状态变更失败"));
    }
  }
}

async function removeEmployee(row: Employee) {
  try {
    await ElMessageBox.confirm(
      `删除后员工「${row.name}」会被软删除并停用，确认继续？`,
      "删除员工",
      {
        type: "warning",
        confirmButtonText: "删除",
        cancelButtonText: "取消"
      }
    );
    await deleteEmployee(row.id);
    ElMessage.success("员工已删除");

    if (employees.value.length === 1 && query.page > 1) {
      query.page -= 1;
    }
    fetchEmployees();
  } catch (error) {
    if (error !== "cancel") {
      ElMessage.error(getErrorMessage(error, "删除员工失败"));
    }
  }
}

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

<template>
  <section class="employee-page">
    <div class="page-heading">
      <div>
        <p class="eyebrow">门店员工权限管理</p>
        <h1>员工管理</h1>
      </div>
      <el-button type="primary" :icon="Plus" @click="openCreateDialog">
        新增员工
      </el-button>
    </div>

    <div class="summary-strip">
      <div class="summary-item">
        <span>总员工</span>
        <strong>{{ pagination.total }}</strong>
      </div>
      <div class="summary-item">
        <span>当前页启用</span>
        <strong>{{ activeCount }}</strong>
      </div>
      <div class="summary-item">
        <span>当前页停用</span>
        <strong>{{ inactiveCount }}</strong>
      </div>
      <div class="summary-item">
        <span>角色数量</span>
        <strong>{{ roles.length }}</strong>
      </div>
    </div>

    <div class="toolbar">
      <el-select
        v-model="query.storeId"
        clearable
        filterable
        placeholder="全部门店"
        class="toolbar-control"
        :loading="catalogLoading"
        @change="handleSearch"
      >
        <el-option
          v-for="store in stores"
          :key="store.id"
          :label="store.name"
          :value="store.id"
        />
      </el-select>
      <el-select
        v-model="query.status"
        clearable
        placeholder="全部状态"
        class="toolbar-control"
        @change="handleSearch"
      >
        <el-option label="启用" value="ACTIVE" />
        <el-option label="停用" value="INACTIVE" />
      </el-select>
      <el-input
        v-model="query.keyword"
        clearable
        class="keyword-input"
        placeholder="搜索姓名或手机号"
        @clear="handleSearch"
        @keyup.enter="handleSearch"
      />
      <div class="toolbar-actions">
        <el-button type="primary" :icon="Search" @click="handleSearch">
          查询
        </el-button>
        <el-button :icon="Refresh" @click="handleReset">重置</el-button>
      </div>
    </div>

    <div class="table-shell">
      <el-table
        v-loading="tableLoading"
        :data="employees"
        row-key="id"
        stripe
        class="employee-table"
      >
        <el-table-column prop="name" label="员工" min-width="160">
          <template #default="{ row }">
            <div class="employee-cell">
              <strong>{{ row.name }}</strong>
              <span>{{ row.phone }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="storeName" label="门店" min-width="150" />
        <el-table-column label="角色" min-width="220">
          <template #default="{ row }">
            <div class="role-tags">
              <el-tag
                v-for="role in row.roles"
                :key="role.id"
                effect="plain"
                size="small"
              >
                {{ role.name }}
              </el-tag>
              <span v-if="row.roles.length === 0" class="muted">未绑定</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="110">
          <template #default="{ row }">
            <el-tag
              :type="row.status === 'ACTIVE' ? 'success' : 'info'"
              effect="light"
            >
              {{ row.status === "ACTIVE" ? "启用" : "停用" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="remark" label="备注" min-width="180">
          <template #default="{ row }">
            <span>{{ row.remark || "-" }}</span>
          </template>
        </el-table-column>
        <el-table-column label="更新时间" width="180">
          <template #default="{ row }">
            {{ formatTime(row.updatedAt) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="260" fixed="right">
          <template #default="{ row }">
            <el-button
              link
              type="primary"
              :icon="EditPen"
              @click="openEditDialog(row)"
            >
              编辑
            </el-button>
            <el-button
              link
              :type="row.status === 'ACTIVE' ? 'warning' : 'success'"
              :icon="row.status === 'ACTIVE' ? CircleClose : CircleCheck"
              @click="toggleStatus(row)"
            >
              {{ row.status === "ACTIVE" ? "停用" : "启用" }}
            </el-button>
            <el-button
              link
              type="danger"
              :icon="Delete"
              @click="removeEmployee(row)"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-row">
        <span
          >共 {{ pagination.total }} 条，{{ pagination.totalPages }} 页</span
        >
        <el-pagination
          v-model:current-page="query.page"
          v-model:page-size="query.pageSize"
          background
          layout="sizes, prev, pager, next"
          :total="pagination.total"
          :page-sizes="[10, 20, 50, 100]"
          @current-change="handlePageChange"
          @size-change="handleSizeChange"
        />
      </div>
    </div>

    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="560px"
      destroy-on-close
    >
      <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-position="top"
        class="employee-form"
      >
        <el-form-item label="所属门店" prop="storeId">
          <el-select
            v-model="form.storeId"
            filterable
            placeholder="请选择门店"
            class="full-width"
            :loading="catalogLoading"
          >
            <el-option
              v-for="store in stores"
              :key="store.id"
              :label="store.name"
              :value="store.id"
            />
          </el-select>
        </el-form-item>
        <div class="form-grid">
          <el-form-item label="员工姓名" prop="name">
            <el-input v-model="form.name" maxlength="50" placeholder="请输入" />
          </el-form-item>
          <el-form-item label="手机号" prop="phone">
            <el-input
              v-model="form.phone"
              maxlength="11"
              placeholder="请输入 11 位手机号"
            />
          </el-form-item>
        </div>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="form.status">
            <el-radio-button label="ACTIVE">启用</el-radio-button>
            <el-radio-button label="INACTIVE">停用</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="角色" prop="roleIds">
          <el-select
            v-model="form.roleIds"
            multiple
            filterable
            collapse-tags
            collapse-tags-tooltip
            placeholder="请选择角色"
            class="full-width"
            :loading="catalogLoading"
          >
            <el-option
              v-for="role in roles"
              :key="role.id"
              :label="`${role.name}（${role.code}）`"
              :value="role.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="form.remark"
            type="textarea"
            maxlength="500"
            show-word-limit
            :rows="4"
            placeholder="可填写班次、权限说明或其他备注"
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitLoading" @click="submitForm">
          保存
        </el-button>
      </template>
    </el-dialog>
  </section>
</template>

<style scoped lang="scss">
.employee-page {
  min-height: 100%;
  padding: 20px;
  background: #f6f8fb;
}

.page-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;

  h1 {
    margin: 4px 0 0;
    font-size: 24px;
    font-weight: 650;
    color: #111827;
    letter-spacing: 0;
  }
}

.eyebrow {
  margin: 0;
  font-size: 13px;
  color: #64748b;
}

.summary-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.summary-item {
  padding: 14px 16px;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;

  span {
    display: block;
    margin-bottom: 8px;
    font-size: 13px;
    color: #64748b;
  }

  strong {
    font-size: 24px;
    font-weight: 700;
    color: #111827;
    letter-spacing: 0;
  }
}

.toolbar,
.table-shell {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 14px;
  margin-bottom: 16px;
}

.toolbar-control {
  width: 180px;
}

.keyword-input {
  width: 240px;
}

.toolbar-actions {
  display: flex;
  gap: 8px;
  margin-left: auto;
}

.table-shell {
  padding: 8px 0 14px;
  overflow: hidden;
}

.employee-table {
  width: 100%;
}

.employee-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;

  strong {
    font-weight: 650;
    color: #111827;
  }

  span {
    font-size: 12px;
    color: #64748b;
  }
}

.role-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.muted {
  color: #94a3b8;
}

.pagination-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px 0;
  font-size: 13px;
  color: #64748b;
}

.employee-form {
  padding-top: 4px;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.full-width {
  width: 100%;
}

@media (max-width: 760px) {
  .employee-page {
    padding: 12px;
  }

  .page-heading {
    align-items: flex-start;
    flex-direction: column;
  }

  .summary-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .toolbar-control,
  .keyword-input,
  .toolbar-actions {
    width: 100%;
    margin-left: 0;
  }

  .toolbar-actions {
    justify-content: flex-end;
  }

  .pagination-row {
    align-items: flex-start;
    flex-direction: column;
  }

  .form-grid {
    grid-template-columns: 1fr;
  }
}
</style>
