import { Injectable } from '@angular/core';
import { v4 as uuidv4 } from 'uuid';
import { FmodeObject, FmodeParse } from 'fmode-ng/parse';

const Parse: any = FmodeParse.with('nova');

export type IssueStatus = 'open' | 'in_progress' | 'resolved' | 'closed';
export type IssuePriority = 'low' | 'medium' | 'high' | 'critical' | 'urgent';
export type IssueType = 'bug' | 'task' | 'feedback' | 'risk' | 'feature';

export interface IssueComment {
  id: string;
  authorId: string;
  content: string;
  createdAt: Date;
}

export interface ProjectIssue {
  id: string;
  projectId: string;
  title: string;
  status: IssueStatus;
  priority: IssuePriority;
  type: IssueType;
  creatorId: string;
  assignee?: FmodeObject;
  assigneeId?: string;
  createdAt: Date;
  updatedAt: Date;
  dueDate?: Date;
  tags?: string[];
  description?: string;
  comments?: IssueComment[];
  // 新增：关联信息
  relatedSpace?: string;
  relatedStage?: string;
  productId?: string;
}

export interface IssueCounts {
  total: number;
  open: number;
  in_progress: number;
  resolved: number;
  closed: number;
}

@Injectable({ providedIn: 'root' })
export class ProjectIssueService {
  private store = new Map<string, ProjectIssue[]>();

  // 状态中英文映射（兼容后台中文状态）
  private zh2en(status: string): IssueStatus {
    const map: any = {
      '待处理': 'open',
      '处理中': 'in_progress',
      '已解决': 'resolved',
      '已关闭': 'closed'
    };
    return (map[status] || status) as IssueStatus;
  }
  private en2zh(status: IssueStatus): string {
    const map: any = {
      open: '待处理',
      in_progress: '处理中',
      resolved: '已解决',
      closed: '已关闭'
    };
    return map[status] || status;
  }

  // 将 Parse.Object 转换为本地模型
  private parseToModel(obj: any): ProjectIssue {
    const data = obj.get('data') || {};
    const tags: string[] = data.tags || [];
    const comments: IssueComment[] = (data.comments || []).map((c: any) => ({
      id: c.id || uuidv4(),
      authorId: c.authorId,
      content: c.content,
      createdAt: c.createdAt ? new Date(c.createdAt) : new Date()
    }));

    const statusRaw = obj.get('status');
    const status: IssueStatus = statusRaw ? this.zh2en(statusRaw) : 'open';

    return {
      id: obj.id,
      projectId: obj.get('project')?.id || '',
      title: obj.get('title') || (obj.get('description') || '').slice(0, 40) || '未命名问题',
      description: obj.get('description') || '',
      priority: (obj.get('priority') || 'medium') as IssuePriority,
      type: (obj.get('issueType') || 'task') as IssueType,
      status,
      creatorId: obj.get('creator')?.id || obj.get('reportedBy')?.id || '',
      assignee: obj.get('assignee'),
      assigneeId: obj.get('assignee')?.id,
      createdAt: obj.createdAt || new Date(),
      updatedAt: obj.updatedAt || new Date(),
      dueDate: obj.get('dueDate') || undefined,
      tags,
      comments,
      relatedSpace: obj.get('relatedSpace') || data.relatedSpace || undefined,
      relatedStage: obj.get('relatedStage') || data.relatedStage || undefined,
      productId: obj.get('product')?.id || undefined
    };
  }

  // 同步缓存筛选
  listIssues(projectId: string, opts?: { status?: IssueStatus[]; text?: string }): ProjectIssue[] {
    const list = this.ensure(projectId);
    let result: ProjectIssue[] = [...list];

    if (opts?.status && opts.status.length > 0) {
      result = result.filter((issue: ProjectIssue) => opts.status!.includes(issue.status));
    }

    if (opts?.text && opts.text.trim()) {
      const q = opts.text.trim().toLowerCase();
      result = result.filter((issue: ProjectIssue) =>
        (issue.title || '').toLowerCase().includes(q) ||
        (issue.description || '').toLowerCase().includes(q) ||
        (issue.tags || []).some((t: string) => t.toLowerCase().includes(q))
      );
    }

    return result.sort((a: ProjectIssue, b: ProjectIssue) => +new Date(b.updatedAt) - +new Date(a.updatedAt));
  }

  // 从后端刷新到缓存
  async refreshFromServer(projectId: string, opts?: { status?: IssueStatus[]; text?: string }): Promise<void> {
    const query = new Parse.Query('ProjectIssue');
    query.equalTo('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
    query.notEqualTo('isDeleted', true);
    query.include(['creator', 'assignee', 'product']);

    // 服务器端粗过滤（仅文本）
    if (opts?.text && opts.text.trim()) {
      const kw = opts.text.trim();
      query.matches('title', new RegExp(kw, 'i'));
    }

    const results = await query.find();
    const list: ProjectIssue[] = results.map((obj: any) => this.parseToModel(obj));

    // 客户端状态过滤
    const filtered: ProjectIssue[] = opts?.status && opts.status.length > 0 ? list.filter((issue: ProjectIssue) => opts!.status!.includes(issue.status)) : list;

    this.store.set(projectId, filtered);
  }

  // 列出负责人候选：基于 ProjectTeam
  async listAssignees(projectId: string): Promise<{ id: string; name: string }[]> {
    try {
      const teamQuery = new Parse.Query('ProjectTeam');
      teamQuery.equalTo('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
      teamQuery.include(['profile']);
      teamQuery.notEqualTo('isDeleted', true);
      const teams = await teamQuery.find();

      const seen = new Set<string>();
      const list: { id: string; name: string }[] = [];
      for (const t of teams) {
        const p = t.get('profile');
        const pid = p?.id;
        const name = p?.get ? (p.get('name') || '未命名') : '未命名';
        if (pid && !seen.has(pid)) {
          seen.add(pid);
          list.push({ id: pid, name });
        }
      }

      // 兜底：加入项目负责人（owner）
      if (list.length === 0) {
        const pQuery = new Parse.Query('Project');
        pQuery.include(['owner']);
        const project = await pQuery.get(projectId);
        const owner = project.get('owner');
        if (owner?.id && !seen.has(owner.id)) {
          list.unshift({ id: owner.id, name: owner.get('name') || '项目负责人' });
          seen.add(owner.id);
        }
      }
      return list;
    } catch (e) {
      console.warn('listAssignees failed', e);
      return [];
    }
  }

  // 创建问题（持久化）
  async createIssue(
    projectId: string,
    payload: { title: string; description?: string; priority?: IssuePriority; type?: IssueType; dueDate?: Date; tags?: string[]; creatorId: string; assigneeId?: string; relatedSpace?: string; relatedStage?: string; productId?: string }
  ): Promise<ProjectIssue> {
    const Issue = Parse.Object.extend('ProjectIssue');
    const obj = new Issue();

    obj.set('project', { __type: 'Pointer', className: 'Project', objectId: projectId });
    obj.set('title', payload.title);
    obj.set('description', payload.description || '');
    obj.set('priority', payload.priority || 'medium');
    obj.set('issueType', payload.type || 'task');
    obj.set('status', this.en2zh('open'));
    obj.set('creator', { __type: 'Pointer', className: 'Profile', objectId: payload.creatorId });

    // 负责人：优先使用传入；否则尝试项目负责人；最后创建人
    let assigneeId = payload.assigneeId;
    if (!assigneeId) {
      try {
        const pQuery = new Parse.Query('Project');
        pQuery.include(['owner']);
        const project = await pQuery.get(projectId);
        assigneeId = project.get('owner')?.id || payload.creatorId;
      } catch {}
    }
    if (assigneeId) {
      obj.set('assignee', { __type: 'Pointer', className: 'Profile', objectId: assigneeId });
    }

    if (payload.dueDate) obj.set('dueDate', payload.dueDate);
    if (payload.relatedSpace) obj.set('relatedSpace', payload.relatedSpace);
    if (payload.relatedStage) obj.set('relatedStage', payload.relatedStage);
    if (payload.productId) obj.set('product', { __type: 'Pointer', className: 'Product', objectId: payload.productId });

    obj.set('isDeleted', false);
    obj.set('data', { tags: payload.tags || [], comments: [], relatedSpace: payload.relatedSpace, relatedStage: payload.relatedStage });

    const saved = await obj.save();
    const model = this.parseToModel(saved);

    const list = this.ensure(projectId);
    list.push(model);
    this.store.set(projectId, list);

    return model;
  }

  // 更新问题（持久化）
  async updateIssue(projectId: string, issueId: string, updates: Partial<ProjectIssue>): Promise<ProjectIssue | null> {
    const query = new Parse.Query('ProjectIssue');
    const obj = await query.get(issueId).catch(() => null);
    if (!obj) return null;

    if (updates.title !== undefined) obj.set('title', updates.title);
    if (updates.description !== undefined) obj.set('description', updates.description);
    if (updates.priority !== undefined) obj.set('priority', updates.priority);
    if (updates.type !== undefined) obj.set('issueType', updates.type);
    if (updates.dueDate !== undefined) obj.set('dueDate', updates.dueDate);
    if (updates.assigneeId !== undefined) {
      obj.set('assignee', updates.assigneeId ? { __type: 'Pointer', className: 'Profile', objectId: updates.assigneeId } : undefined);
    }
    if (updates.relatedSpace !== undefined) obj.set('relatedSpace', updates.relatedSpace || undefined);
    if (updates.relatedStage !== undefined) obj.set('relatedStage', updates.relatedStage || undefined);
    if (updates.productId !== undefined) obj.set('product', updates.productId ? { __type: 'Pointer', className: 'Product', objectId: updates.productId } : undefined);
    if (updates.status !== undefined) obj.set('status', this.en2zh(updates.status));
    if (updates.tags !== undefined) {
      const data = obj.get('data') || {};
      data.tags = updates.tags || [];
      obj.set('data', data);
    }

    const saved = await obj.save();

    // 更新缓存
    const list = this.ensure(projectId);
    const idx = list.findIndex((issue: ProjectIssue) => issue.id === issueId);
    const updated = this.parseToModel(saved);
    if (idx >= 0) list[idx] = updated; else list.push(updated);
    this.store.set(projectId, list);
    return updated;
  }

  async deleteIssue(projectId: string, issueId: string): Promise<boolean> {
    const query = new Parse.Query('ProjectIssue');
    const obj = await query.get(issueId).catch(() => null);
    if (!obj) return false;
    obj.set('isDeleted', true);
    await obj.save();

    const list = this.ensure(projectId).filter((issue: ProjectIssue) => issue.id !== issueId);
    this.store.set(projectId, list);
    return true;
  }

  // 添加评论（持久化至 data.comments）
  async addComment(projectId: string, issueId: string, authorId: string, content: string): Promise<IssueComment | null> {
    const query = new Parse.Query('ProjectIssue');
    const obj = await query.get(issueId).catch(() => null);
    if (!obj) return null;

    const comment: IssueComment = { id: uuidv4(), authorId, content, createdAt: new Date() };
    const data = obj.get('data') || {};
    data.comments = Array.isArray(data.comments) ? data.comments : [];
    data.comments.push({ ...comment });
    obj.set('data', data);
    await obj.save();

    // 更新缓存
    const list = this.ensure(projectId);
    const issue = list.find((i: ProjectIssue) => i.id === issueId);
    if (issue) {
      issue.comments = issue.comments || [];
      issue.comments.push(comment);
      issue.updatedAt = new Date();
      this.store.set(projectId, list);
    }
    return comment;
  }

  // 快速修改状态（持久化）
  async setStatus(projectId: string, issueId: string, status: IssueStatus): Promise<ProjectIssue | null> {
    return await this.updateIssue(projectId, issueId, { status });
  }

  // 统计汇总（缓存）
  getCounts(projectId: string): IssueCounts {
    const list = this.ensure(projectId);
    const counts: IssueCounts = { total: list.length, open: 0, in_progress: 0, resolved: 0, closed: 0 };
    for (const issue of list) {
      if (issue.status === 'open') counts.open++;
      else if (issue.status === 'in_progress') counts.in_progress++;
      else if (issue.status === 'resolved') counts.resolved++;
      else if (issue.status === 'closed') counts.closed++;
    }
    return counts;
  }

  // 首次访问种子数据（仍保留本地演示，不写入后端）
  seed(projectId: string) {
    const list = this.ensure(projectId);
    if (list.length > 0) return;
    const now = new Date();
    const creator = 'seed-user';
    // list.push({
    //   id: uuidv4(), projectId, title: '确认客厅配色与材质样板', description: '需要确认客厅主色调与地面材质，影响方案深化。', priority: 'high', type: 'task', status: 'open', creatorId: creator, createdAt: now, updatedAt: now, dueDate: new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000), tags: ['配色', '材质'], comments: []
    // });
    // list.push({
    //   id: uuidv4(), projectId, title: '主卧效果图灯光偏暗', description: '客户反馈主卧效果图灯光偏暗，需要调整光源与明暗对比。', priority: 'medium', type: 'feedback', status: 'open', creatorId: creator, createdAt: now, updatedAt: now, tags: ['灯光', '效果图'], comments: []
    // });
    // const secondId = uuidv4();
    // list.push({
    //   id: secondId, projectId, title: '厨房柜体尺寸与现场不符', description: '现场复尺发现图纸尺寸与实际有偏差，需要同步调整。', priority: 'critical', type: 'bug', status: 'in_progress', creatorId: creator, createdAt: now, updatedAt: now, tags: ['复尺', '尺寸'], comments: []
    // });
    this.store.set(projectId, list);
  }

  // 内部：确保项目列表存在
  private ensure(projectId: string): ProjectIssue[] {
    if (!this.store.has(projectId)) {
      this.store.set(projectId, []);
    }
    return this.store.get(projectId)!;
  }
}