<template>
  <div class="page-container">
    <ProSplitLayout :side-width="280">
      <template #side>
        <!-- dept tree -->
        <div class="dept-tree-header">
          <h3>{{ t("dept.organizationStructure") }}</h3>
          <a-button type="primary" size="small" @click="handleAdd(null)">
            <template #icon><PlusOutlined /></template>
            {{ t("common.add") }}
          </a-button>
        </div>
        <div class="dept-tree-search">
          <a-input-search
            v-model:value="searchText"
            :placeholder="t('dept.searchDept')"
            allow-clear
            @search="loadDeptTree"
          />
        </div>
        <div class="dept-tree-body">
          <a-tree
            v-if="treeData.length"
            :tree-data="treeData"
            :field-names="{ title: 'name', key: 'id', children: 'children' }"
            :selected-keys="selectedKeys"
            default-expand-all
            block-node
            @select="handleTreeSelect"
          >
            <template #title="{ name, status }">
              <div class="tree-node">
                <span class="tree-node-name">{{ name }}</span>
                <span v-if="status === 'disabled'" class="tree-node-badge">{{
                  t("dept.disabled")
                }}</span>
              </div>
            </template>
          </a-tree>
          <a-empty v-else :image="null" :description="t('common.noData')" />
        </div>
      </template>

      <template #main>
        <!-- dept detail -->
        <template v-if="selectedDept">
          <div class="dept-detail-header">
            <div class="dept-detail-title">
              <h3>{{ selectedDept.name }}</h3>
              <ProStatus
                :value="selectedDept.status"
                :status-map="deptStatusMap"
              />
            </div>
            <a-space>
              <a-button
                type="primary"
                size="small"
                @click="handleAdd(selectedDept.id)"
              >
                <template #icon><PlusOutlined /></template>
                {{ t("dept.addChildDept") }}
              </a-button>
              <a-button size="small" @click="handleEdit(selectedDept)">
                <template #icon><EditOutlined /></template>
                {{ t("common.edit") }}
              </a-button>
              <a-button size="small" danger @click="handleDelete(selectedDept)">
                <template #icon><DeleteOutlined /></template>
                {{ t("common.delete") }}
              </a-button>
            </a-space>
          </div>
          <ProDescriptions
            :columns="deptDescColumns"
            :data="deptDescData"
            :column="2"
            bordered
            size="middle"
            class="dept-descriptions"
          />

          <!-- dept users -->
          <div class="dept-users">
            <ProTable
              ref="userTableRef"
              :key="selectedDept.id"
              :columns="userColumns"
              :request="loadDeptUsers"
              :search="false"
              :pagination="{ pageSize: 10 }"
              :toolbar="{
                title: `${t('dept.deptMembers')} (${userCount})`,
              }"
            >
              <template #toolbar-actions>
                <a-button type="primary" size="small" @click="openAddMember">
                  <template #icon><PlusOutlined /></template>
                  添加人员
                </a-button>
              </template>
              <template #bodyCell="{ column, record }">
                <template v-if="column.key === 'status'">
                  <a-tag :color="record.status === 'active' ? 'green' : 'default'">
                    {{ record.status === 'active' ? '正常' : '停用' }}
                  </a-tag>
                </template>
                <template v-else-if="column.key === 'roles'">
                  <a-tag v-for="r in record.roles" :key="r.id" size="small">
                    {{ r.name }}
                  </a-tag>
                </template>
                <template v-else-if="column.key === 'action'">
                  <a-popconfirm
                    title="确认将该成员移出此部门？"
                    @confirm="handleRemoveUser(record)"
                  >
                    <a-button type="link" danger size="small">移出部门</a-button>
                  </a-popconfirm>
                </template>
              </template>
            </ProTable>
          </div>
        </template>
        <div v-else class="dept-detail-empty">
          <a-empty :description="t('dept.selectDeptNode')" />
        </div>
      </template>
    </ProSplitLayout>

    <!-- add/edit modal -->
    <a-modal
      v-model:open="modalVisible"
      :title="modalTitle"
      @ok="handleSubmit"
      :width="520"
    >
      <a-form :model="form" :label-col="{ span: 6 }" style="margin-top: 16px">
        <a-form-item :label="t('dept.parentDept')">
          <a-tree-select
            v-model:value="form.parentId"
            :tree-data="parentTreeData"
            :field-names="{ label: 'name', value: 'id', children: 'children' }"
            :placeholder="t('dept.noneTopLevelDept')"
            allow-clear
            tree-default-expand-all
          />
        </a-form-item>
        <a-form-item :label="t('dept.deptName')" required>
          <a-input
            v-model:value="form.name"
            :placeholder="t('dept.pleaseEnterDeptName')"
          />
        </a-form-item>
        <a-form-item :label="t('dept.leader')">
          <a-input
            v-model:value="form.leader"
            :placeholder="t('dept.pleaseEnterLeader')"
          />
        </a-form-item>
        <a-form-item :label="t('dept.phone')">
          <a-input
            v-model:value="form.phone"
            :placeholder="t('dept.pleaseEnterPhone')"
          />
        </a-form-item>
        <a-form-item :label="t('dept.email')">
          <a-input
            v-model:value="form.email"
            :placeholder="t('dept.pleaseEnterEmail')"
          />
        </a-form-item>
        <a-form-item :label="t('dept.sort')">
          <a-input-number
            v-model:value="form.sort"
            :min="0"
            style="width: 100%"
          />
        </a-form-item>
        <a-form-item :label="t('dept.status')">
          <a-radio-group v-model:value="form.status">
            <a-radio value="enabled">{{ t("dept.enabled") }}</a-radio>
            <a-radio value="disabled">{{ t("dept.disabled") }}</a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item :label="t('dept.remark')">
          <a-textarea
            v-model:value="form.remark"
            :placeholder="t('dept.pleaseEnterRemark')"
            :rows="3"
          />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- add member modal -->
    <a-modal
      v-model:open="addMemberVisible"
      title="添加人员"
      :confirm-loading="addMemberLoading"
      @ok="handleAddMembers"
      :width="480"
    >
      <a-form :label-col="{ span: 4 }" style="margin-top: 16px">
        <a-form-item label="目标部门">
          <a-input :value="selectedDept?.name" disabled />
        </a-form-item>
        <a-form-item label="选择用户" required>
          <a-select
            v-model:value="selectedUserIds"
            mode="multiple"
            placeholder="搜索并选择用户"
            :options="candidateUsers"
            :field-names="{ label: 'label', value: 'id' }"
            show-search
            :filter-option="filterCandidate"
            style="width: 100%"
            :max-tag-count="3"
          />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import type { Department } from "@/types/dept";
import type {
  ProTableColumn,
  ProDescriptionItem,
  ProStatusMap,
} from "@/types/pro";

import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message, Modal } from "antdv-next";
import { ref, computed } from "vue";
import { useI18n } from "vue-i18n";

import {
  getDeptTree,
  getDeptList,
  createDept,
  updateDept,
  deleteDept,
} from "@/api/dept";
import { getUserList, saveUser } from "@/api/user";
import ProDescriptions from "@/components/Pro/ProDescriptions/index.vue";
import ProSplitLayout from "@/components/Pro/ProSplitLayout/index.vue";
import ProStatus from "@/components/Pro/ProStatus/index.vue";
import ProTable from "@/components/Pro/ProTable/index.vue";

const { t } = useI18n();

const deptStatusMap = computed<ProStatusMap>(() => ({
  enabled: { text: t("dept.enabled"), color: "#52c41a" },
  disabled: { text: t("dept.disabled"), color: "#bfbfbf" },
}));

const searchText = ref("");
const treeData = ref<Department[]>([]);
const flatList = ref<Department[]>([]);
const selectedKeys = ref<string[]>([]);

const buildTree = (list: Department[]): Department[] => {
  const map = new Map<string, Department>();
  const roots: Department[] = [];
  for (const item of list) {
    map.set(item.id, { ...item, children: [] });
  }
  for (const item of map.values()) {
    if (item.parentId && map.has(item.parentId)) {
      map.get(item.parentId)!.children!.push(item);
    } else {
      roots.push(item);
    }
  }
  return roots;
};

const selectedDept = computed(() => {
  if (!selectedKeys.value.length) return null;
  return flatList.value.find((d) => d.id === selectedKeys.value[0]) || null;
});

const userCount = ref(0);
const userTableRef = ref<{ refresh: () => void } | null>(null);

// add member modal
const addMemberVisible = ref(false);
const addMemberLoading = ref(false);
const selectedUserIds = ref<string[]>([]);
const candidateUsers = ref<{ id: string; label: string }[]>([]);
const candidateUsersMap = ref<Map<string, any>>(new Map());

const parentTreeData = computed(() => {
  const root: Department = {
    id: "",
    name: t("dept.noneTopLevelDept"),
    parentId: null,
    sort: 0,
    status: "enabled",
    createTime: "",
    updateTime: "",
  };
  return [{ ...root, children: treeData.value }];
});

// modal
const modalVisible = ref(false);
const modalTitle = computed(() =>
  form.value.id ? t("dept.editDept") : t("dept.createDept"),
);
const form = ref<Partial<Department>>({
  name: "",
  parentId: null,
  leader: "",
  phone: "",
  email: "",
  sort: 0,
  status: "enabled",
  remark: "",
});

const userColumns = computed<ProTableColumn[]>(() => [
  { title: "用户名", dataIndex: "username", key: "username", width: 110 },
  { title: "姓名", dataIndex: "realName", key: "realName", width: 100 },
  { title: "电话", dataIndex: "phone", key: "phone", width: 120 },
  { title: "邮箱", dataIndex: "email", key: "email", width: 150, ellipsis: true },
  { title: "角色", dataIndex: "roles", key: "roles", width: 140 },
  { title: "状态", dataIndex: "status", key: "status", width: 70 },
  { title: "操作", dataIndex: "action", key: "action", width: 90 },
]);

const deptDescColumns = computed<ProDescriptionItem[]>(() => [
  { label: t("dept.deptName"), dataIndex: "name" },
  { label: t("dept.parentDept"), dataIndex: "parentName" },
  { label: t("dept.leader"), dataIndex: "leader" },
  { label: t("dept.phone"), dataIndex: "phone" },
  { label: t("dept.email"), dataIndex: "email" },
  { label: t("dept.sort"), dataIndex: "sort" },
  { label: t("dept.createTime"), dataIndex: "createTime" },
  { label: t("dept.updateTime"), dataIndex: "updateTime" },
  { label: t("dept.remark"), dataIndex: "remark", span: 2 },
]);

const deptDescData = computed(() => {
  if (!selectedDept.value) return {};
  return {
    ...selectedDept.value,
    parentName: getParentName(selectedDept.value.parentId),
  };
});

const getParentName = (parentId: string | null) => {
  if (!parentId) return t("dept.noneTopLevel");
  return flatList.value.find((d) => d.id === parentId)?.name || "-";
};

const loadDeptUsers = async () => {
  if (!selectedDept.value) return { data: [], total: 0, success: true };
  try {
    const res: any = await getUserList({
      dept_id: selectedDept.value.id,
      pageSize: 50,
    });
    if (res.code === 1 && res.data) {
      userCount.value = res.data.total || 0;
      return { data: res.data.list || [], total: res.data.total || 0, success: true };
    }
  } catch {
    // ignore
  }
  return { data: [], total: 0, success: false };
};

const loadDeptTree = async () => {
  try {
    const params: Record<string, unknown> = {};
    if (searchText.value) params.name = searchText.value;
    const [treeRes, listRes] = await Promise.all([
      getDeptTree(params),
      getDeptList(),
    ]);
    if (treeRes.code === 1) treeData.value = buildTree(treeRes.data);
    if (listRes.code === 1) flatList.value = listRes.data;
    if (!selectedKeys.value.length && treeData.value.length) {
      selectedKeys.value = [treeData.value[0].id];
    }
  } catch (error: unknown) {
    console.error(t("dept.loadDataFailed"), (error as Error).message);
  }
};

const filterCandidate = (input: string, option: { label: string }) => {
  return option.label.toLowerCase().includes(input.toLowerCase());
};

async function handleRemoveUser(record: any) {
  try {
    const res: any = await saveUser({ ...record, dept_id: undefined });
    if (res.code === 1) {
      message.success("已移出部门");
      userTableRef.value?.refresh();
    } else {
      message.error(res.message || "操作失败");
    }
  } catch {
    message.error("操作失败");
  }
}

async function openAddMember() {
  selectedUserIds.value = [];
  candidateUsersMap.value.clear();
  try {
    const res: any = await getUserList({ pageSize: 1000 });
    if (res.code === 1 && res.data) {
      const filtered = (res.data.list || [])
        .filter((u: any) => u.dept_id !== selectedDept.value?.id);
      candidateUsers.value = filtered.map((u: any) => {
        candidateUsersMap.value.set(u.id, u);
        return { id: u.id, label: `${u.username} (${u.realName || u.user_name})` };
      });
    }
  } catch {
    candidateUsers.value = [];
  }
  addMemberVisible.value = true;
}

async function handleAddMembers() {
  if (!selectedUserIds.value.length) {
    message.warning("请选择至少一个用户");
    return;
  }
  addMemberLoading.value = true;
  try {
    for (const userId of selectedUserIds.value) {
      const userData = candidateUsersMap.value.get(userId);
      if (!userData) continue;
      const res: any = await saveUser({ ...userData, dept_id: selectedDept.value?.id });
      if (res.code !== 1) {
        message.error(res.message || "添加失败");
        addMemberLoading.value = false;
        return;
      }
    }
    message.success("添加成功");
    addMemberVisible.value = false;
    userTableRef.value?.refresh();
  } catch {
    message.error("操作失败");
  } finally {
    addMemberLoading.value = false;
  }
}

const handleTreeSelect = (keys: string[]) => {
  if (keys.length) selectedKeys.value = keys;
};

const handleAdd = (parentId: string | null) => {
  form.value = {
    name: "",
    parentId,
    leader: "",
    phone: "",
    email: "",
    sort: 0,
    status: "enabled",
    remark: "",
  };
  modalVisible.value = true;
};

const handleEdit = (dept: Department) => {
  form.value = { ...dept };
  modalVisible.value = true;
};

const handleDelete = (dept: Department) => {
  const hasChildren = flatList.value.some((d) => d.parentId === dept.id);
  if (hasChildren) {
    message.warning(t("dept.hasChildrenWarning"));
    return;
  }
  Modal.confirm({
    title: t("dept.confirmDelete"),
    content: t("dept.confirmDeleteContent", { name: dept.name }),
    onOk: async () => {
      try {
        const response = await deleteDept(dept.id);
        if (response.code === 1) {
          message.success(t("dept.deleteSuccess"));
          selectedKeys.value = [];
          loadDeptTree();
        } else {
          message.error(response.message || t("dept.deleteFailed"));
        }
      } catch (_error: unknown) {
        message.error(t("dept.deleteFailed"));
      }
    },
  });
};

const handleSubmit = async () => {
  if (!form.value.name) {
    message.warning(t("dept.pleaseEnterDeptName"));
    return;
  }
  try {
    if (form.value.id) {
      const response = await updateDept({ ...form.value, id: form.value.id });
      if (response.code === 1) {
        message.success(t("dept.updateSuccess"));
        modalVisible.value = false;
        loadDeptTree();
      } else {
        message.error(response.message || t("dept.operateFailed"));
      }
    } else {
      const response = await createDept(form.value);
      if (response.code === 1) {
        message.success(t("dept.createSuccess"));
        modalVisible.value = false;
        loadDeptTree();
      } else {
        message.error(response.message || t("dept.operateFailed"));
      }
    }
  } catch (_error: unknown) {
    message.error(t("dept.operateFailed"));
  }
};

// init
loadDeptTree();
</script>

<style scoped lang="scss">
// dept tree content
.dept-tree-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;

  h3 {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--color-text);
  }
}

.dept-tree-search {
  margin-bottom: 12px;
}

.dept-tree-body {
  flex: 1;
  overflow-y: auto;

  &::-webkit-scrollbar {
    width: 4px;
  }
  &::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.1);
    border-radius: 4px;
  }

  :deep(.ant-tree-node-content-wrapper) {
    flex: 1;
  }

  .tree-node {
    display: flex;
    align-items: center;
    gap: 8px;

    .tree-node-name {
      flex: 1;
    }

    .tree-node-badge {
      font-size: 11px;
      padding: 0 6px;
      border-radius: 8px;
      background: #fff1f0;
      color: #cf1322;
      line-height: 18px;
    }
  }
}

// dept detail content
.dept-detail-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--color-border-secondary, #f0f0f0);

  .dept-detail-title {
    display: flex;
    align-items: center;
    gap: 12px;

    h3 {
      margin: 0;
      font-size: 17px;
      font-weight: 600;
    }
  }
}

.dept-descriptions {
  margin-bottom: 24px;
}

.dept-users {
  :deep(.ant-table-thead > tr > th) {
    background: var(--color-fill-quaternary);
  }
}

.dept-detail-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}
</style>
