<script setup lang="tsx">
import { computed, ref, watch } from 'vue';
import { ElButton, ElEmpty, ElTag } from 'element-plus';
import dayjs from 'dayjs';
import {
  fetchDeleteOrgLeaderRelation,
  fetchGetOrgLeaderCandidateUsers,
  fetchGetOrgLeaderListByDept,
  fetchGetUserPage
} from '@/service/api';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import BusinessTableActionCell from '@/components/custom/business-table-action-cell';
import { $t } from '@/locales';
import UserOrgLeaderOperateDialog from './user-org-leader-operate-dialog.vue';

defineOptions({ name: 'UserOrgLeaderDialog' });

interface Props {
  dept?: Api.SystemManage.Dept | null;
}

const props = defineProps<Props>();

const visible = defineModel<boolean>('visible', {
  default: false
});

const loading = ref(false);
const relations = ref<Api.SystemManage.OrgLeaderRelation[]>([]);
const candidateUsers = ref<Api.SystemManage.OrgLeaderCandidateUser[]>([]);
const operateVisible = ref(false);
const operateType = ref<UI.TableOperateType>('add');
const editingData = ref<Api.SystemManage.OrgLeaderRelation | null>(null);

const title = computed(() => {
  if (props.dept?.name) {
    return `${$t('page.system.user.orgLeaderTitle')} / ${props.dept.name}`;
  }

  return $t('page.system.user.orgLeaderTitle');
});

const total = computed(() => relations.value.length);

function formatTime(value?: number | null) {
  if (!value) {
    return '--';
  }

  return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
}

function isCandidateUser(item: unknown): item is Api.SystemManage.OrgLeaderCandidateUser {
  if (!item || typeof item !== 'object') {
    return false;
  }

  const record = item as Record<string, unknown>;

  return typeof record.id === 'number' && typeof record.nickname === 'string' && typeof record.deptId === 'number';
}

function mapUsersToCandidateUsers(users: Api.SystemManage.User[]): Api.SystemManage.OrgLeaderCandidateUser[] {
  const now = Date.now();

  return users
    .filter(item => !item.resignedAt || item.resignedAt > now)
    .map(item => ({
      id: String(item.id),
      nickname: item.nickname?.trim() || item.username,
      deptId: item.deptId,
      deptName: item.deptName ?? null
    }));
}

async function loadCandidateUsers(deptId: number) {
  const candidateResult = await fetchGetOrgLeaderCandidateUsers(deptId);

  if (!candidateResult.error && Array.isArray(candidateResult.data) && candidateResult.data.every(isCandidateUser)) {
    return candidateResult.data;
  }

  const userResult = await fetchGetUserPage({
    pageNo: 1,
    pageSize: 200,
    deptId,
    status: 0
  });

  if (userResult.error) {
    return [];
  }

  return mapUsersToCandidateUsers(userResult.data.list);
}

async function loadData() {
  if (!props.dept?.id) {
    relations.value = [];
    candidateUsers.value = [];
    return;
  }

  loading.value = true;

  const [relationResult, candidates] = await Promise.all([
    fetchGetOrgLeaderListByDept(props.dept.id),
    loadCandidateUsers(props.dept.id)
  ]);

  loading.value = false;

  relations.value = relationResult.error ? [] : relationResult.data;
  candidateUsers.value = candidates;
}

function openAdd() {
  operateType.value = 'add';
  editingData.value = null;
  operateVisible.value = true;
}

function openEdit(row: Api.SystemManage.OrgLeaderRelation) {
  operateType.value = 'edit';
  editingData.value = row;
  operateVisible.value = true;
}

async function handleDelete(row: Api.SystemManage.OrgLeaderRelation) {
  const { error } = await fetchDeleteOrgLeaderRelation(row.id);

  if (error) {
    return;
  }

  window.$message?.success($t('common.deleteSuccess'));
  await loadData();
}

async function handleDeleteAction(row: Api.SystemManage.OrgLeaderRelation) {
  try {
    await window.$messageBox?.confirm($t('common.confirmDelete'), $t('common.warning'), {
      confirmButtonText: $t('common.confirm'),
      cancelButtonText: $t('common.cancel'),
      type: 'warning'
    });
  } catch {
    return;
  }

  await handleDelete(row);
}

async function handleSubmitted() {
  operateVisible.value = false;
  await loadData();
}

watch(
  () => [visible.value, props.dept?.id] as const,
  async ([dialogVisible, deptId]) => {
    if (!dialogVisible || !deptId) {
      return;
    }

    await loadData();
  }
);
</script>

<template>
  <BusinessFormDialog v-model="visible" :title="title" preset="lg" :show-footer="false">
    <div class="flex-col-stretch gap-16px">
      <div class="flex items-center justify-between gap-12px">
        <div class="flex items-center gap-8px">
          <ElTag type="primary" effect="light">{{ dept?.name || $t('common.noData') }}</ElTag>
          <ElTag effect="plain">{{ total }}</ElTag>
        </div>
        <div class="flex items-center gap-8px">
          <ElButton type="primary" plain size="small" @click="openAdd">
            <template #icon>
              <icon-ic-round-plus class="text-icon" />
            </template>
            {{ $t('common.add') }}
          </ElButton>
          <ElButton plain size="small" @click="loadData">
            <template #icon>
              <icon-mdi-refresh class="text-icon" />
            </template>
            {{ $t('common.refresh') }}
          </ElButton>
        </div>
      </div>

      <div v-loading="loading" class="min-h-260px">
        <template v-if="relations.length">
          <div class="min-h-260px">
            <ElTable border :data="relations" :max-height="420">
              <ElTableColumn type="index" :label="$t('common.index')" width="64" />
              <ElTableColumn prop="userNickname" :label="$t('page.system.user.orgLeader')" min-width="140" />
              <ElTableColumn
                prop="effectiveFrom"
                :label="$t('page.system.user.effectiveFrom')"
                min-width="170"
                :formatter="row => formatTime(row.effectiveFrom)"
              />
              <ElTableColumn
                prop="effectiveUntil"
                :label="$t('page.system.user.effectiveUntil')"
                min-width="170"
                :formatter="row => formatTime(row.effectiveUntil)"
              />
              <ElTableColumn
                prop="remark"
                :label="$t('page.system.user.relationRemark')"
                min-width="180"
                show-overflow-tooltip
              />
              <ElTableColumn
                prop="createTime"
                :label="$t('page.system.user.createTime')"
                min-width="170"
                :formatter="row => formatTime(row.createTime)"
              />
              <ElTableColumn :label="$t('common.operate')" width="196" align="center" fixed="right">
                <template #default="{ row }">
                  <BusinessTableActionCell
                    :actions="[
                      {
                        key: 'edit',
                        label: $t('common.edit'),
                        buttonType: 'primary',
                        onClick: () => openEdit(row)
                      },
                      {
                        key: 'delete',
                        label: $t('common.delete'),
                        buttonType: 'danger',
                        onClick: () => handleDeleteAction(row)
                      }
                    ]"
                  />
                </template>
              </ElTableColumn>
            </ElTable>
          </div>
        </template>

        <div v-else class="min-h-260px flex items-center justify-center">
          <ElEmpty :description="$t('page.system.user.emptyLeader')" />
        </div>
      </div>
    </div>

    <UserOrgLeaderOperateDialog
      v-model:visible="operateVisible"
      :operate-type="operateType"
      :row-data="editingData"
      :dept="dept"
      :candidate-users="candidateUsers"
      @submitted="handleSubmitted"
    />
  </BusinessFormDialog>
</template>
