<script setup lang="ts">
import { computed, nextTick, reactive, ref, watch } from 'vue';
import { useForm, useFormRules } from '@/hooks/common/form';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import BusinessTableActionCell, { type BusinessTableAction } from '@/components/custom/business-table-action-cell';
import BusinessUserSelect from '@/components/custom/business-user-select.vue';
import { formatDateTime, isActiveExecutionAssignee, withVirtualOwnerAssignee } from '../shared';

defineOptions({ name: 'ProjectExecutionAssigneeCurrentPanel' });

interface Props {
  execution: Api.Project.ProjectExecution | null;
  assignees: Api.Project.ExecutionAssignee[];
  userOptions: Api.SystemManage.UserSimple[];
  loading: boolean;
  canManageAssignee: boolean;
  canChangeOwner: boolean;
}

interface Emits {
  (e: 'add', payload: Api.Project.CreateExecutionAssigneeParams): void;
  (e: 'inactive', assignee: Api.Project.ExecutionAssignee, payload: Api.Project.InactiveExecutionAssigneeParams): void;
  (e: 'change-owner', payload: Api.Project.ChangeExecutionOwnerParams): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

const newAssigneeId = ref('');

const PAGE_SIZE = 5;
const currentPage = ref(1);

const displayAssignees = computed<Api.Project.ExecutionAssignee[]>(() => {
  const ownerId = props.execution?.ownerId;
  if (!ownerId) {
    return props.assignees;
  }

  const ownerNickname =
    props.execution?.ownerNickname?.trim() ||
    props.userOptions.find(item => item.id === ownerId)?.nickname?.trim() ||
    ownerId;

  return withVirtualOwnerAssignee(props.assignees, ownerId, ownerNickname, props.execution?.id ?? '');
});

const pagedAssignees = computed(() => {
  const start = (currentPage.value - 1) * PAGE_SIZE;
  return displayAssignees.value.slice(start, start + PAGE_SIZE);
});

watch(
  () => displayAssignees.value.length,
  total => {
    const maxPage = Math.max(1, Math.ceil(total / PAGE_SIZE));
    if (currentPage.value > maxPage) {
      currentPage.value = maxPage;
    }
  }
);

const { createRequiredRule } = useFormRules();

const inactiveTarget = ref<Api.Project.ExecutionAssignee | null>(null);
const inactiveModel = reactive({ reason: '' });
const { formRef: inactiveFormRef, validate: validateInactive } = useForm();
const inactiveRules = {
  reason: [createRequiredRule('请输入失效原因')]
} satisfies Record<string, App.Global.FormRule[]>;
const inactiveVisible = computed({
  get: () => Boolean(inactiveTarget.value),
  set: value => {
    if (!value) {
      inactiveTarget.value = null;
    }
  }
});

const ownerTarget = ref<Api.Project.ExecutionAssignee | null>(null);
const ownerModel = reactive({ reason: '' });
const ownerVisible = computed({
  get: () => Boolean(ownerTarget.value),
  set: value => {
    if (!value) {
      ownerTarget.value = null;
    }
  }
});

const currentOwnerId = computed(() => props.execution?.ownerId || '');

function isOwner(member: Api.Project.ExecutionAssignee) {
  return Boolean(currentOwnerId.value) && member.userId === currentOwnerId.value;
}

function isActiveAssignee(assignee: Api.Project.ExecutionAssignee) {
  return isActiveExecutionAssignee(assignee);
}

const activeAssigneeUserIds = computed(() => {
  const list = props.assignees.filter(item => isActiveExecutionAssignee(item)).map(item => item.userId);
  const ownerId = props.execution?.ownerId;
  // 负责人无论是否实际入库为协办人，都不允许再被加为协办人
  if (ownerId && !list.includes(ownerId)) {
    list.push(ownerId);
  }
  return list;
});

const userNicknameMap = computed(() => {
  const map = new Map<string, string>();
  props.userOptions.forEach(item => {
    if (item.id) {
      map.set(item.id, item.nickname?.trim() || item.id);
    }
  });
  return map;
});

function getAssigneeIndex(index: number) {
  return (currentPage.value - 1) * PAGE_SIZE + index + 1;
}

function getAssigneeDisplayName(assignee: Api.Project.ExecutionAssignee | null) {
  if (!assignee) return '';
  return assignee.userNickname?.trim() || userNicknameMap.value.get(assignee.userId) || assignee.userId || '--';
}

function buildAssigneeActions(row: Api.Project.ExecutionAssignee): BusinessTableAction[] {
  const actions: BusinessTableAction[] = [];

  if (props.canChangeOwner) {
    actions.push({
      key: 'set-owner',
      label: '设为负责人',
      buttonType: 'primary',
      onClick: () => openOwner(row)
    });
  }

  if (props.canManageAssignee) {
    actions.push({
      key: 'inactive',
      label: '失效',
      buttonType: 'danger',
      onClick: () => openInactive(row)
    });
  }

  return actions;
}

function handleAdd() {
  if (!newAssigneeId.value) {
    window.$message?.warning('请选择协办人');
    return;
  }

  emit('add', { userId: newAssigneeId.value });
  newAssigneeId.value = '';
}

async function openInactive(assignee: Api.Project.ExecutionAssignee) {
  inactiveTarget.value = assignee;
  inactiveModel.reason = '';
  await nextTick();
  inactiveFormRef.value?.clearValidate();
}

async function confirmInactive() {
  await validateInactive();

  if (!inactiveTarget.value) {
    return;
  }

  emit('inactive', inactiveTarget.value, { reason: inactiveModel.reason.trim() });
  inactiveTarget.value = null;
}

function openOwner(assignee: Api.Project.ExecutionAssignee) {
  ownerTarget.value = assignee;
  ownerModel.reason = '';
}

function confirmOwner() {
  if (!ownerTarget.value) {
    return;
  }

  emit('change-owner', {
    newOwnerId: ownerTarget.value.userId,
    reason: ownerModel.reason.trim() || null
  });
  ownerTarget.value = null;
}

function reset() {
  newAssigneeId.value = '';
  inactiveTarget.value = null;
  inactiveModel.reason = '';
  ownerTarget.value = null;
  ownerModel.reason = '';
  currentPage.value = 1;
}

defineExpose({ reset });
</script>

<template>
  <div v-loading="loading" class="assignee-current-panel">
    <div v-if="canManageAssignee" class="assignee-current-panel__toolbar">
      <BusinessUserSelect
        v-model="newAssigneeId"
        :options="userOptions"
        :exclude-user-ids="activeAssigneeUserIds"
        no-data-text="所有项目成员已加入执行"
        placeholder="选择用户加入执行"
        class="assignee-current-panel__user-select"
      />
      <ElButton type="primary" @click="handleAdd">新增协办人</ElButton>
    </div>

    <ElTable :data="pagedAssignees" :height="247" border row-key="id" size="default">
      <ElTableColumn type="index" :index="getAssigneeIndex" label="序号" width="64" align="center" />
      <ElTableColumn label="协办人" width="200" show-overflow-tooltip>
        <template #default="{ row }">
          <span class="assignee-current-panel__name">{{ getAssigneeDisplayName(row) }}</span>
        </template>
      </ElTableColumn>
      <ElTableColumn label="角色" width="140" align="center">
        <template #default="{ row }">
          <ElTag v-if="isOwner(row)" type="warning" effect="light">负责人</ElTag>
          <ElTag v-else type="info" effect="plain">协办人</ElTag>
        </template>
      </ElTableColumn>
      <ElTableColumn label="加入时间" min-width="200" align="center">
        <template #default="{ row }">
          {{ formatDateTime(row.joinedAt) }}
        </template>
      </ElTableColumn>
      <ElTableColumn label="操作" width="220" align="center" fixed="right">
        <template #default="{ row }">
          <BusinessTableActionCell v-if="!isOwner(row) && isActiveAssignee(row)" :actions="buildAssigneeActions(row)" />
          <span v-else class="assignee-current-panel__actions-empty">--</span>
        </template>
      </ElTableColumn>

      <template #empty>
        <ElEmpty description="当前执行暂无协办人" :image-size="80" />
      </template>
    </ElTable>

    <div class="assignee-current-panel__pagination">
      <ElPagination
        v-if="displayAssignees.length > PAGE_SIZE"
        v-model:current-page="currentPage"
        :page-size="PAGE_SIZE"
        :total="displayAssignees.length"
        layout="total, prev, pager, next"
        background
        size="small"
      />
    </div>

    <BusinessFormDialog
      v-model="inactiveVisible"
      :title="`失效协办人：${getAssigneeDisplayName(inactiveTarget)}`"
      preset="sm"
      append-to-body
      @confirm="confirmInactive"
    >
      <ElForm
        ref="inactiveFormRef"
        :model="inactiveModel"
        :rules="inactiveRules"
        label-position="top"
        :validate-on-rule-change="false"
      >
        <ElFormItem label="失效原因" prop="reason">
          <ElInput
            v-model="inactiveModel.reason"
            type="textarea"
            :rows="4"
            maxlength="500"
            show-word-limit
            placeholder="请输入失效原因"
          />
        </ElFormItem>
      </ElForm>
    </BusinessFormDialog>

    <BusinessFormDialog
      v-model="ownerVisible"
      :title="`设为负责人：${getAssigneeDisplayName(ownerTarget)}`"
      preset="sm"
      append-to-body
      @confirm="confirmOwner"
    >
      <ElForm :model="ownerModel" label-position="top">
        <ElFormItem label="变更原因">
          <ElInput
            v-model="ownerModel.reason"
            type="textarea"
            :rows="3"
            maxlength="500"
            show-word-limit
            placeholder="可选填写变更原因"
          />
        </ElFormItem>
      </ElForm>
    </BusinessFormDialog>
  </div>
</template>

<style scoped lang="scss">
.assignee-current-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.assignee-current-panel__toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}

.assignee-current-panel__user-select {
  width: 280px;
}

.assignee-current-panel__name {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  vertical-align: middle;
  white-space: nowrap;
}

.assignee-current-panel__actions-empty {
  color: var(--el-text-color-placeholder);
}

.assignee-current-panel__pagination {
  display: flex;
  justify-content: flex-end;
  min-height: 32px;
}
</style>
