<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { PRODUCT_MANAGER_ROLE_CODE } from '@/constants/business';
import ProductTeamBatchDialog, {
  type BatchMemberPayload
} from '@/views/product/shared/components/product-team-batch-dialog.vue';
import ProductCreateTeamMemberDialog from './product-create-team-member-dialog.vue';
import type { ProductCreateBaseForm } from './product-create-base-form.vue';

defineOptions({ name: 'ProductCreateTeamStep' });

interface DraftMember {
  /** 客户端临时主键，仅用于 v-for 稳定 */
  key: string;
  userId: string;
  roleId: string;
  remark: string;
  /** true 表示由产品经理自动派生的锁定行 */
  locked: boolean;
}

interface Props {
  baseInfo: ProductCreateBaseForm;
  userOptions: Api.SystemManage.UserSimple[];
  roleOptions: Api.SystemManage.RoleSimple[];
  roleLoading: boolean;
  managerRoleError: string;
}

const props = defineProps<Props>();

const emit = defineEmits<{
  (e: 'update:members', members: Api.Product.CreateProductMemberParams[]): void;
}>();

const members = ref<DraftMember[]>([]);

const memberDialogVisible = ref(false);
const editingKey = ref<string | null>(null);

const batchDialogVisible = ref(false);

const batchDisabledUserIds = computed(() => members.value.map(item => item.userId).filter(Boolean));

const userLabelMap = computed(() => new Map(props.userOptions.map(item => [String(item.id), item.nickname])));

const managerRole = computed(() => props.roleOptions.find(item => item.code === PRODUCT_MANAGER_ROLE_CODE) ?? null);

const dialogInitial = computed(() => {
  if (!editingKey.value) return null;
  const target = members.value.find(item => item.key === editingKey.value);
  if (!target) return null;
  return { userId: target.userId, roleId: target.roleId, remark: target.remark };
});

function getUserNickname(userId: string) {
  return userLabelMap.value.get(String(userId)) || userId;
}

function getRoleName(roleId: string) {
  return props.roleOptions.find(item => item.id === roleId)?.name || '--';
}

function generateKey() {
  return `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
}

function refreshManagerRow() {
  const managerUserId = props.baseInfo.managerUserId;

  if (!managerUserId || !managerRole.value) {
    members.value = members.value.filter(item => !item.locked);
    emitMembers();
    return;
  }

  const lockedIndex = members.value.findIndex(item => item.locked);
  const lockedRow: DraftMember = {
    key: lockedIndex >= 0 ? members.value[lockedIndex].key : generateKey(),
    userId: managerUserId,
    roleId: managerRole.value.id,
    remark: lockedIndex >= 0 ? members.value[lockedIndex].remark : '',
    locked: true
  };

  if (lockedIndex >= 0) {
    members.value[lockedIndex] = lockedRow;
  } else {
    members.value = [lockedRow, ...members.value];
  }

  emitMembers();
}

function openBatch() {
  batchDialogVisible.value = true;
}

function handleBatchSubmit(payloads: BatchMemberPayload[]) {
  for (const p of payloads) {
    members.value.push({
      key: generateKey(),
      userId: p.userId,
      roleId: p.roleId,
      remark: p.remark,
      locked: false
    });
  }
  batchDialogVisible.value = false;
  emitMembers();
}

function openEdit(row: DraftMember) {
  editingKey.value = row.key;
  memberDialogVisible.value = true;
}

function removeMember(key: string) {
  members.value = members.value.filter(item => item.key !== key);
  emitMembers();
}

function handleMemberEditSubmit(payload: { userId: string; roleId: string; remark: string }) {
  if (!editingKey.value) return;
  const idx = members.value.findIndex(item => item.key === editingKey.value);
  if (idx >= 0) {
    members.value[idx] = {
      ...members.value[idx],
      roleId: payload.roleId,
      remark: payload.remark
    };
  }
  memberDialogVisible.value = false;
  emitMembers();
}

function emitMembers() {
  emit(
    'update:members',
    members.value.map(item => ({
      userId: item.userId,
      roleId: item.roleId,
      remark: item.remark.trim() || null,
      previousManagerUserId: null,
      previousManagerRoleId: null
    }))
  );
}

async function runValidate(): Promise<boolean> {
  if (props.managerRoleError) {
    window.$message?.error(props.managerRoleError);
    return false;
  }

  for (const item of members.value) {
    if (!item.userId || !item.roleId) {
      window.$message?.error('请补全所有成员的用户和角色');
      return false;
    }
  }

  const userIdSet = new Set<string>();

  for (const item of members.value) {
    if (userIdSet.has(item.userId)) {
      window.$message?.error(`成员「${getUserNickname(item.userId)}」重复，请检查`);
      return false;
    }

    userIdSet.add(item.userId);
  }

  return true;
}

watch(
  () => props.baseInfo.managerUserId,
  () => {
    if (!props.managerRoleError && managerRole.value) {
      refreshManagerRow();
    }
  }
);

// roleOptions 异步加载到位后,补一次 locked 行刷新
watch(managerRole, () => {
  if (!props.managerRoleError && managerRole.value && props.baseInfo.managerUserId) {
    refreshManagerRow();
  }
});

defineExpose({ validate: runValidate });
</script>

<template>
  <div v-loading="roleLoading" class="team-step">
    <button type="button" class="team-step__add" :disabled="Boolean(managerRoleError)" @click="openBatch">
      <icon-ep:plus class="team-step__add-icon" />
      <span>新增成员</span>
      <span class="team-step__add-hint">从部门 / 管理链路 / 全公司 批量选人</span>
    </button>

    <ElAlert
      v-if="managerRoleError"
      :title="managerRoleError"
      type="error"
      :closable="false"
      show-icon
      class="team-step__alert"
    />

    <div class="team-step__table-wrap">
      <ElTable :data="members" height="100%" border row-key="key" empty-text="点击右上角“新增成员”添加">
        <ElTableColumn type="index" label="序号" width="64" align="center" />
        <ElTableColumn label="成员姓名" min-width="120">
          <template #default="{ row }">
            {{ getUserNickname(row.userId) }}
          </template>
        </ElTableColumn>
        <ElTableColumn label="当前角色" min-width="140">
          <template #default="{ row }">
            {{ getRoleName(row.roleId) }}
          </template>
        </ElTableColumn>
        <ElTableColumn label="备注" min-width="200" show-overflow-tooltip>
          <template #default="{ row }">
            {{ row.remark || '--' }}
          </template>
        </ElTableColumn>
        <ElTableColumn label="操作" width="150" fixed="right" align="center">
          <template #default="{ row }">
            <div class="team-step__actions">
              <ElButton link type="primary" :disabled="row.locked" @click="openEdit(row)">编辑</ElButton>
              <ElButton link type="danger" :disabled="row.locked" @click="removeMember(row.key)">移除</ElButton>
            </div>
          </template>
        </ElTableColumn>
      </ElTable>
    </div>

    <ProductCreateTeamMemberDialog
      v-model:visible="memberDialogVisible"
      :initial="dialogInitial"
      :user-options="userOptions"
      :role-options="roleOptions"
      @submit="handleMemberEditSubmit"
    />

    <ProductTeamBatchDialog
      v-model:visible="batchDialogVisible"
      :user-options="userOptions"
      :role-options="roleOptions"
      :disabled-user-ids="batchDisabledUserIds"
      @submit="handleBatchSubmit"
    />
  </div>
</template>

<style scoped>
.team-step {
  display: flex;
  flex-direction: column;
  gap: 14px;
  height: 100%;
  min-height: 0;
}

.team-step__add {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 44px;
  padding: 0 16px;
  border: 1px dashed var(--el-border-color-darker);
  border-radius: 6px;
  background: transparent;
  color: var(--el-text-color-regular);
  font-size: 13px;
  cursor: pointer;
  transition:
    border-color 0.2s ease,
    color 0.2s ease,
    background-color 0.2s ease;
  flex-shrink: 0;
}

.team-step__add:hover:not(:disabled) {
  border-color: var(--el-color-primary);
  color: var(--el-color-primary);
  background: var(--el-color-primary-light-9);
}

.team-step__add:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.team-step__add-icon {
  font-size: 16px;
}

.team-step__add-hint {
  color: var(--el-text-color-placeholder);
  font-size: 12px;
  font-weight: 400;
}

.team-step__add:hover:not(:disabled) .team-step__add-hint {
  color: var(--el-color-primary);
  opacity: 0.7;
}

.team-step__alert {
  margin: 0;
  flex-shrink: 0;
}

.team-step__table-wrap {
  flex: 1 1 auto;
  min-height: 0;
}

.team-step__actions {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
</style>
