import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router, RouterModule } from '@angular/router';
import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
import { ProjectService } from '../../../services/project.service';

// 项目阶段定义
interface ProjectStage {
  id: string;
  name: string;
  order: number;
}

interface ProjectPhase {
  name: string;
  percentage: number;
  startPercentage: number;
  isCompleted: boolean;
  isCurrent: boolean;
}

interface Project {
  id: string;
  name: string;
  type: 'soft' | 'hard';
  memberType: 'vip' | 'normal';
  designerName: string;
  status: string;
  expectedEndDate: Date; // TODO: 兼容旧字段，后续可移除
  deadline: Date; // 真实截止时间字段
  createdAt?: Date; // 真实开始时间字段（可选）
  isOverdue: boolean;
  overdueDays: number;
  dueSoon: boolean;
  urgency: 'high' | 'medium' | 'low';
  phases: ProjectPhase[];
  currentStage: string; // 新增：当前项目阶段
  // 新增：质量评级
  qualityRating?: 'excellent' | 'qualified' | 'unqualified' | 'pending';
  lastCustomerFeedback?: string;
// 预构建的搜索索引，减少重复 toLowerCase 与拼接
  searchIndex?: string;
}

interface TodoTask {
  id: string;
  title: string;
  description: string;
  deadline: Date;
  priority: 'high' | 'medium' | 'low';
  type: 'review' | 'assign' | 'performance';
  targetId: string;
}

declare const echarts: any;
@Component({
  selector: 'app-dashboard',
  imports: [CommonModule, FormsModule, RouterModule],
  templateUrl: './dashboard.html',
  styleUrl: './dashboard.scss'
})

export class Dashboard implements OnInit, OnDestroy {
  projects: Project[] = [];
  filteredProjects: Project[] = [];
  todoTasks: TodoTask[] = [];
  overdueProjects: Project[] = [];
  urgentPinnedProjects: Project[] = [];
  showAlert: boolean = false;
  selectedProjectId: string = '';
  // 新增：关键词搜索
  searchTerm: string = '';
  searchSuggestions: Project[] = [];
  showSuggestions: boolean = false;
  private hideSuggestionsTimer: any;
  
  // 搜索性能与交互控制
  private searchDebounceTimer: any;
  private readonly SEARCH_DEBOUNCE_MS = 200; // 防抖时长（毫秒）
  private readonly MIN_SEARCH_LEN = 2; // 最小触发建议长度
  private readonly MAX_SUGGESTIONS = 8; // 建议最大条数
  private isSearchFocused: boolean = false; // 是否处于输入聚焦态
  // 新增：临期项目与筛选状态
  dueSoonProjects: Project[] = [];
  selectedType: 'all' | 'soft' | 'hard' = 'all';
  selectedUrgency: 'all' | 'high' | 'medium' | 'low' = 'all';
  selectedStatus: 'all' | 'progress' | 'completed' | 'overdue' | 'pendingApproval' | 'pendingAssignment' | 'dueSoon' = 'all';
  selectedDesigner: string = 'all';
  selectedMemberType: 'all' | 'vip' | 'normal' = 'all';
  // 新增：时间窗筛选
  selectedTimeWindow: 'all' | 'today' | 'threeDays' | 'sevenDays' = 'all';
  designers: string[] = [];
  // 新增：四大板块筛选
  selectedCorePhase: 'all' | 'order' | 'requirements' | 'delivery' | 'aftercare' = 'all';
  
  // 设计师画像（用于智能推荐）
  designerProfiles: any[] = [
    { id: 'zhang', name: '张三', skills: ['现代风格', '北欧风格'], workload: 70, avgRating: 4.5, experience: 3 },
    { id: 'li', name: '李四', skills: ['新中式', '宋式风格'], workload: 45, avgRating: 4.8, experience: 5 },
    { id: 'wang', name: '王五', skills: ['北欧风格', '日式风格'], workload: 85, avgRating: 4.2, experience: 2 },
    { id: 'zhao', name: '赵六', skills: ['现代风格', '轻奢风格'], workload: 30, avgRating: 4.6, experience: 4 }
  ];

  // 10个项目阶段
  projectStages: ProjectStage[] = [
    { id: 'pendingApproval', name: '待确认', order: 1 },
    { id: 'pendingAssignment', name: '待分配', order: 2 },
    { id: 'requirement', name: '需求沟通', order: 3 },
    { id: 'planning', name: '方案规划', order: 4 },
    { id: 'modeling', name: '建模阶段', order: 5 },
    { id: 'rendering', name: '渲染阶段', order: 6 },
    { id: 'postProduction', name: '后期处理', order: 7 },
    { id: 'review', name: '方案评审', order: 8 },
    { id: 'revision', name: '方案修改', order: 9 },
    { id: 'delivery', name: '交付完成', order: 10 }
  ];

  // 5大核心阶段（聚合展示）
  corePhases: ProjectStage[] = [
    { id: 'order', name: '订单创建', order: 1 },        // 待确认、待分配
    { id: 'requirements', name: '确认需求', order: 2 },  // 需求沟通、方案规划
    { id: 'delivery', name: '交付执行', order: 3 },      // 建模、渲染、后期/评审/修改
    { id: 'aftercare', name: '售后', order: 4 }          // 交付完成 → 售后
  ];
  // 甘特视图开关与实例引用
  showGanttView: boolean = false;
  private ganttChart: any | null = null;
  @ViewChild('ganttChartRef', { static: false }) ganttChartRef!: ElementRef<HTMLDivElement>;
  // 新增：工作量概览图表引用与实例
  @ViewChild('workloadChartRef', { static: false }) workloadChartRef!: ElementRef<HTMLDivElement>;
  private workloadChart: any | null = null;
  workloadDimension: 'designer' | 'member' = 'designer';
  // 甘特时间尺度：仅周/月
  ganttScale: 'week' | 'month' = 'week';
  // 新增：甘特模式（项目 / 设计师排班）
  ganttMode: 'project' | 'designer' = 'project';
  constructor(private projectService: ProjectService, private router: Router) {}

  ngOnInit(): void {
    this.loadProjects();
    this.loadTodoTasks();
    // 首次微任务后尝试初始化一次，确保容器已渲染
    setTimeout(() => this.updateWorkloadChart(), 0);
  }

  loadProjects(): void {
    // 模拟数据加载 - 增强数据结构，添加currentStage
    this.projects = [
      {
        id: 'proj-001',
        name: '现代风格客厅设计',
        type: 'soft',
        memberType: 'vip',
        designerName: '张三',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 15),
        deadline: new Date(2023, 9, 15),
        isOverdue: true,
        overdueDays: 2,
        dueSoon: false,
        urgency: 'high',
        currentStage: 'rendering',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: true, isCurrent: false },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: false, isCurrent: true },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: false },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      {
        id: 'proj-002',
        name: '北欧风格卧室设计',
        type: 'soft',
        memberType: 'normal',
        designerName: '李四',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 20),
        deadline: new Date(2023, 9, 20),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'medium',
        currentStage: 'postProduction',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: true, isCurrent: false },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: true, isCurrent: false },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: true },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      {
        id: 'proj-003',
        name: '新中式餐厅设计',
        type: 'hard',
        memberType: 'normal',
        designerName: '王五',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 25),
        deadline: new Date(2023, 9, 25),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'low',
        currentStage: 'modeling',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: false, isCurrent: true },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: false, isCurrent: false },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: false },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      {
        id: 'proj-004',
        name: '工业风办公室设计',
        type: 'hard',
        memberType: 'normal',
        designerName: '赵六',
        status: '进行中',
        expectedEndDate: new Date(2023, 9, 10),
        deadline: new Date(2023, 9, 10),
        isOverdue: true,
        overdueDays: 7,
        dueSoon: false,
        urgency: 'high',
        currentStage: 'review',
        phases: [
          { name: '建模', percentage: 15, startPercentage: 0, isCompleted: true, isCurrent: false },
          { name: '渲染', percentage: 20, startPercentage: 15, isCompleted: true, isCurrent: false },
          { name: '后期', percentage: 15, startPercentage: 35, isCompleted: false, isCurrent: false },
          { name: '交付', percentage: 50, startPercentage: 50, isCompleted: false, isCurrent: false }
        ]
      },
      // 添加更多不同阶段的项目
      {
        id: 'proj-005',
        name: '现代简约厨房设计',
        type: 'soft',
        memberType: 'normal',
        designerName: '',
        status: '待分配',
        expectedEndDate: new Date(2023, 10, 5),
        deadline: new Date(2023, 10, 5),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'medium',
        currentStage: 'pendingAssignment',
        phases: []
      },
      {
        id: 'proj-006',
        name: '日式风格书房设计',
        type: 'hard',
        memberType: 'normal',
        designerName: '',
        status: '待确认',
        expectedEndDate: new Date(2023, 10, 10),
        deadline: new Date(2023, 10, 10),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'low',
        currentStage: 'pendingApproval',
        phases: []
      },
      {
        id: 'proj-007',
        name: '轻奢风格浴室设计',
        type: 'soft',
        memberType: 'normal',
        designerName: '钱七',
        status: '已完成',
        expectedEndDate: new Date(2023, 9, 5),
        deadline: new Date(2023, 9, 5),
        isOverdue: false,
        overdueDays: 0,
        dueSoon: false,
        urgency: 'medium',
        currentStage: 'delivery',
        phases: []
      }
    ];

    // ===== 追加生成示例数据：保证总量达到100条 =====
    const stageIds = this.projectStages.map(s => s.id);
    const designers = ['张三','李四','王五','赵六','钱七','孙八','周九','吴十','郑一','冯二','陈三','褚四'];
    const statusMap: Record<string, string> = {
      pendingApproval: '待确认',
      pendingAssignment: '待分配',
      requirement: '进行中',
      planning: '进行中',
      modeling: '进行中',
      rendering: '进行中',
      postProduction: '进行中',
      review: '进行中',
      revision: '进行中',
      delivery: '已完成'
    };

    for (let i = 8; i <= 100; i++) {
      const stageIndex = (i - 1) % stageIds.length;
      const currentStage = stageIds[stageIndex];
      const type: 'soft' | 'hard' = i % 2 === 0 ? 'soft' : 'hard';
      const urgency: 'high' | 'medium' | 'low' = i % 5 === 0 ? 'high' : (i % 3 === 0 ? 'medium' : 'low');
      const isOverdue = ['planning','modeling','rendering','postProduction','review','revision','delivery'].includes(currentStage) ? i % 7 === 0 : false;
      const overdueDays = isOverdue ? (i % 10) + 1 : 0;
      const hasDesigner = !['pendingApproval', 'pendingAssignment'].includes(currentStage);
      const designerName = hasDesigner ? designers[i % designers.length] : '';
      const status = statusMap[currentStage] || '进行中';
      const expectedEndDate = new Date();
      const daysOffset = isOverdue ? - (overdueDays + (i % 5)) : ((i % 20) + 3);
      expectedEndDate.setDate(expectedEndDate.getDate() + daysOffset);
      const daysToDeadline = Math.ceil((expectedEndDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
      const dueSoon = !isOverdue && daysToDeadline >= 0 && daysToDeadline <= 3;
      const memberType: 'vip' | 'normal' = i % 4 === 0 ? 'vip' : 'normal';

      this.projects.push({
        id: `proj-${String(i).padStart(3, '0')}`,
        name: `${type === 'soft' ? '软装' : '硬装'}示例项目 ${i}`,
        type,
        memberType,
        designerName,
        status,
        expectedEndDate,
        deadline: expectedEndDate,
        isOverdue,
        overdueDays,
        dueSoon,
        urgency,
        currentStage,
        phases: []
      });
    }
    // ===== 示例数据生成结束 =====

    // 统一补齐真实时间字段（deadline/createdAt），以真实字段贯通筛选与甘特
    const DAY = 24 * 60 * 60 * 1000;
    this.projects = this.projects.map(p => {
      const deadline = p.deadline || p.expectedEndDate;
      const baseDays = p.type === 'hard' ? 30 : 14;
      const createdAt = p.createdAt || new Date(new Date(deadline).getTime() - baseDays * DAY);
      return { ...p, deadline, createdAt } as Project;
    });

    // 筛选超期与临期项目
    this.overdueProjects = this.projects.filter(project => project.isOverdue);
    this.dueSoonProjects = this.projects.filter(project => project.dueSoon && !project.isOverdue);
    this.filteredProjects = [...this.projects];

    // 供筛选用的设计师列表
    this.designers = Array.from(new Set(this.projects.map(p => p.designerName).filter(n => !!n)));

    // 显示超期提醒
    if (this.overdueProjects.length > 0) {
      this.showAlert = true;
    }
  }

  loadTodoTasks(): void {
    // 模拟待办任务数据
    this.todoTasks = [
      {
        id: 'todo-001',
        title: '待评审效果图',
        description: '现代风格客厅设计项目需要进行效果图评审',
        deadline: new Date(2023, 9, 18, 15, 0),
        priority: 'high',
        type: 'review',
        targetId: 'proj-001'
      },
      {
        id: 'todo-002',
        title: '待分配项目',
        description: '新中式厨房设计项目需要分配给合适的设计师',
        deadline: new Date(2023, 9, 19, 10, 0),
        priority: 'high',
        type: 'assign',
        targetId: 'proj-new'
      },
      {
        id: 'todo-003',
        title: '待确认绩效',
        description: '9月份团队绩效需要进行审核确认',
        deadline: new Date(2023, 9, 22, 18, 0),
        priority: 'medium',
        type: 'performance',
        targetId: 'sep-2023'
      },
      {
        id: 'todo-004',
        title: '待处理客户反馈',
        description: '北欧风格卧室设计项目有客户反馈需要处理',
        deadline: new Date(2023, 9, 20, 14, 0),
        priority: 'medium',
        type: 'review',
        targetId: 'proj-002'
      },
      {
        id: 'todo-005',
        title: '团队会议',
        description: '每周团队进度沟通会议',
        deadline: new Date(2023, 9, 18, 10, 0),
        priority: 'low',
        type: 'performance',
        targetId: 'weekly-meeting'
      }
    ];

    // 按优先级排序：紧急且重要 > 重要不紧急 > 紧急不重要
    this.todoTasks.sort((a, b) => {
      const priorityOrder = {
        'high': 3,
        'medium': 2,
        'low': 1
      };
      return priorityOrder[b.priority] - priorityOrder[a.priority];
    });
  }

  // 筛选项目类型
  filterProjects(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedType = (target && target.value ? target.value : 'all') as any;
    this.applyFilters();
  }

  // 筛选紧急程度
  filterByUrgency(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedUrgency = (target && target.value ? target.value : 'all') as any;
    this.applyFilters();
  }

  // 筛选项目状态
  filterByStatus(status: string): void {
    // 点击同一状态时，切换回“全部”，以便恢复全量项目列表
    const next = (this.selectedStatus === status) ? 'all' : (status && status.length ? status : 'all');
    this.selectedStatus = next as any;
    this.applyFilters();
  }
  
  // 处理状态筛选下拉框变化
  onStatusChange(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedStatus = (target && target.value ? target.value : 'all') as any;
    this.applyFilters();
  }

  // 新增：设计师筛选下拉事件处理
  onDesignerChange(event: Event): void {
    const target = event.target as HTMLSelectElement;
    this.selectedDesigner = (target && target.value ? target.value : 'all');
    this.applyFilters();
  }

  // 新增：会员类型筛选下拉事件处理
  onMemberTypeChange(event: Event): void {
    const select = event.target as HTMLSelectElement;
    this.selectedMemberType = select.value as any;
    this.applyFilters();
  }

  // 新增：四大板块改变
  onCorePhaseChange(event: Event): void {
    const select = event.target as HTMLSelectElement;
    this.selectedCorePhase = select.value as any;
    this.applyFilters();
  }

  // 时间窗快捷筛选（供UI按钮触发）
  filterByTimeWindow(timeWindow: 'all' | 'today' | 'threeDays' | 'sevenDays'): void {
    this.selectedTimeWindow = timeWindow;
    this.applyFilters();
  }

  // 新增：搜索输入变化
  onSearchChange(): void {
    if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer);
    this.searchDebounceTimer = setTimeout(() => {
      this.updateSearchSuggestions();
      this.applyFilters();
    }, this.SEARCH_DEBOUNCE_MS);
  }

  // 新增：搜索框聚焦/失焦控制建议显隐
  onSearchFocus(): void {
    if (this.hideSuggestionsTimer) clearTimeout(this.hideSuggestionsTimer);
    this.isSearchFocused = true;
    this.updateSearchSuggestions();
  }
  onSearchBlur(): void {
    // 延迟隐藏以允许选择项的 mousedown 触发
    this.isSearchFocused = false;
    this.hideSuggestionsTimer = setTimeout(() => {
      this.showSuggestions = false;
    }, 150);
  }

  // 新增：更新搜索建议（不叠加其它筛选，仅基于关键字）
  private updateSearchSuggestions(): void {
    const q = (this.searchTerm || '').trim().toLowerCase();
    if (q.length < this.MIN_SEARCH_LEN) {
      this.searchSuggestions = [];
      this.showSuggestions = false;
      return;
    }

    const scored = this.projects
      .filter(p => (p.searchIndex || `${(p.name || '')}|${(p.designerName || '')}`.toLowerCase()).includes(q))
      .map(p => {
        const dl = p.deadline || p.expectedEndDate;
        const dlTime = dl ? new Date(dl).getTime() : NaN;
        const daysToDl = Math.ceil(((isNaN(dlTime) ? 0 : dlTime) - Date.now()) / (1000 * 60 * 60 * 24));
        const urgencyScore = p.urgency === 'high' ? 3 : p.urgency === 'medium' ? 2 : 1;
        const overdueScore = p.isOverdue ? 10 : 0;
        const score = overdueScore + (4 - urgencyScore) * 2 - (isNaN(daysToDl) ? 0 : daysToDl);
        return { p, score };
      })
      .sort((a, b) => b.score - a.score)
      .slice(0, this.MAX_SUGGESTIONS)
      .map(x => x.p);

    this.searchSuggestions = scored;
    this.showSuggestions = this.isSearchFocused && this.searchSuggestions.length > 0;
  }

  // 新增：选择建议项
  selectSuggestion(project: Project): void {
    this.searchTerm = project.name;
    this.showSuggestions = false;
    this.viewProjectDetails(project.id);
  }

  // 统一筛选
  private applyFilters(): void {
    let result = [...this.projects];

    // 新增：关键词搜索（项目名 / 设计师名 / 含风格关键词的项目名）
    const q = (this.searchTerm || '').trim().toLowerCase();
    if (q) {
      result = result.filter(p => (p.searchIndex || `${(p.name || '')}|${(p.designerName || '')}`.toLowerCase()).includes(q));
    }

    // 类型筛选
    if (this.selectedType !== 'all') {
      result = result.filter(p => p.type === this.selectedType);
    }

    // 紧急程度筛选
    if (this.selectedUrgency !== 'all') {
      result = result.filter(p => p.urgency === this.selectedUrgency);
    }

    // 项目状态筛选
    if (this.selectedStatus !== 'all') {
      if (this.selectedStatus === 'overdue') {
        result = result.filter(p => p.isOverdue);
      } else if (this.selectedStatus === 'dueSoon') {
        result = result.filter(p => p.dueSoon && !p.isOverdue);
      } else if (this.selectedStatus === 'pendingApproval') {
        result = result.filter(p => p.currentStage === 'pendingApproval');
      } else if (this.selectedStatus === 'pendingAssignment') {
        result = result.filter(p => p.currentStage === 'pendingAssignment');
      } else if (this.selectedStatus === 'progress') {
        const progressStages = ['requirement','planning','modeling','rendering','postProduction','review','revision'];
        result = result.filter(p => progressStages.includes(p.currentStage));
      } else if (this.selectedStatus === 'completed') {
        result = result.filter(p => p.currentStage === 'delivery');
      }
    }

    // 新增：四大板块筛选
    if (this.selectedCorePhase !== 'all') {
      result = result.filter(p => this.mapStageToCorePhase(p.currentStage) === this.selectedCorePhase);
    }

    // 设计师筛选
    if (this.selectedDesigner !== 'all') {
      result = result.filter(p => p.designerName === this.selectedDesigner);
    }

    // 会员类型筛选
    if (this.selectedMemberType !== 'all') {
      result = result.filter(p => p.memberType === this.selectedMemberType);
    }

    // 新增：时间窗筛选
    if (this.selectedTimeWindow !== 'all') {
      const now = new Date();
      const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
      
      result = result.filter(p => {
        const projectDeadline = new Date(p.deadline);
        const timeDiff = projectDeadline.getTime() - today.getTime();
        const daysDiff = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
        
        switch (this.selectedTimeWindow) {
          case 'today':
            return daysDiff <= 1 && daysDiff >= 0;
          case 'threeDays':
            return daysDiff <= 3 && daysDiff >= 0;
          case 'sevenDays':
            return daysDiff <= 7 && daysDiff >= 0;
          default:
            return true;
        }
      });
    }

    this.filteredProjects = result;
    // 新增：计算紧急任务固定区（超期 + 高紧急），与筛选联动
    this.urgentPinnedProjects = this.filteredProjects
      .filter(p => p.isOverdue && p.urgency === 'high')
      .sort((a, b) => (b.overdueDays - a.overdueDays) || a.name.localeCompare(b.name, 'zh-Hans-CN'));
    // 当显示甘特卡片时，同步刷新甘特图
    if (this.showGanttView) {
      this.updateGantt();
    }
    // 同步刷新工作量概览图
    this.updateWorkloadChart();
  }

  // 切换项目看板/负载日历（甘特）视图
  toggleView(): void {
    this.showGanttView = !this.showGanttView;
    if (this.showGanttView) {
      setTimeout(() => this.initOrUpdateGantt(), 0);
    } else {
      if (this.ganttChart) {
        this.ganttChart.dispose();
        this.ganttChart = null;
      }
      if (this.workloadChart) {
        this.workloadChart.dispose();
        this.workloadChart = null;
      }
    }
  }

  // 设置甘特时间尺度
  setGanttScale(scale: 'week' | 'month'): void {
    if (this.ganttScale !== scale) {
      this.ganttScale = scale;
      this.updateGantt();
    }
  }

  // 新增：切换甘特模式
  setGanttMode(mode: 'project' | 'designer'): void {
    if (this.ganttMode !== mode) {
      this.ganttMode = mode;
      this.updateGantt();
    }
  }

  private initOrUpdateGantt(): void {
    if (!this.ganttChartRef) return;
    const el = this.ganttChartRef.nativeElement;
    if (!this.ganttChart) {
      this.ganttChart = echarts.init(el);
      window.addEventListener('resize', () => {
        this.ganttChart && this.ganttChart.resize();
      });
    }
    this.updateGantt();
  }

  private updateGantt(): void {
    if (!this.ganttChart) return;
    if (this.ganttMode === 'designer') {
      this.updateGanttDesigner();
      return;
    }

    // 按紧急程度从上到下排序（高->中->低），同级按到期时间升序
    const urgencyRank: Record<'high'|'medium'|'low', number> = { high: 0, medium: 1, low: 2 };
    const projects = [...this.filteredProjects]
      .sort((a, b) => {
        const u = urgencyRank[a.urgency] - urgencyRank[b.urgency];
        if (u !== 0) return u;
        // 二级排序：临期优先（到期更近）> 已分配人员 > VIP客户 > 其他
        const endDiff = new Date(a.deadline).getTime() - new Date(b.deadline).getTime();
        if (endDiff !== 0) return endDiff;
        const assignedA = !!a.designerName;
        const assignedB = !!b.designerName;
        if (assignedA !== assignedB) return assignedA ? -1 : 1; // 已分配在前
        const vipA = a.memberType === 'vip';
        const vipB = b.memberType === 'vip';
        if (vipA !== vipB) return vipA ? -1 : 1; // VIP在前
        return a.name.localeCompare(b.name, 'zh-CN');
      });

    const categories = projects.map(p => p.name);
    const urgencyMap: Record<string, 'high'|'medium'|'low'> = Object.fromEntries(projects.map(p => [p.name, p.urgency])) as any;

    const colorByUrgency: Record<'high'|'medium'|'low', string> = {
      high: '#ef4444',
      medium: '#f59e0b',
      low: '#22c55e'
    } as const;

    const DAY = 24 * 60 * 60 * 1000;

    const data = projects.map((p, idx) => {
      const end = new Date(p.deadline).getTime();
      const baseDays = p.type === 'hard' ? 30 : 14;
      const start = p.createdAt ? new Date(p.createdAt).getTime() : end - baseDays * DAY;
      const color = colorByUrgency[p.urgency] || '#60a5fa';
      return {
        name: p.name,
        value: [idx, start, end, p.designerName, p.urgency, p.memberType, p.currentStage],
        itemStyle: { color }
      };
    });

    // 计算时间范围（仅周/月）
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const todayTs = today.getTime();

    let xMin: number;
    let xMax: number;
    let xSplitNumber: number;
    let xLabelFormatter: (value: number) => string;

    if (this.ganttScale === 'week') {
      const day = today.getDay(); // 0=周日
      const diffToMonday = (day === 0 ? 6 : day - 1);
      const startOfWeek = new Date(today.getTime() - diffToMonday * DAY);
      const endOfWeek = new Date(startOfWeek.getTime() + 7 * DAY - 1);
      xMin = startOfWeek.getTime();
      xMax = endOfWeek.getTime();
      xSplitNumber = 7;
      const WEEK_LABELS = ['周日','周一','周二','周三','周四','周五','周六'];
      xLabelFormatter = (val) => {
        const d = new Date(val);
        return WEEK_LABELS[d.getDay()];
      };
    } else { // month
      const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
      const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0, 23, 59, 59, 999);
      xMin = startOfMonth.getTime();
      xMax = endOfMonth.getTime();
      xSplitNumber = 4;
      xLabelFormatter = (val) => {
        const d = new Date(val);
        const weekOfMonth = Math.ceil(d.getDate() / 7);
        return `第${weekOfMonth}周`;
      };
    }

    // 计算默认可视区，并尝试保留上一次的滚动/缩放位置
    const total = categories.length;
    const visible = Math.min(total, 15); // 默认首屏展开15条
    const defaultEndPercent = total > 0 ? Math.min(100, (visible / total) * 100) : 100;
    const prevOpt: any = (this.ganttChart as any).getOption ? (this.ganttChart as any).getOption() : null;
    const preservedStart = typeof prevOpt?.dataZoom?.[0]?.start === 'number' ? prevOpt.dataZoom[0].start : 0;
    const preservedEnd = typeof prevOpt?.dataZoom?.[0]?.end === 'number' ? prevOpt.dataZoom[0].end : defaultEndPercent;

    const option = {
      backgroundColor: 'transparent',
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          const v = params.value;
          const start = new Date(v[1]);
          const end = new Date(v[2]);
          return `项目：${params.name}<br/>负责人：${v[3] || '未分配'}<br/>阶段：${v[6]}<br/>起止：${start.toLocaleDateString()} ~ ${end.toLocaleDateString()}`;
        }
      },
      grid: { left: 100, right: 64, top: 30, bottom: 30 },
      xAxis: {
        type: 'time',
        min: xMin,
        max: xMax,
        splitNumber: xSplitNumber,
        axisLine: { lineStyle: { color: '#e5e7eb' } },
        axisLabel: { color: '#6b7280', formatter: (value: number) => xLabelFormatter(value) },
        splitLine: { lineStyle: { color: '#f1f5f9' } }
      },
      yAxis: {
        type: 'category',
        data: categories,
        inverse: true,
        axisLabel: {
          color: '#374151',
          margin: 8,
          formatter: (val: string) => {
            const u = urgencyMap[val] || 'low';
            const text = val.length > 16 ? val.slice(0, 16) + '…' : val;
            return `{${u}Dot|●} ${text}`;
          },
          rich: {
            highDot: { color: '#ef4444' },
            mediumDot: { color: '#f59e0b' },
            lowDot: { color: '#22c55e' }
          }
        },
        axisTick: { show: false },
        axisLine: { lineStyle: { color: '#e5e7eb' } }
      },
      dataZoom: [
        { type: 'slider', yAxisIndex: 0, orient: 'vertical', right: 6, width: 14, start: preservedStart, end: preservedEnd, zoomLock: false },
        { type: 'inside', yAxisIndex: 0, zoomOnMouseWheel: true, moveOnMouseMove: true, moveOnMouseWheel: true }
      ],
      series: [
        {
          type: 'custom',
          renderItem: (params: any, api: any) => {
            const categoryIndex = api.value(0);
            const start = api.coord([api.value(1), categoryIndex]);
            const end = api.coord([api.value(2), categoryIndex]);
            const height = Math.max(api.size([0, 1])[1] * 0.5, 8);
            const rectShape = echarts.graphic.clipRectByRect({
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height
            }, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            });
            return rectShape ? { type: 'rect', shape: rectShape, style: api.style() } : undefined;
          },
          encode: { x: [1, 2], y: 0 },
          data,
          itemStyle: { borderRadius: 4 },
          emphasis: { focus: 'self' },
          markLine: {
            silent: true,
            symbol: 'none',
            lineStyle: { color: '#ef4444', type: 'dashed', width: 1 },
            label: { formatter: '今日', color: '#ef4444', fontSize: 10, position: 'end' },
            data: [ { xAxis: todayTs } ]
          }
        }
      ]
    };

    // 强制刷新，避免缓存导致坐标轴不更新
    this.ganttChart.clear();
    this.ganttChart.setOption(option, true);
    this.ganttChart.resize();
  }

  // 新增：设计师排班甘特
  private updateGanttDesigner(): void {
    if (!this.ganttChart) return;

    const DAY = 24 * 60 * 60 * 1000;
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const todayTs = today.getTime();

    // 时间轴按当前周/月
    let xMin: number;
    let xMax: number;
    let xSplitNumber: number;
    let xLabelFormatter: (value: number) => string;
    if (this.ganttScale === 'week') {
      const day = today.getDay();
      const diffToMonday = (day === 0 ? 6 : day - 1);
      const startOfWeek = new Date(today.getTime() - diffToMonday * DAY);
      const endOfWeek = new Date(startOfWeek.getTime() + 7 * DAY - 1);
      xMin = startOfWeek.getTime();
      xMax = endOfWeek.getTime();
      xSplitNumber = 7;
      const WEEK_LABELS = ['周日','周一','周二','周三','周四','周五','周六'];
      xLabelFormatter = (val) => WEEK_LABELS[new Date(val).getDay()];
    } else {
      const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
      const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0, 23, 59, 59, 999);
      xMin = startOfMonth.getTime();
      xMax = endOfMonth.getTime();
      xSplitNumber = 4;
      xLabelFormatter = (val) => `第${Math.ceil(new Date(val).getDate() / 7)}周`;
    }

    // 仅统计已分配项目
    const assigned = this.filteredProjects.filter(p => !!p.designerName);
    const designers = Array.from(new Set(assigned.map(p => p.designerName)));

    const byDesigner: Record<string, typeof assigned> = {} as any;
    designers.forEach(n => byDesigner[n] = [] as any);
    assigned.forEach(p => byDesigner[p.designerName].push(p));

    const busyCountMap: Record<string, number> = Object.fromEntries(designers.map(n => [n, byDesigner[n].length]));

    const sortedDesigners = designers.sort((a, b) => {
      const diff = (busyCountMap[b] || 0) - (busyCountMap[a] || 0);
      return diff !== 0 ? diff : a.localeCompare(b, 'zh-CN');
    });

    const categories = sortedDesigners;

    // 工作量等级（用于左侧小圆点颜色）
    const workloadLevelMap: Record<string, 'high'|'medium'|'low'> = {} as any;
    categories.forEach(name => {
      const cnt = busyCountMap[name] || 0;
      workloadLevelMap[name] = cnt >= 5 ? 'high' : (cnt >= 3 ? 'medium' : 'low');
    });

    // 条形颜色仍按项目紧急度
    const colorByUrgency: Record<'high'|'medium'|'low', string> = {
      high: '#ef4444',
      medium: '#f59e0b',
      low: '#22c55e'
    } as const;

    const data = assigned.flatMap(p => {
      const end = new Date(p.deadline).getTime();
      const baseDays = p.type === 'hard' ? 30 : 14;
      const start = p.createdAt ? new Date(p.createdAt).getTime() : end - baseDays * DAY;
      const yIndex = categories.indexOf(p.designerName);
      if (yIndex === -1) return [] as any[];
      const color = colorByUrgency[p.urgency] || '#60a5fa';
      return [{
        name: p.name,
        value: [yIndex, start, end, p.designerName, p.urgency, p.memberType, p.currentStage],
        itemStyle: { color }
      }];
    });

    const prevOpt: any = (this.ganttChart as any).getOption ? (this.ganttChart as any).getOption() : null;
    const total = categories.length || 1;
    const visible = Math.min(total, 30);
    const defaultEndPercent = Math.min(100, (visible / total) * 100);
    const preservedStart = typeof prevOpt?.dataZoom?.[0]?.start === 'number' ? prevOpt.dataZoom[0].start : 0;
    const preservedEnd = typeof prevOpt?.dataZoom?.[0]?.end === 'number' ? prevOpt.dataZoom[0].end : defaultEndPercent;

    const option = {
      backgroundColor: 'transparent',
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          const v = params.value;
          const start = new Date(v[1]);
          const end = new Date(v[2]);
          return `项目：${params.name}<br/>设计师：${v[3]}<br/>阶段：${v[6]}<br/>起止：${start.toLocaleDateString()} ~ ${end.toLocaleDateString()}`;
        }
      },
      grid: { left: 110, right: 64, top: 30, bottom: 30 },
      xAxis: {
        type: 'time',
        min: xMin,
        max: xMax,
        splitNumber: xSplitNumber,
        axisLine: { lineStyle: { color: '#e5e7eb' } },
        axisLabel: { color: '#6b7280', formatter: (value: number) => xLabelFormatter(value) },
        splitLine: { lineStyle: { color: '#f1f5f9' } }
      },
      yAxis: {
        type: 'category',
        data: categories,
        inverse: true,
        axisLabel: {
          color: '#374151',
          margin: 8,
          formatter: (val: string) => {
            const lvl = workloadLevelMap[val] || 'low';
            const count = busyCountMap[val] || 0;
            const text = val.length > 8 ? val.slice(0, 8) + '…' : val;
            return `{${lvl}Dot|●} ${text}（${count}项）`;
          },
          rich: {
            highDot: { color: '#ef4444' },
            mediumDot: { color: '#f59e0b' },
            lowDot: { color: '#22c55e' }
          }
        },
        axisTick: { show: false },
        axisLine: { lineStyle: { color: '#e5e7eb' } }
      },
      dataZoom: [
        { type: 'slider', yAxisIndex: 0, orient: 'vertical', right: 6, start: preservedStart, end: preservedEnd, zoomLock: false },
        { type: 'inside', yAxisIndex: 0, zoomOnMouseWheel: true, moveOnMouseMove: true, moveOnMouseWheel: true }
      ],
      series: [
        {
          type: 'custom',
          renderItem: (params: any, api: any) => {
            const categoryIndex = api.value(0);
            const start = api.coord([api.value(1), categoryIndex]);
            const end = api.coord([api.value(2), categoryIndex]);
            const height = Math.max(api.size([0, 1])[1] * 0.5, 8);
            const rectShape = echarts.graphic.clipRectByRect({
              x: start[0],
              y: start[1] - height / 2,
              width: Math.max(end[0] - start[0], 2),
              height
            }, {
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height
            });
            return rectShape ? { type: 'rect', shape: rectShape, style: api.style() } : undefined;
          },
          encode: { x: [1, 2], y: 0 },
          data,
          itemStyle: { borderRadius: 4 },
          emphasis: { focus: 'self' },
          markLine: {
            silent: true,
            symbol: 'none',
            lineStyle: { color: '#ef4444', type: 'dashed', width: 1 },
            label: { formatter: '今日', color: '#ef4444', fontSize: 10, position: 'end' },
            data: [ { xAxis: todayTs } ]
          }
        }
      ]
    } as any;

    this.ganttChart.clear();
    this.ganttChart.setOption(option, true);
    this.ganttChart.resize();
  }

  ngOnDestroy(): void {
    if (this.ganttChart) {
      this.ganttChart.dispose();
      this.ganttChart = null;
    }
    if (this.workloadChart) {
      this.workloadChart.dispose();
      this.workloadChart = null;
    }
  }
  // 选择单个项目
  selectProject(): void {
    if (this.selectedProjectId) {
      this.router.navigate(['/team-leader/project-detail', this.selectedProjectId]);
    }
  }

  // 获取特定阶段的项目
  getProjectsByStage(stageId: string): Project[] {
    return this.filteredProjects.filter(project => project.currentStage === stageId);
  }

  // 新增：阶段到核心阶段的映射
  private mapStageToCorePhase(stageId: string): 'order' | 'requirements' | 'delivery' | 'aftercare' {
    // 订单创建：立项初期
    if (stageId === 'pendingApproval' || stageId === 'pendingAssignment') return 'order';
    // 确认需求：需求沟通 + 方案规划
    if (stageId === 'requirement' || stageId === 'planning') return 'requirements';
    // 交付执行：制作与评审修订过程
    if (stageId === 'modeling' || stageId === 'rendering' || stageId === 'postProduction' || stageId === 'review' || stageId === 'revision') return 'delivery';
    // 售后：交付完成后的跟进（当前数据以交付完成代表进入售后）
    return 'aftercare';
  }

  // 新增：获取核心阶段的项目
  getProjectsByCorePhase(coreId: string): Project[] {
    return this.filteredProjects.filter(p => this.mapStageToCorePhase(p.currentStage) === coreId);
  }

  // 新增：获取核心阶段的项目数量
  getProjectCountByCorePhase(coreId: string): number {
    return this.getProjectsByCorePhase(coreId).length;
  }

  // 获取特定阶段的项目数量
  getProjectCountByStage(stageId: string): number {
    return this.getProjectsByStage(stageId).length;
  }

  // 待审批项目：currentStage === 'pendingApproval'
  get pendingApprovalProjects(): Project[] {
    const src = (this.filteredProjects && this.filteredProjects.length) ? this.filteredProjects : this.projects;
    return src.filter(p => p.currentStage === 'pendingApproval');
  }

  // 待指派项目：currentStage === 'pendingAssignment'
  get pendingAssignmentProjects(): Project[] {
    const src = (this.filteredProjects && this.filteredProjects.length) ? this.filteredProjects : this.projects;
    return src.filter(p => p.currentStage === 'pendingAssignment');
  }

  // 获取紧急程度标签
  getUrgencyLabel(urgency: string): string {
    const labels = {
      high: '紧急',
      medium: '一般',
      low: '普通'
    };
    return labels[urgency as keyof typeof labels] || urgency;
  }

  // 智能推荐设计师
  private getRecommendedDesigner(projectType: 'soft' | 'hard') {
    if (!this.designerProfiles || !this.designerProfiles.length) return null;
    const scoreOf = (p: any) => {
      const workloadScore = 100 - (p.workload ?? 0); // 负载越低越好
      const ratingScore = (p.avgRating ?? 0) * 10;   // 评分越高越好
      const expScore = (p.experience ?? 0) * 5;      // 经验越高越好
      return workloadScore * 0.5 + ratingScore * 0.3 + expScore * 0.2;
    };
    const sorted = [...this.designerProfiles].sort((a, b) => scoreOf(b) - scoreOf(a));
    return sorted[0] || null;
  }

  // 质量评审
  reviewProjectQuality(projectId: string, rating: 'excellent' | 'qualified' | 'unqualified'): void {
    const project = this.projects.find(p => p.id === projectId);
    if (!project) return;
    project.qualityRating = rating;
    if (rating === 'unqualified') {
      // 不合格：回退到修改阶段
      project.currentStage = 'revision';
    }
    this.applyFilters();
    alert('质量评审已提交');
  }

  // 查看绩效预警（占位：跳转到团队管理）
  viewPerformanceDetails(): void {
    this.router.navigate(['/team-leader/team-management']);
  }

  // 打开负载日历（占位：跳转到团队管理）
  navigateToWorkloadCalendar(): void {
    this.router.navigate(['/team-leader/workload-calendar']);
  }

  // 查看项目详情
  viewProjectDetails(projectId: string): void {
    // 改为跳转到复用的项目详情（组长上下文，具备审核权限）
    this.router.navigate(['/team-leader/project-detail', projectId]);
  }

  // 快速分配项目（增强：加入智能推荐）
  quickAssignProject(projectId: string): void {
    const project = this.projects.find(p => p.id === projectId);
    if (!project) {
      alert('未找到对应项目');
      return;
    }

    const recommended = this.getRecommendedDesigner(project.type);
    if (recommended) {
      const reassigning = !!project.designerName;
      const message = `推荐设计师：${recommended.name}（工作负载：${recommended.workload}%，评分：${recommended.avgRating}分）` +
                (reassigning ? `\n\n该项目当前已由「${project.designerName}」负责，是否改为分配给「${recommended.name}」？` : '\n\n是否确认分配？');
      const confirmAssign = confirm(message);
      if (confirmAssign) {
        project.designerName = recommended.name;
        if (project.currentStage === 'pendingAssignment' || project.currentStage === 'pendingApproval') {
          project.currentStage = 'requirement';
        }
        project.status = '进行中';
        // 更新设计师筛选列表
        this.designers = Array.from(new Set(this.projects.map(p => p.designerName).filter(n => !!n)));
        this.applyFilters();
        alert(`项目已${reassigning ? '重新' : ''}分配给 ${recommended.name}`);
        return;
      }
    }
    // 无推荐或用户取消，跳转到详细分配页面
    // 改为跳转到复用详情（组长视图），通过 query 参数标记 assign 模式
    this.router.navigate(['/team-leader/project-detail', projectId], { queryParams: { mode: 'assign' } });
    }

  // 导航到待办任务
  navigateToTask(task: TodoTask): void {
    switch (task.type) {
      case 'review':
        this.router.navigate(['team-leader/quality-management', task.targetId]);
        break;
      case 'assign':
        this.router.navigate(['/team-leader/dashboard']);
        break;
      case 'performance':
        this.router.navigate(['team-leader/team-management']);
        break;
    }
  }

  // 获取优先级标签
  getPriorityLabel(priority: 'high' | 'medium' | 'low'): string {
    const labels: Record<'high' | 'medium' | 'low', string> = {
      'high': '紧急且重要',
      'medium': '重要不紧急',
      'low': '紧急不重要'
    };
    return labels[priority];
  }

  // 导航到团队管理
  navigateToTeamManagement(): void {
    this.router.navigate(['/team-leader/team-management']);
  }

  // 导航到项目评审
  navigateToProjectReview(): void {
    // 统一入口：跳转到项目列表/看板，而非旧评审页
    this.router.navigate(['/team-leader/dashboard']);
  }

  // 导航到质量管理
  navigateToQualityManagement(): void {
    this.router.navigate(['/team-leader/quality-management']);
  }

  // 打开工作量预估工具（已迁移）
  openWorkloadEstimator(): void {
    // 工具迁移至详情页：引导前往当前选中项目详情
    if (this.selectedProjectId) {
      this.router.navigate(['/team-leader/project-detail', this.selectedProjectId], { queryParams: { tool: 'estimator' } });
    } else {
      this.router.navigate(['/team-leader/dashboard']);
    }
    alert('工作量预估工具已迁移至项目详情页，您可以在建模阶段之前使用该工具进行工作量计算。');
  }

  // 查看所有超期项目
  viewAllOverdueProjects(): void {
    this.filterByStatus('overdue');
    this.closeAlert();
  }

  // 关闭提醒
  closeAlert(): void {
    this.showAlert = false;
  }

  // 维度切换（设计师/会员类型）
  setWorkloadDimension(dim: 'designer' | 'member'): void {
    if (this.workloadDimension !== dim) {
      this.workloadDimension = dim;
      this.updateWorkloadChart();
    }
  }

  // 刷新“工作量概览”图表
  private updateWorkloadChart(): void {
    if (!this.workloadChartRef) { return; }
    const el = this.workloadChartRef.nativeElement;
    if (!el) { return; }

    // 初始化实例（使用 SVG 渲染以获得更佳文本清晰度）
    if (!this.workloadChart) {
      this.workloadChart = echarts.init(el, null, { renderer: 'svg' });
    }

    const data = (this.filteredProjects && this.filteredProjects.length) ? this.filteredProjects : this.projects;
    const byDesigner = this.workloadDimension === 'designer';
    const groupKey = byDesigner ? 'designerName' : 'memberType';

    const labelMap: Record<string, string> = { vip: 'VIP', normal: '普通' };
    const groupSet = new Set<string>();
    data.forEach(p => {
      const val = (p as any)[groupKey] || (byDesigner ? '未分配' : '未知');
      groupSet.add(val);
    });
    const categories = Array.from(groupSet).sort((a, b) => a.localeCompare(b, 'zh-Hans-CN'));

    const count = (urg: 'high'|'medium'|'low', group: string) =>
      data.filter(p => (((p as any)[groupKey] || (byDesigner ? '未分配' : '未知')) === group) && p.urgency === urg).length;

    const high = categories.map(c => count('high', c));
    const medium = categories.map(c => count('medium', c));
    const low = categories.map(c => count('low', c));

    const option = {
      tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
      legend: { data: ['高', '中', '低'] },
      grid: { left: 12, right: 16, top: 28, bottom: 8, containLabel: true },
      xAxis: { type: 'value', boundaryGap: [0, 0.01] },
      yAxis: {
        type: 'category',
        data: categories.map(c => byDesigner ? c : (labelMap[c] || c))
      },
      series: [
        { name: '高', type: 'bar', stack: 'workload', data: high, itemStyle: { color: '#ef4444' } },
        { name: '中', type: 'bar', stack: 'workload', data: medium, itemStyle: { color: '#f59e0b' } },
        { name: '低', type: 'bar', stack: 'workload', data: low, itemStyle: { color: '#10b981' } }
      ]
    } as any;

    this.workloadChart.clear();
    this.workloadChart.setOption(option, true);
    this.workloadChart.resize();
  }

  resetStatusFilter(): void {
    this.selectedStatus = 'all';
    this.applyFilters();
  }
}
