import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { ProjectService } from '../../../services/project.service';
import {
  Project,
  RenderProgress,
  ModelCheckItem,
  CustomerFeedback,
  DesignerChange,
  Settlement,
  ProjectStage
} from '../../../models/project.model';

interface ExceptionHistory {
  id: string;
  type: 'failed' | 'stuck' | 'quality' | 'other';
  description: string;
  submitTime: Date;
  status: '待处理' | '处理中' | '已解决';
  response?: string;
}

interface ProjectMember {
  id: string;
  name: string;
  role: string;
  avatar: string;
  skillMatch: number;
  progress: number;
  contribution: number;
}

interface ProjectFile {
  id: string;
  name: string;
  type: string;
  size: string;
  date: string;
  url: string;
}

interface TimelineEvent {
  id: string;
  time: string;
  title: string;
  action: string;
  description: string;
}

// 新增：四大板块键类型（顶层声明，供组件与模板共同使用）
type SectionKey = 'order' | 'requirements' | 'delivery' | 'aftercare';

@Component({
  selector: 'app-project-detail',
  imports: [CommonModule, FormsModule],
  templateUrl: './project-detail.html',
  styleUrls: ['./project-detail.scss', './debug-styles.scss']
})
export class ProjectDetail implements OnInit, OnDestroy {
  // 项目基本数据
  projectId: string = '';
  project: Project | undefined;
  renderProgress: RenderProgress | undefined;
  modelCheckItems: ModelCheckItem[] = [];
  feedbacks: CustomerFeedback[] = [];
  designerChanges: DesignerChange[] = [];
  settlements: Settlement[] = [];
  requirementChecklist: string[] = [];
  reminderMessage: string = '';
  isLoadingRenderProgress: boolean = false;
  errorLoadingRenderProgress: boolean = false;
  feedbackTimeoutCountdown: number = 0;
  private countdownInterval: any;
  projects: {id: string, name: string, status: string}[] = [];
  showDropdown: boolean = false;
  currentStage: string = '';
  // 新增：10阶段顺序（串式流程）
  stageOrder: ProjectStage[] = ['订单创建', '需求沟通', '方案确认', '建模', '软装', '渲染', '尾款结算', '客户评价', '投诉处理'];
  // 新增：阶段展开状态（默认全部收起，当前阶段在数据加载后自动展开）
  expandedStages: Partial<Record<ProjectStage, boolean>> = {
    '订单创建': false,
    '需求沟通': false,
    '方案确认': false,
    '建模': false,
    '软装': false,
    '渲染': false,
    '尾款结算': false,
    '客户评价': false,
    '投诉处理': false,
  };

  // 新增：四大板块定义与展开状态
  sections: Array<{ key: SectionKey; label: string; stages: ProjectStage[] }> = [
    { key: 'order', label: '订单创建', stages: ['订单创建'] },
    { key: 'requirements', label: '确认需求', stages: ['需求沟通', '方案确认'] },
    { key: 'delivery', label: '交付执行', stages: ['建模', '软装', '渲染'] },
    { key: 'aftercare', label: '售后', stages: ['尾款结算', '客户评价', '投诉处理'] }
  ];
  expandedSection: SectionKey | null = null;
  // 渲染异常反馈相关属性
  exceptionType: 'failed' | 'stuck' | 'quality' | 'other' = 'failed';
  exceptionDescription: string = '';
  exceptionScreenshotUrl: string | null = null;
  exceptionHistories: ExceptionHistory[] = [];
  isSubmittingFeedback: boolean = false;
  selectedScreenshot: File | null = null;
  screenshotPreview: string | null = null;
  showExceptionForm: boolean = false;
  
  // 标签页相关
  activeTab: 'progress' | 'members' | 'files' = 'progress';
  tabs = [
    { id: 'progress', name: '项目进度' },
    { id: 'members', name: '项目成员' },
    { id: 'files', name: '项目文件' }
  ];

  // 标准化阶段（视图层映射）
  standardPhases: Array<'待分配' | '需求方案' | '项目执行' | '收尾验收' | '归档'> = ['待分配', '需求方案', '项目执行', '收尾验收', '归档'];

  // 文件上传（通用）
  acceptedFileTypes: string = '.doc,.docx,.pdf,.jpg,.jpeg,.png,.zip,.rar,.max,.obj';
  isUploadingFile: boolean = false;
  projectMembers: ProjectMember[] = [];
  
  // 项目文件数据
  projectFiles: ProjectFile[] = [];
  
  // 团队协作时间轴
  timelineEvents: TimelineEvent[] = [];

  // ============ 阶段图片上传状态（新增） ============
  allowedImageTypes: string = '.jpg,.jpeg,.png';
  // 增加审核状态reviewStatus与是否已同步synced标记（仅由组长操作）
  whiteModelImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
  softDecorImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
  renderLargeImages: Array<{ id: string; name: string; url: string; size?: string; reviewStatus?: 'pending' | 'approved' | 'rejected'; synced?: boolean }> = [];
  showRenderUploadModal: boolean = false;
  pendingRenderLargeItems: Array<{ id: string; name: string; url: string; file: File }> = [];

  // 视图上下文：根据路由前缀识别角色视角（客服/设计师/组长）
  private roleContext: 'customer-service' | 'designer' | 'team-leader' = 'designer';

  constructor(
    private route: ActivatedRoute,
    private projectService: ProjectService,
    private router: Router
  ) {}

  // 切换标签页
  switchTab(tabId: 'progress' | 'members' | 'files') {
    this.activeTab = tabId;
  }

  // 类型安全的标签页检查方法
  isActiveTab(tabId: 'progress' | 'members' | 'files'): boolean {
    return this.activeTab === tabId;
  }

  // 根据事件类型获取作者名称
  getEventAuthor(action: string): string {
    // 根据不同的action类型返回对应的作者名称
    switch(action) {
      case '完成':
      case '更新':
      case '优化':
        return '李设计师';
      case '收到':
        return '李客服';
      case '提交':
        return '赵建模师';
      default:
        return '王组长';
    }
  }

  // 切换项目
  switchProject(projectId: string): void {
    this.projectId = projectId;
    this.loadProjectData();
    this.loadProjectMembers();
    this.loadProjectFiles();
    this.loadTimelineEvents();
    // 更新URL但不触发组件重载
    this.router.navigate([], { relativeTo: this.route, queryParamsHandling: 'merge', queryParams: { id: projectId } });
  }

  // 返回工作台
  backToWorkbench(): void {
    this.router.navigate(['/designer/dashboard']);
  }
  
  // 检查阶段是否已完成
  isStageCompleted(stage: ProjectStage): boolean {
    if (!this.project) return false;
    
    // 定义阶段顺序
    const stageOrder = [
      '订单创建', '需求沟通', '方案确认', '建模', '软装', 
      '渲染', '后期', '尾款结算', '客户评价', '投诉处理'
    ];
    
    // 获取当前阶段和检查阶段的索引
    const currentStageIndex = stageOrder.indexOf(this.project.currentStage);
    const checkStageIndex = stageOrder.indexOf(stage);
    
    // 如果检查阶段在当前阶段之前，则已完成
    return checkStageIndex < currentStageIndex;
  }

  // 获取阶段状态：completed/active/pending
  getStageStatus(stage: ProjectStage): 'completed' | 'active' | 'pending' {
    const order = this.stageOrder;
    const current = this.project?.currentStage as ProjectStage | undefined;
    const currentIdx = current ? order.indexOf(current) : -1;
    const idx = order.indexOf(stage);
    if (idx === -1) return 'pending';
    if (currentIdx === -1) return 'pending';
    if (idx < currentIdx) return 'completed';
    if (idx === currentIdx) return 'active';
    return 'pending';
  }

  // 切换阶段展开/收起，并保持单展开
  toggleStage(stage: ProjectStage): void {
    // 已移除所有展开按钮，本方法保留以兼容模板其它引用，如无需可进一步删除调用点和方法
    const exclusivelyOpen = true;
    if (exclusivelyOpen) {
      Object.keys(this.expandedStages).forEach((key) => (this.expandedStages[key as ProjectStage] = false));
      this.expandedStages[stage] = true;
    } else {
      this.expandedStages[stage] = !this.expandedStages[stage];
    }
  }

  // 查看阶段详情（已不再通过按钮触发，保留以兼容日志或未来调用）
  viewStageDetails(stage: ProjectStage): void {
    // 以往这里有 alert/导航行为，现清空用户交互，避免误触
    return;
  }

  ngOnInit(): void {
    this.route.paramMap.subscribe(params => {
      this.projectId = params.get('id') || '';
      // 根据当前URL检测视图上下文
      this.roleContext = this.detectRoleContextFromUrl();
      this.loadProjectData();
      this.loadExceptionHistories();
      this.loadProjectMembers();
      this.loadProjectFiles();
      this.loadTimelineEvents();
    });
    
    // 添加点击事件监听器，当点击页面其他位置时关闭下拉菜单
    document.addEventListener('click', this.closeDropdownOnClickOutside);
  }

  // 在组件销毁时移除事件监听器和清理资源
  ngOnDestroy(): void {
    if (this.countdownInterval) {
      clearInterval(this.countdownInterval);
    }
    document.removeEventListener('click', this.closeDropdownOnClickOutside);
    // 释放所有 blob 预览 URL
    const revokeList: string[] = [];
    this.whiteModelImages.forEach(i => { if (i.url.startsWith('blob:')) revokeList.push(i.url); });
    this.softDecorImages.forEach(i => { if (i.url.startsWith('blob:')) revokeList.push(i.url); });
    this.renderLargeImages.forEach(i => { if (i.url.startsWith('blob:')) revokeList.push(i.url); });
    this.pendingRenderLargeItems.forEach(i => { if (i.url.startsWith('blob:')) revokeList.push(i.url); });
    revokeList.forEach(u => URL.revokeObjectURL(u));
  }

  // ============ 角色视图与只读控制（新增） ============
  private detectRoleContextFromUrl(): 'customer-service' | 'designer' | 'team-leader' {
    const url = this.router.url || '';
    if (url.includes('/customer-service/')) return 'customer-service';
    if (url.includes('/team-leader/')) return 'team-leader';
    return 'designer';
  }

  isDesignerView(): boolean { return this.roleContext === 'designer'; }
  isTeamLeaderView(): boolean { return this.roleContext === 'team-leader'; }
  isCustomerServiceView(): boolean { return this.roleContext === 'customer-service'; }
  // 只读规则：客服视角为只读
  isReadOnly(): boolean { return this.isCustomerServiceView(); }

  // 设计师仅看三大执行阶段，其它角色看全流程
  getVisibleStages(): ProjectStage[] {
    if (this.isDesignerView()) {
      return this.stageOrder.filter(s => ['建模', '软装', '渲染'].includes(s));
    }
    return this.stageOrder;
  }

  // ============ 组长：同步上传与审核（新增，模拟实现） ============
  syncUploadedImages(phase: 'white' | 'soft' | 'render'): void {
    if (!this.isTeamLeaderView()) return;
    const markSynced = (arr: Array<{ reviewStatus?: 'pending'|'approved'|'rejected'; synced?: boolean }>) => {
      arr.forEach(img => {
        if (!img.synced) img.synced = true;
        if (!img.reviewStatus) img.reviewStatus = 'pending';
      });
    };
    if (phase === 'white') markSynced(this.whiteModelImages);
    if (phase === 'soft') markSynced(this.softDecorImages);
    if (phase === 'render') markSynced(this.renderLargeImages);
    alert('已同步该阶段的图片信息（模拟）');
  }

  reviewImage(imageId: string, phase: 'white' | 'soft' | 'render', status: 'approved' | 'rejected'): void {
    if (!this.isTeamLeaderView()) return;
    const setStatus = (arr: Array<{ id: string; reviewStatus?: 'pending'|'approved'|'rejected'; synced?: boolean }>) => {
      const target = arr.find(i => i.id === imageId);
      if (target) {
        target.reviewStatus = status;
        if (!target.synced) target.synced = true; // 审核时自动视为已同步
      }
    };
    if (phase === 'white') setStatus(this.whiteModelImages);
    if (phase === 'soft') setStatus(this.softDecorImages);
    if (phase === 'render') setStatus(this.renderLargeImages);
  }

  getImageReviewStatusText(img: { reviewStatus?: 'pending'|'approved'|'rejected'; synced?: boolean }): string {
    const synced = img.synced ? '已同步' : '未同步';
    const map: Record<string, string> = {
      'pending': '待审',
      'approved': '已通过',
      'rejected': '已驳回'
    };
    const st = img.reviewStatus ? map[img.reviewStatus] : '未标记';
    return `${st} · ${synced}`;
  }

  // 点击页面其他位置时关闭下拉菜单
  private closeDropdownOnClickOutside = (event: MouseEvent): void => {
    const targetElement = event.target as HTMLElement;
    const projectSwitcher = targetElement.closest('.project-switcher');
    
    if (!projectSwitcher && this.showDropdown) {
      this.showDropdown = false;
    }
  };

  loadProjectData(): void {
    if (this.projectId) {
      this.loadProjectDetails();
      this.loadRenderProgress();
      this.loadModelCheckItems();
      this.loadCustomerFeedbacks();
      this.loadDesignerChanges();
      this.loadSettlements();
      this.loadRequirementChecklist();
    }
    
    // 初始化项目列表数据（模拟）
    this.projects = [
      { id: '1', name: '现代风格客厅设计', status: '进行中' },
      { id: '2', name: '北欧风卧室装修', status: '已完成' },
      { id: '3', name: '新中式书房改造', status: '进行中' },
      { id: '4', name: '工业风餐厅设计', status: '待处理' }
    ];
  }
  
  // 加载项目成员数据
  loadProjectMembers(): void {
    // 模拟API请求获取项目成员数据
    setTimeout(() => {
      this.projectMembers = [
        {
          id: '1',
          name: '李设计师',
          role: '主设计师',
          avatar: '李',
          skillMatch: 95,
          progress: 65,
          contribution: 75
        },
        {
          id: '2',
          name: '陈设计师',
          role: '助理设计师',
          avatar: '陈',
          skillMatch: 88,
          progress: 80,
          contribution: 60
        },
        {
          id: '3',
          name: '王组长',
          role: '项目组长',
          avatar: '王',
          skillMatch: 92,
          progress: 70,
          contribution: 70
        },
        {
          id: '4',
          name: '赵建模师',
          role: '3D建模师',
          avatar: '赵',
          skillMatch: 90,
          progress: 90,
          contribution: 85
        }
      ];
    }, 600);
  }
  
  // 加载项目文件数据
  loadProjectFiles(): void {
    // 模拟API请求获取项目文件数据
    setTimeout(() => {
      this.projectFiles = [
        {
          id: '1',
          name: '客厅设计方案V2.0.pdf',
          type: 'pdf',
          size: '2.5MB',
          date: '2024-02-10',
          url: '#'
        },
        {
          id: '2',
          name: '材质库集合.rar',
          type: 'rar',
          size: '45.8MB',
          date: '2024-02-08',
          url: '#'
        },
        {
          id: '3',
          name: '客厅渲染预览1.jpg',
          type: 'jpg',
          size: '3.2MB',
          date: '2024-02-14',
          url: '#'
        },
        {
          id: '4',
          name: '3D模型文件.max',
          type: 'max',
          size: '87.5MB',
          date: '2024-02-12',
          url: '#'
        },
        {
          id: '5',
          name: '客户需求文档.docx',
          type: 'docx',
          size: '1.2MB',
          date: '2024-01-15',
          url: '#'
        },
        {
          id: '6',
          name: '客厅渲染预览2.jpg',
          type: 'jpg',
          size: '3.8MB',
          date: '2024-02-15',
          url: '#'
        }
      ];
    }, 700);
  }
  
  // 加载团队协作时间轴数据
  loadTimelineEvents(): void {
    // 模拟API请求获取时间轴数据
    setTimeout(() => {
      this.timelineEvents = [
        {
          id: '1',
          time: '2024-02-15 14:30',
          title: '渲染完成',
          action: '完成',
          description: '客厅主视角渲染已完成，等待客户确认'
        },
        {
          id: '2',
          time: '2024-02-14 10:15',
          title: '材质调整',
          action: '更新',
          description: '根据客户反馈调整了沙发和窗帘材质'
        },
        {
          id: '3',
          time: '2024-02-12 16:45',
          title: '模型优化',
          action: '优化',
          description: '优化了模型面数，提高渲染效率'
        },
        {
          id: '4',
          time: '2024-02-10 09:30',
          title: '客户反馈',
          action: '收到',
          description: '收到客户关于颜色和储物空间的反馈意见'
        },
        {
          id: '5',
          time: '2024-02-08 15:20',
          title: '模型提交',
          action: '提交',
          description: '完成3D模型搭建并提交审核'
        }
      ];
    }, 800);
  }
  
  // 加载历史反馈记录
  loadExceptionHistories(): void {
    this.projectService.getExceptionHistories(this.projectId).subscribe(histories => {
      this.exceptionHistories = histories;
    });
  }

  loadProjectDetails(): void {
    this.projectService.getProjectById(this.projectId).subscribe(project => {
      this.project = project;
      // 设置当前阶段
      if (project) {
        this.currentStage = project.currentStage || '';
        // 重置展开状态并默认展开当前阶段
        this.stageOrder.forEach(s => this.expandedStages[s] = false);
        if (this.stageOrder.includes(project.currentStage)) {
          this.expandedStages[project.currentStage] = true;
        }
        // 新增：根据当前阶段默认展开所属板块
        const currentSec = this.getSectionKeyForStage(project.currentStage as ProjectStage);
        this.expandedSection = currentSec;
      }
      // 检查技能匹配度
      this.checkSkillMismatch();
    });
  }
  
  // 整理项目详情
  organizeProject(): void {
    // 模拟整理项目逻辑
    alert('项目详情已整理');
  }
  
  // 检查当前阶段是否显示特定卡片
  shouldShowCard(cardType: string): boolean {
    // 改为始终显示：各阶段详情在看板下方就地展示，不再受当前阶段限制
    return true;
  }

  loadRenderProgress(): void {
    this.isLoadingRenderProgress = true;
    this.errorLoadingRenderProgress = false;
    
    // 模拟API加载过程
    setTimeout(() => {
      this.projectService.getRenderProgress(this.projectId).subscribe(progress => {
        this.renderProgress = progress;
        this.isLoadingRenderProgress = false;
        
        // 模拟API加载失败的情况
        if (!progress) {
          this.errorLoadingRenderProgress = true;
          // 通知技术组长
          this.notifyTeamLeader('render-failed');
        } else {
          // 检查是否需要显示超时预警
          this.checkRenderTimeout();
        }
      });
    }, 1000);
  }

  loadModelCheckItems(): void {
    this.projectService.getModelCheckItems().subscribe(items => {
      this.modelCheckItems = items;
    });
  }

  loadCustomerFeedbacks(): void {
    this.projectService.getCustomerFeedbacks().subscribe(feedbacks => {
      this.feedbacks = feedbacks.filter(f => f.projectId === this.projectId);
      // 为反馈添加分类标签
      this.tagCustomerFeedbacks();
      // 检查是否有需要处理的反馈并启动倒计时
      this.checkFeedbackTimeout();
    });
  }

  loadDesignerChanges(): void {
    // 在实际应用中，这里应该从服务中获取设计师变更记录
    // 这里使用模拟数据
    this.designerChanges = [
      {
        id: 'dc1',
        projectId: this.projectId,
        oldDesignerId: 'designer2',
        oldDesignerName: '设计师B',
        newDesignerId: 'designer1',
        newDesignerName: '设计师A',
        changeTime: new Date('2025-09-05'),
        acceptanceTime: new Date('2025-09-05'),
        historicalAchievements: ['完成初步建模', '确定色彩方案'],
        completedWorkload: 30
      }
    ];
  }

  loadSettlements(): void {
    this.projectService.getSettlements().subscribe(settlements => {
      this.settlements = settlements.filter(s => s.projectId === this.projectId);
    });
  }

  loadRequirementChecklist(): void {
    this.projectService.generateRequirementChecklist(this.projectId).subscribe(checklist => {
      this.requirementChecklist = checklist;
    });
  }

  updateModelCheckItem(itemId: string, isPassed: boolean): void {
    this.projectService.updateModelCheckItem(itemId, isPassed).subscribe(() => {
      this.loadModelCheckItems(); // 重新加载检查项
    });
  }

  updateFeedbackStatus(feedbackId: string, status: '处理中' | '已解决'): void {
    this.projectService.updateFeedbackStatus(feedbackId, status).subscribe(() => {
      this.loadCustomerFeedbacks(); // 重新加载反馈
      // 清除倒计时
      if (this.countdownInterval) {
        clearInterval(this.countdownInterval);
        this.feedbackTimeoutCountdown = 0;
      }
    });
  }

  updateProjectStage(stage: ProjectStage): void {
    if (this.project) {
      this.projectService.updateProjectStage(this.projectId, stage).subscribe(() => {
        this.loadProjectDetails(); // 重新加载项目详情
      });
    }
  }

  // 新增：根据给定阶段跳转到下一阶段
  advanceToNextStage(afterStage: ProjectStage): void {
    const idx = this.stageOrder.indexOf(afterStage);
    if (idx >= 0 && idx < this.stageOrder.length - 1) {
      const next = this.stageOrder[idx + 1];
      this.updateProjectStage(next);
      // 可选：更新展开状态，折叠当前、展开下一阶段，提升体验
      if (this.expandedStages[afterStage] !== undefined) this.expandedStages[afterStage] = false as any;
      if (this.expandedStages[next] !== undefined) this.expandedStages[next] = true as any;
    }
  }
  generateReminderMessage(): void {
    this.projectService.generateReminderMessage('stagnation').subscribe(message => {
      this.reminderMessage = message;
      
      // 3秒后自动清除提醒
      setTimeout(() => {
        this.reminderMessage = '';
      }, 3000);
    });
  }

  // ============ 新增：标准化阶段映射与紧急程度 ============
  // 计算距离截止日期的天数（向下取整）
  getDaysToDeadline(): number | null {
    if (!this.project?.deadline) return null;
    const now = new Date();
    const deadline = new Date(this.project.deadline);
    const diffMs = deadline.getTime() - now.getTime();
    return Math.floor(diffMs / (1000 * 60 * 60 * 24));
  }

  // 是否延期/临期/提示
  getUrgencyBadge(): 'overdue' | 'due_3' | 'due_7' | null {
    const d = this.getDaysToDeadline();
    if (d === null) return null;
    if (d < 0) return 'overdue';
    if (d <= 3) return 'due_3';
    if (d <= 7) return 'due_7';
    return null;
  }

  // 是否存在不满意或待处理投诉/反馈
  hasPendingComplaint(): boolean {
    return this.feedbacks.some(f => !f.isSatisfied || f.status === '待处理');
  }

  // 将现有细分阶段映射为标准化阶段
  mapToStandardPhase(stage: ProjectStage): '待分配' | '需求方案' | '项目执行' | '收尾验收' | '归档' {
    const mapping: Record<ProjectStage, '待分配' | '需求方案' | '项目执行' | '收尾验收' | '归档'> = {
      '订单创建': '待分配',
      '需求沟通': '需求方案',
      '方案确认': '需求方案',
      '建模': '项目执行',
      '软装': '项目执行',
      '渲染': '项目执行',
      '后期': '项目执行',
      '尾款结算': '收尾验收',
      '客户评价': '收尾验收',
      '投诉处理': '收尾验收'
    };
    return mapping[stage] ?? '待分配';
  }

  getStandardPhaseIndex(): number {
    if (!this.project?.currentStage) return 0;
    const phase = this.mapToStandardPhase(this.project.currentStage);
    return this.standardPhases.indexOf(phase);
  }

  isStandardPhaseCompleted(phase: '待分配' | '需求方案' | '项目执行' | '收尾验收' | '归档'): boolean {
    return this.standardPhases.indexOf(phase) < this.getStandardPhaseIndex();
  }

  isStandardPhaseCurrent(phase: '待分配' | '需求方案' | '项目执行' | '收尾验收' | '归档'): boolean {
    return this.standardPhases.indexOf(phase) === this.getStandardPhaseIndex();
  }

  // ============ 新增：项目报告导出 ============
  exportProjectReport(): void {
    if (!this.project) return;
    const lines: string[] = [];
    const d = this.getDaysToDeadline();
    lines.push(`项目名称: ${this.project.name}`);
    lines.push(`当前阶段(细分): ${this.project.currentStage}`);
    lines.push(`当前阶段(标准化): ${this.mapToStandardPhase(this.project.currentStage)}`);
    if (this.project.deadline) {
      lines.push(`截止日期: ${this.formatDate(this.project.deadline)}`);
      lines.push(`剩余天数: ${d !== null ? d : '-'}天`);
    }
    lines.push(`技能需求: ${(this.project.skillsRequired || []).join('、')}`);
    lines.push('—— 渲染进度 ——');
    lines.push(this.renderProgress ? `状态: ${this.renderProgress.status}, 完成度: ${this.renderProgress.completionRate}%` : '无渲染进度数据');
    lines.push('—— 客户反馈 ——');
    lines.push(this.feedbacks.length ? `${this.feedbacks.length} 条` : '暂无');
    lines.push('—— 设计师变更 ——');
    lines.push(this.designerChanges.length ? `${this.designerChanges.length} 条` : '暂无');
    lines.push('—— 交付文件 ——');
    lines.push(this.projectFiles.length ? this.projectFiles.map(f => `• ${f.name} (${f.type}, ${f.size})`).join('\n') : '暂无');

    const content = lines.join('\n');
    const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${this.project.name || '项目'}-阶段报告.txt`;
    a.click();
    URL.revokeObjectURL(url);
  }

  // ============ 新增：通用文件上传（含4K图片校验） ============
  async onGeneralFilesSelected(event: Event): Promise<void> {
    const input = event.target as HTMLInputElement;
    if (!input.files || input.files.length === 0) return;
    const files = Array.from(input.files);
    this.isUploadingFile = true;

    for (const file of files) {
      // 对图片进行4K校验（最大边 >= 4000px）
      if (/\.(jpg|jpeg|png)$/i.test(file.name)) {
        const ok = await this.validateImage4K(file).catch(() => false);
        if (!ok) {
          alert(`图片不符合4K标准（最大边需≥4000像素）：${file.name}`);
          continue;
        }
      }
      // 简化：直接追加到本地列表（实际应上传到服务器）
      const fakeType = (file.name.split('.').pop() || '').toLowerCase();
      const sizeMB = (file.size / (1024 * 1024)).toFixed(1) + 'MB';
      const nowStr = this.formatDate(new Date());
      this.projectFiles.unshift({
        id: `file-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
        name: file.name,
        type: fakeType,
        size: sizeMB,
        date: nowStr,
        url: '#'
      });
    }

    this.isUploadingFile = false;
    // 清空选择
    input.value = '';
  }

  validateImage4K(file: File): Promise<boolean> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => {
        const img = new Image();
        img.onload = () => {
          const maxSide = Math.max(img.width, img.height);
          resolve(maxSide >= 4000);
        };
        img.onerror = () => reject('image load error');
        img.src = reader.result as string;
      };
      reader.onerror = () => reject('read error');
      reader.readAsDataURL(file);
    });
  }

  // 可选：列表 trackBy，优化渲染
  trackById(_: number, item: { id: string }): string { return item.id; }

  retryLoadRenderProgress(): void {
    this.loadRenderProgress();
  }

  // 检查是否所有模型检查项都已通过
  areAllModelChecksPassed(): boolean {
    return this.modelCheckItems.every(item => item.isPassed);
  }

  // 获取技能匹配度警告
  getSkillMismatchWarning(): string | null {
    if (!this.project) return null;
    
    // 模拟技能匹配度检查
    const designerSkills = ['现代风格', '硬装'];
    const requiredSkills = this.project.skillsRequired;
    
    const mismatchedSkills = requiredSkills.filter(skill => !designerSkills.includes(skill));
    
    if (mismatchedSkills.length > 0) {
      return `警告：您不擅长${mismatchedSkills.join('、')}，建议联系组长协调`;
    }
    
    return null;
  }

  // 检查渲染是否超时
  checkRenderTimeout(): void {
    if (!this.renderProgress || !this.project) return;
    
    // 模拟交付前3小时预警
    const deliveryTime = new Date(this.project.deadline);
    const currentTime = new Date();
    const timeDifference = deliveryTime.getTime() - currentTime.getTime();
    const hoursRemaining = Math.floor(timeDifference / (1000 * 60 * 60));
    
    if (hoursRemaining <= 3 && hoursRemaining > 0) {
      // 弹窗预警
      alert('渲染进度预警：交付前3小时，请关注渲染进度');
    }
    
    if (hoursRemaining <= 1 && hoursRemaining > 0) {
      // 更严重的预警
      alert('渲染进度严重预警：交付前1小时，渲染可能无法按时完成！');
    }
  }

  // 为客户反馈添加分类标签
  tagCustomerFeedbacks(): void {
    this.feedbacks.forEach(feedback => {
      // 添加分类标签
      if (feedback.content.includes('色彩') || feedback.problemLocation?.includes('色彩')) {
        (feedback as any).tag = '色彩问题';
      } else if (feedback.content.includes('家具') || feedback.problemLocation?.includes('家具')) {
        (feedback as any).tag = '家具款式问题';
      } else if (feedback.content.includes('光线') || feedback.content.includes('照明')) {
        (feedback as any).tag = '光线问题';
      } else {
        (feedback as any).tag = '其他问题';
      }
    });
  }
  
  // 获取反馈标签的辅助方法
  getFeedbackTag(feedback: CustomerFeedback): string {
    return (feedback as any).tag || '';
  }

  // 检查反馈超时
  checkFeedbackTimeout(): void {
    const pendingFeedbacks = this.feedbacks.filter(f => f.status === '待处理');
    if (pendingFeedbacks.length > 0) {
      // 启动1小时倒计时
      this.feedbackTimeoutCountdown = 3600; // 3600秒 = 1小时
      this.startCountdown();
    }
  }

  // 启动倒计时
  startCountdown(): void {
    this.countdownInterval = setInterval(() => {
      if (this.feedbackTimeoutCountdown > 0) {
        this.feedbackTimeoutCountdown--;
      } else {
        clearInterval(this.countdownInterval);
        // 超时提醒
        alert('客户反馈已超过1小时未响应，请立即处理！');
        this.notifyTeamLeader('feedback-overdue');
      }
    }, 1000);
  }

  // 通知技术组长
  notifyTeamLeader(type: 'render-failed' | 'feedback-overdue' | 'skill-mismatch'): void {
    // 实际应用中应调用消息服务通知组长
    console.log(`通知技术组长：${type} - 项目ID: ${this.projectId}`);
  }

  // 检查技能匹配度并提示
  checkSkillMismatch(): void {
    const warning = this.getSkillMismatchWarning();
    if (warning) {
      // 显示技能不匹配警告
      if (confirm(`${warning}\n是否联系技术组长协调支持？`)) {
        this.notifyTeamLeader('skill-mismatch');
      }
    }
  }

  // 发起设计师变更
  initiateDesignerChange(reason: string): void {
    // 实际应用中应调用API发起变更
    console.log(`发起设计师变更，原因：${reason}`);
    alert('已发起设计师变更申请，请等待新设计师承接');
  }

  // 确认承接变更项目
  acceptDesignerChange(changeId: string): void {
    // 实际应用中应调用API确认承接
    console.log(`确认承接设计师变更：${changeId}`);
    alert('已确认承接项目，系统已记录时间戳和责任人');
  }

  // 格式化倒计时显示
  formatCountdown(seconds: number): string {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const remainingSeconds = seconds % 60;
    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
  }



  // 提交异常反馈
  submitExceptionFeedback(): void {
    if (!this.exceptionDescription.trim() || this.isSubmittingFeedback) {
      alert('请填写异常类型和描述');
      return;
    }

    this.isSubmittingFeedback = true;
    
    // 模拟提交反馈到服务器
    setTimeout(() => {
      const newException: ExceptionHistory = {
        id: `exception-${Date.now()}`,
        type: this.exceptionType,
        description: this.exceptionDescription,
        submitTime: new Date(),
        status: '待处理'
      };

      // 添加到历史记录中
      this.exceptionHistories.unshift(newException);
      
      // 通知客服和技术支持
      this.notifyTechnicalSupport(newException);
      
      // 清空表单
      this.exceptionDescription = '';
      this.clearExceptionScreenshot();
      this.showExceptionForm = false;
      
      // 显示成功消息
      alert('异常反馈已提交，技术支持将尽快处理');
      
      this.isSubmittingFeedback = false;
    }, 1000);
  }

  // 上传异常截图
  uploadExceptionScreenshot(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files[0]) {
      const file = input.files[0];
      // 在实际应用中，这里应该上传文件到服务器
      // 这里我们使用FileReader来生成一个预览URL
      const reader = new FileReader();
      reader.onload = (e) => {
        this.exceptionScreenshotUrl = e.target?.result as string;
      };
      reader.readAsDataURL(file);
    }
  }

  // 清除异常截图
  clearExceptionScreenshot(): void {
    this.exceptionScreenshotUrl = null;
    const input = document.getElementById('screenshot-upload') as HTMLInputElement;
    if (input) {
      input.value = '';
    }
  }

  // 联系组长
  contactTeamLeader() {
    alert(`已联系${this.project?.assigneeName || '项目组长'}`);
  }

  // 处理渲染超时预警
  handleRenderTimeout() {
    alert('已发送渲染超时预警通知');
  }

  // 通知技术支持
  notifyTechnicalSupport(exception: ExceptionHistory): void {
    // 实际应用中应调用消息服务通知技术支持和客服
    console.log(`通知技术支持和客服：渲染异常 - 项目ID: ${this.projectId}`);
    console.log(`异常类型: ${this.getExceptionTypeText(exception.type)}, 描述: ${exception.description}`);
  }

  // 获取异常类型文本
  getExceptionTypeText(type: string): string {
    const typeMap: Record<string, string> = {
      'failed': '渲染失败',
      'stuck': '渲染卡顿',
      'quality': '渲染质量问题',
      'other': '其他问题'
    };
    return typeMap[type] || type;
  }

  // 格式化日期
  formatDate(date: Date | string): string {
    const d = typeof date === 'string' ? new Date(date) : date;
    const year = d.getFullYear();
    const month = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    const hours = String(d.getHours()).padStart(2, '0');
    const minutes = String(d.getMinutes()).padStart(2, '0');
    return `${year}-${month}-${day} ${hours}:${minutes}`;
  }

  // 将字节格式化为易读尺寸
  private formatFileSize(bytes: number): string {
    if (bytes < 1024) return `${bytes}B`;
    const kb = bytes / 1024;
    if (kb < 1024) return `${kb.toFixed(1)}KB`;
    const mb = kb / 1024;
    if (mb < 1024) return `${mb.toFixed(1)}MB`;
    const gb = mb / 1024;
    return `${gb.toFixed(2)}GB`;
  }

  // 生成缩略图条目（并创建本地预览URL）
  private makeImageItem(file: File): { id: string; name: string; url: string; size: string } {
    const id = `img-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    const url = URL.createObjectURL(file);
    return { id, name: file.name, url, size: this.formatFileSize(file.size) };
  }

  // 释放对象URL
  private revokeUrl(url: string): void {
    try { if (url && url.startsWith('blob:')) URL.revokeObjectURL(url); } catch {}
  }

  // =========== 建模阶段：白模上传 ===========
  onWhiteModelSelected(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (!input.files || input.files.length === 0) return;
    const files = Array.from(input.files).filter(f => /\.(jpg|jpeg|png)$/i.test(f.name));
    const items = files.map(f => this.makeImageItem(f));
    this.whiteModelImages.unshift(...items);
    input.value = '';
  }
  removeWhiteModelImage(id: string): void {
    const target = this.whiteModelImages.find(i => i.id === id);
    if (target) this.revokeUrl(target.url);
    this.whiteModelImages = this.whiteModelImages.filter(i => i.id !== id);
  }

  // 新增：建模阶段 确认上传并自动进入下一阶段（软装）
  confirmWhiteModelUpload(): void {
    if (this.whiteModelImages.length === 0) return;
    this.advanceToNextStage('建模');
  }

  // =========== 软装阶段：小图上传（建议≤1MB，不强制） ===========
  onSoftDecorSmallPicsSelected(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (!input.files || input.files.length === 0) return;
    const files = Array.from(input.files).filter(f => /\.(jpg|jpeg|png)$/i.test(f.name));
    const warnOversize = files.filter(f => f.size > 1024 * 1024);
    if (warnOversize.length > 0) {
      // 仅提示，不阻断
      console.warn('软装小图建议≤1MB，以下文件较大：', warnOversize.map(f => f.name));
    }
    const items = files.map(f => this.makeImageItem(f));
    this.softDecorImages.unshift(...items);
    input.value = '';
  }
  removeSoftDecorImage(id: string): void {
    const target = this.softDecorImages.find(i => i.id === id);
    if (target) this.revokeUrl(target.url);
    this.softDecorImages = this.softDecorImages.filter(i => i.id !== id);
  }

  // 新增：软装阶段 确认上传并自动进入下一阶段（渲染）
  confirmSoftDecorUpload(): void {
    if (this.softDecorImages.length === 0) return;
    this.advanceToNextStage('软装');
  }

  // =========== 渲染阶段：大图上传（弹窗 + 4K校验） ===========
  openRenderUploadModal(): void {
    this.showRenderUploadModal = true;
    this.pendingRenderLargeItems = [];
  }
  closeRenderUploadModal(): void {
    // 关闭时释放临时预览URL
    this.pendingRenderLargeItems.forEach(i => this.revokeUrl(i.url));
    this.pendingRenderLargeItems = [];
    this.showRenderUploadModal = false;
  }
  async onRenderLargePicsSelected(event: Event): Promise<void> {
    const input = event.target as HTMLInputElement;
    if (!input.files || input.files.length === 0) return;
    const files = Array.from(input.files).filter(f => /\.(jpg|jpeg|png)$/i.test(f.name));

    for (const f of files) {
      const ok = await this.validateImage4K(f).catch(() => false);
      if (!ok) {
        alert(`图片不符合4K标准（最大边需≥4000像素）：${f.name}`);
        continue;
      }
      const item = this.makeImageItem(f);
      this.pendingRenderLargeItems.push({ id: item.id, name: item.name, url: item.url, file: f });
    }
    input.value = '';
  }
  confirmRenderUpload(): void {
    // 将待确认的图片加入正式列表（此处模拟上传成功）
    const toAdd = this.pendingRenderLargeItems.map(i => ({ id: i.id, name: i.name, url: i.url, size: this.formatFileSize(i.file.size) }));
    this.renderLargeImages.unshift(...toAdd);
    this.closeRenderUploadModal();
    // 新增：渲染阶段确认后，自动进入下一阶段（后期）
    this.advanceToNextStage('渲染');
  }
  removeRenderLargeImage(id: string): void {
    const target = this.renderLargeImages.find(i => i.id === id);
    if (target) this.revokeUrl(target.url);
    this.renderLargeImages = this.renderLargeImages.filter(i => i.id !== id);
  }

// 根据阶段映射所属板块
getSectionKeyForStage(stage: ProjectStage): SectionKey {
switch (stage) {
case '订单创建':
return 'order';
case '需求沟通':
case '方案确认':
return 'requirements';
case '建模':
case '软装':
case '渲染':
return 'delivery';
case '尾款结算':
case '客户评价':
case '投诉处理':
return 'aftercare';
default:
return 'order';
}
}

// 获取板块状态：completed/active/pending
getSectionStatus(key: SectionKey): 'completed' | 'active' | 'pending' {
  const current = this.project?.currentStage as ProjectStage | undefined;
  if (!current) return 'pending';

  const currentSection = this.getSectionKeyForStage(current);
  const sectionOrder = this.sections.map(s => s.key);
  const currentIdx = sectionOrder.indexOf(currentSection);
  const idx = sectionOrder.indexOf(key);
  if (idx === -1 || currentIdx === -1) return 'pending';

  if (idx < currentIdx) return 'completed';
  if (idx === currentIdx) return 'active';
  return 'pending';
}

// 切换四大板块（单展开）
toggleSection(key: SectionKey): void {
  this.expandedSection = key;
}
}
