<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import type { RouteKey } from '@elegant-router/types';
import { useRouterPush } from '@/hooks/common/router';
import PersonalItemOperateDialog from '@/views/personal-center/my-item/modules/personal-item-operate-dialog.vue';
import {
  type WorkbenchTodoDeadlineFilter,
  type WorkbenchTodoItem,
  type WorkbenchTodoMainTab,
  buildWorkbenchTodoItems,
  filterWorkbenchTodoItemsByCategory,
  filterWorkbenchTodoItemsByDeadline,
  isWorkbenchTodoOverdue,
  sortWorkbenchTodoItemsByPriority
} from '../homepage';
import { workbenchTodoMock } from '../mock';
import WorkbenchModuleCard from './workbench-module-card.vue';

type SortKey = 'created' | 'priority' | 'deadline';

defineOptions({ name: 'WorkbenchTodoPanel' });

interface Props {
  editing?: boolean;
  collapsed?: boolean;
}

withDefaults(defineProps<Props>(), { editing: false, collapsed: false });

defineEmits<{
  (e: 'hide'): void;
  (e: 'toggle-collapse'): void;
}>();

const { routerPushByKey } = useRouterPush();

const PAGE_SIZE = 5;

const activeTab = ref<WorkbenchTodoMainTab>('all');
const activeDeadlineFilter = ref<WorkbenchTodoDeadlineFilter>(null);
const activeSort = ref<SortKey>('deadline');
const currentPage = ref(1);

const sortOptions = computed<Array<{ key: SortKey; label: string }>>(() => {
  const base: Array<{ key: SortKey; label: string }> = [
    { key: 'deadline', label: '截止时间' },
    { key: 'created', label: '创建时间' }
  ];
  if (activeTab.value === 'task') {
    base.push({ key: 'priority', label: '优先级' });
  }
  return base;
});

const mainTabs: Array<{ key: WorkbenchTodoMainTab; label: string }> = [
  { key: 'all', label: '全部' },
  { key: 'task', label: '任务' },
  { key: 'ticket', label: '工单' },
  { key: 'personal', label: '个人事项' },
  { key: 'review', label: '待评审' }
];

const deadlineFilters: Array<{ key: Exclude<WorkbenchTodoDeadlineFilter, null>; label: string }> = [
  { key: 'overdue', label: '已逾期' },
  { key: 'today', label: '今日到期' },
  { key: 'week', label: '本周到期' }
];

const allItems = computed(() => buildWorkbenchTodoItems(workbenchTodoMock));

const addDialogVisible = ref(false);

function handleOpenAdd() {
  addDialogVisible.value = true;
}

function handleAddSubmitted() {
  activeTab.value = 'personal';
  activeDeadlineFilter.value = null;
}

const tabCounts = computed(() => {
  const counts: Record<WorkbenchTodoMainTab, number> = {
    all: allItems.value.length,
    task: 0,
    ticket: 0,
    personal: 0,
    review: 0
  };
  allItems.value.forEach(item => {
    counts[item.category] += 1;
  });
  return counts;
});

const tabOverdueCount = computed(() => {
  const map: Record<WorkbenchTodoMainTab, number> = {
    all: 0,
    task: 0,
    ticket: 0,
    personal: 0,
    review: 0
  };
  allItems.value.forEach(item => {
    if (!isWorkbenchTodoOverdue(item)) return;
    map.all += 1;
    map[item.category] += 1;
  });
  return map;
});

const itemsInTab = computed(() => filterWorkbenchTodoItemsByCategory(allItems.value, activeTab.value));

const filteredItems = computed(() => filterWorkbenchTodoItemsByDeadline(itemsInTab.value, activeDeadlineFilter.value));

const sortedItems = computed(() => {
  const base = filteredItems.value;
  if (activeSort.value === 'priority') {
    return sortWorkbenchTodoItemsByPriority(base, 'desc');
  }
  if (activeSort.value === 'deadline') {
    return [...base].sort((left, right) => {
      const leftValue = left.remainingDays === null ? Number.POSITIVE_INFINITY : left.remainingDays;
      const rightValue = right.remainingDays === null ? Number.POSITIVE_INFINITY : right.remainingDays;
      return leftValue - rightValue;
    });
  }
  return base;
});

const currentSortLabel = computed(
  () => sortOptions.value.find(option => option.key === activeSort.value)?.label ?? '排序'
);

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

watch([activeTab, activeDeadlineFilter, activeSort], () => {
  currentPage.value = 1;
});

function handleSelectTab(key: WorkbenchTodoMainTab) {
  if (activeTab.value === key) return;
  activeTab.value = key;
  activeDeadlineFilter.value = null;
  if (key !== 'task' && activeSort.value === 'priority') {
    activeSort.value = 'deadline';
  }
}

function handleSelectDeadlineFilter(key: Exclude<WorkbenchTodoDeadlineFilter, null>) {
  activeDeadlineFilter.value = activeDeadlineFilter.value === key ? null : key;
}

function handleSelectSort(key: SortKey) {
  activeSort.value = key;
}

function handleClickItem(item: WorkbenchTodoItem) {
  if (!item.routeKey) return;
  routerPushByKey(item.routeKey as RouteKey);
}

function getDeadlineToneClass(item: WorkbenchTodoItem) {
  if (isWorkbenchTodoOverdue(item)) return 'workbench-todo__deadline--rose';
  if (item.remainingDays === 0) return 'workbench-todo__deadline--amber';
  return 'workbench-todo__deadline--slate';
}
</script>

<template>
  <WorkbenchModuleCard
    title="我的待办"
    icon="mdi:clipboard-text-clock-outline"
    :editing="editing"
    :collapsed="collapsed"
    @hide="$emit('hide')"
    @toggle-collapse="$emit('toggle-collapse')"
  >
    <div class="workbench-todo__tabs">
      <div class="workbench-todo__tabs-group">
        <ElTooltip
          v-for="tab in mainTabs"
          :key="tab.key"
          :content="`已逾期 ${tabOverdueCount[tab.key]} 项，建议尽快处理`"
          :disabled="tabOverdueCount[tab.key] === 0"
          placement="top"
          effect="dark"
        >
          <button
            type="button"
            class="workbench-todo__tab"
            :class="{ 'workbench-todo__tab--active': activeTab === tab.key }"
            @click="handleSelectTab(tab.key)"
          >
            <span>{{ tab.label }}</span>
            <span class="workbench-todo__tab-count">{{ tabCounts[tab.key] }}</span>
            <span v-if="tabOverdueCount[tab.key] > 0" class="workbench-todo__tab-dot" />
          </button>
        </ElTooltip>
      </div>

      <button type="button" class="workbench-todo__add" @click="handleOpenAdd">
        <SvgIcon icon="mdi:plus" class="workbench-todo__add-icon" />
        <span>个人事项</span>
      </button>
    </div>

    <div class="workbench-todo__filters">
      <div class="workbench-todo__filters-left">
        <button
          v-for="filter in deadlineFilters"
          :key="filter.key"
          type="button"
          class="workbench-todo__filter"
          :class="{ 'workbench-todo__filter--active': activeDeadlineFilter === filter.key }"
          @click="handleSelectDeadlineFilter(filter.key)"
        >
          {{ filter.label }}
        </button>
      </div>

      <ElDropdown trigger="click" placement="bottom-end" @command="handleSelectSort">
        <span class="workbench-todo__sort">
          排序：{{ currentSortLabel }}
          <SvgIcon icon="mdi:chevron-down" class="workbench-todo__sort-icon" />
        </span>
        <template #dropdown>
          <ElDropdownMenu>
            <ElDropdownItem
              v-for="option in sortOptions"
              :key="option.key"
              :command="option.key"
              :class="{ 'is-active': activeSort === option.key }"
            >
              {{ option.label }}
            </ElDropdownItem>
          </ElDropdownMenu>
        </template>
      </ElDropdown>
    </div>

    <div class="workbench-todo__content">
      <div v-if="pagedItems.length" class="workbench-todo__list">
        <article
          v-for="item in pagedItems"
          :key="item.id"
          class="workbench-todo__item"
          :class="{ 'workbench-todo__item--clickable': Boolean(item.routeKey) }"
          @click="handleClickItem(item)"
        >
          <div class="workbench-todo__leading">
            <span class="workbench-todo__category" :class="`workbench-todo__category--${item.categoryTone}`">
              {{ item.categoryLabel }}
            </span>
            <span v-if="item.priority === 'high'" class="workbench-todo__priority">高</span>
          </div>

          <div class="workbench-todo__body">
            <h4 class="workbench-todo__item-title">{{ item.title }}</h4>
            <div class="workbench-todo__meta">
              <span class="workbench-todo__source">{{ item.source }}</span>
            </div>
          </div>

          <div class="workbench-todo__trailing">
            <span class="workbench-todo__deadline" :class="getDeadlineToneClass(item)">
              {{ item.deadlineLabel }}
            </span>
          </div>
        </article>
      </div>
      <ElEmpty v-else description="当前筛选下暂无待办" :image-size="72" />
    </div>

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

    <PersonalItemOperateDialog
      v-model:visible="addDialogVisible"
      operate-type="add"
      :row-data="null"
      @submitted="handleAddSubmitted"
    />
  </WorkbenchModuleCard>
</template>

<style scoped>
.workbench-todo__tabs {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.workbench-todo__tabs-group {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.workbench-todo__add {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 12px;
  border: 1px solid rgb(14 116 144 / 60%);
  border-radius: 999px;
  background-color: rgb(240 253 250 / 80%);
  color: rgb(14 116 144 / 96%);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: all 160ms ease;
}

.workbench-todo__add:hover {
  background-color: rgb(14 116 144 / 96%);
  border-color: rgb(14 116 144 / 96%);
  color: white;
}

.workbench-todo__add-icon {
  font-size: 14px;
}

.workbench-todo__tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid rgb(226 232 240 / 92%);
  border-radius: 999px;
  background-color: rgb(255 255 255 / 96%);
  color: rgb(71 85 105 / 94%);
  font-size: 13px;
  cursor: pointer;
  transition: all 160ms ease;
}

.workbench-todo__tab:hover {
  border-color: rgb(14 116 144 / 64%);
  color: rgb(14 116 144 / 96%);
}

.workbench-todo__tab--active {
  border-color: rgb(14 116 144 / 92%);
  background-color: rgb(14 116 144 / 96%);
  color: white;
}

.workbench-todo__tab--active:hover {
  color: white;
}

.workbench-todo__tab-count {
  padding: 1px 6px;
  border-radius: 999px;
  background-color: rgb(241 245 249 / 96%);
  color: rgb(71 85 105 / 94%);
  font-size: 11px;
  font-weight: 600;
}

.workbench-todo__tab--active .workbench-todo__tab-count {
  background-color: rgb(255 255 255 / 22%);
  color: white;
}

.workbench-todo__tab-dot {
  position: absolute;
  top: 4px;
  right: 6px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: rgb(225 29 72 / 96%);
  box-shadow: 0 0 0 2px rgb(255 255 255 / 96%);
}

.workbench-todo__tab--active .workbench-todo__tab-dot {
  box-shadow: 0 0 0 2px rgb(14 116 144 / 96%);
}

.workbench-todo__filters {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}

.workbench-todo__filters-left {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.workbench-todo__sort {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px 8px;
  border-radius: 6px;
  color: rgb(100 116 139 / 92%);
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
  transition: all 160ms ease;
}

.workbench-todo__sort:hover {
  background-color: rgb(241 245 249 / 96%);
  color: rgb(14 116 144 / 96%);
}

.workbench-todo__sort-icon {
  font-size: 14px;
}

:deep(.el-dropdown-menu__item.is-active) {
  color: var(--el-color-primary);
  font-weight: 600;
}

.workbench-todo__filter {
  padding: 3px 10px;
  border: 1px dashed rgb(203 213 225 / 92%);
  border-radius: 999px;
  background-color: transparent;
  color: rgb(100 116 139 / 92%);
  font-size: 12px;
  cursor: pointer;
  transition: all 160ms ease;
}

.workbench-todo__filter:hover {
  border-style: solid;
  border-color: rgb(14 116 144 / 60%);
  color: rgb(14 116 144 / 96%);
}

.workbench-todo__filter--active {
  border-style: solid;
  border-color: rgb(190 18 60 / 80%);
  background-color: rgb(255 228 230 / 96%);
  color: rgb(190 18 60 / 96%);
}

.workbench-todo__filter--active:hover {
  border-color: rgb(190 18 60 / 92%);
  color: rgb(190 18 60 / 96%);
}

.workbench-todo__content {
  min-height: 400px;
  display: flex;
  flex-direction: column;
}

.workbench-todo__content :deep(.el-empty) {
  margin: auto;
}

.workbench-todo__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.workbench-todo__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid rgb(226 232 240 / 90%);
  border-radius: 16px;
  background-color: rgb(255 255 255 / 98%);
  transition:
    border-color 160ms ease,
    background-color 160ms ease;
}

.workbench-todo__item--clickable {
  cursor: pointer;
}

.workbench-todo__item--clickable:hover {
  border-color: rgb(14 116 144 / 60%);
  background-color: rgb(240 253 250 / 84%);
}

.workbench-todo__leading {
  display: flex;
  align-items: center;
  gap: 8px;
}

.workbench-todo__category {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}

.workbench-todo__category--sky {
  background-color: rgb(224 242 254 / 96%);
  color: rgb(14 116 144 / 96%);
}

.workbench-todo__category--emerald {
  background-color: rgb(220 252 231 / 96%);
  color: rgb(5 150 105 / 96%);
}

.workbench-todo__category--amber {
  background-color: rgb(254 243 199 / 96%);
  color: rgb(180 83 9 / 96%);
}

.workbench-todo__category--rose {
  background-color: rgb(255 228 230 / 96%);
  color: rgb(190 18 60 / 96%);
}

.workbench-todo__category--violet {
  background-color: rgb(237 233 254 / 96%);
  color: rgb(109 40 217 / 96%);
}

.workbench-todo__priority {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  background-color: rgb(254 226 226 / 96%);
  color: rgb(220 38 38 / 96%);
  font-size: 11px;
  font-weight: 800;
}

.workbench-todo__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.workbench-todo__item-title {
  margin: 0;
  color: rgb(15 23 42 / 98%);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.workbench-todo__meta {
  display: flex;
  align-items: center;
  gap: 8px;
}

.workbench-todo__source {
  color: rgb(100 116 139 / 92%);
  font-size: 12px;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.workbench-todo__trailing {
  display: flex;
  align-items: center;
}

.workbench-todo__deadline {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.workbench-todo__deadline--slate {
  background-color: rgb(241 245 249 / 96%);
  color: rgb(71 85 105 / 94%);
}

.workbench-todo__deadline--amber {
  background-color: rgb(254 243 199 / 96%);
  color: rgb(180 83 9 / 96%);
}

.workbench-todo__deadline--rose {
  background-color: rgb(255 228 230 / 96%);
  color: rgb(190 18 60 / 96%);
}

.workbench-todo__pager {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  min-height: 32px;
  margin-top: 12px;
}

@media (width <= 600px) {
  .workbench-todo__item {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .workbench-todo__trailing {
    grid-column: 1 / -1;
    justify-content: flex-end;
  }
}
</style>
