<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 } from '../shared';

defineOptions({ name: 'ProjectExecutionTaskAssigneeCurrentPanel' });

interface Props {
  task: Api.Project.ProjectTask | null;
  assignees: Api.Project.TaskAssigneeRef[];
  userOptions: Api.SystemManage.UserSimple[];
  loading: boolean;
  canManage: boolean;
}

interface Emits {
  (e: 'add', payload: Api.Project.CreateTaskAssigneeParams): void;
  (e: 'inactive', assignee: Api.Project.TaskAssigneeRef, payload: Api.Project.InactiveTaskAssigneeParams): void;
}

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

const newUserId = ref('');

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

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

watch(
  () => props.assignees.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.TaskAssigneeRef | 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 ownerId = computed(() => props.task?.ownerId || '');

const activeAssigneeUserIds = computed(() => props.assignees.map(item => item.userId));

const excludeUserIds = computed(() => {
  const ids = [...activeAssigneeUserIds.value];
  if (ownerId.value) {
    ids.push(ownerId.value);
  }
  return ids;
});

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.TaskAssigneeRef | null) {
  if (!assignee) return '';
  return assignee.nickname?.trim() || userNicknameMap.value.get(assignee.userId) || assignee.userId || '--';
}

function buildAssigneeActions(row: Api.Project.TaskAssigneeRef): BusinessTableAction[] {
  if (!props.canManage) {
    return [];
  }
  return [
    {
      key: 'inactive',
      label: '失效',
      buttonType: 'danger',
      onClick: () => openInactive(row)
    }
  ];
}

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

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

async function openInactive(assignee: Api.Project.TaskAssigneeRef) {
  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 reset() {
  newUserId.value = '';
  inactiveTarget.value = null;
  inactiveModel.reason = '';
  currentPage.value = 1;
}

defineExpose({ reset });
</script>

<template>
  <div v-loading="loading" class="task-assignee-current-panel">
    <div v-if="canManage" class="task-assignee-current-panel__toolbar">
      <BusinessUserSelect
        v-model="newUserId"
        :options="userOptions"
        :exclude-user-ids="excludeUserIds"
        no-data-text="暂无可选成员"
        placeholder="选择协办人"
        class="task-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="task-assignee-current-panel__name">{{ getAssigneeDisplayName(row) }}</span>
        </template>
      </ElTableColumn>
      <ElTableColumn label="加入时间" min-width="200" align="center">
        <template #default="{ row }">{{ formatDateTime(row.joinedAt) }}</template>
      </ElTableColumn>
      <ElTableColumn label="操作" width="120" align="center" fixed="right">
        <template #default="{ row }">
          <BusinessTableActionCell v-if="canManage" :actions="buildAssigneeActions(row)" />
          <span v-else class="task-assignee-current-panel__actions-empty">--</span>
        </template>
      </ElTableColumn>

      <template #empty>
        <ElEmpty description="当前任务暂无活跃协办人" :image-size="80" />
      </template>
    </ElTable>

    <div class="task-assignee-current-panel__pagination">
      <ElPagination
        v-if="assignees.length > PAGE_SIZE"
        v-model:current-page="currentPage"
        :page-size="PAGE_SIZE"
        :total="assignees.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>
  </div>
</template>

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

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

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

.task-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;
}

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

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