import {
  Bug,
  BugAssignment,
  BugSeverity,
  BugStatus,
  Employee,
  Project,
  Task,
} from '@prisma/client';

const statusFromDb: Record<BugStatus, string> = {
  Open: 'Open',
  Assigned: 'Assigned',
  InProgress: 'In Progress',
  ReadyForRetest: 'Ready for Retest',
  Reopened: 'Reopened',
  Closed: 'Closed',
  Cancelled: 'Cancelled',
};

const statusToDbMap: Record<string, BugStatus> = {
  Open: BugStatus.Open,
  Assigned: BugStatus.Assigned,
  'In Progress': BugStatus.InProgress,
  InProgress: BugStatus.InProgress,
  'Ready for Retest': BugStatus.ReadyForRetest,
  ReadyForRetest: BugStatus.ReadyForRetest,
  Reopened: BugStatus.Reopened,
  Closed: BugStatus.Closed,
  Cancelled: BugStatus.Cancelled,
};

const severityFromDb: Record<BugSeverity, string> = {
  Critical: 'Critical',
  High: 'High',
  Medium: 'Medium',
  Low: 'Low',
};

const severityToDbMap: Record<string, BugSeverity> = {
  Critical: BugSeverity.Critical,
  High: BugSeverity.High,
  Medium: BugSeverity.Medium,
  Low: BugSeverity.Low,
};

type EmpPick = Pick<Employee, 'id' | 'name' | 'code' | 'avatarColor'>;

type BugRow = Bug & {
  assignee?: EmpPick | null;
  reporter?: EmpPick | null;
  assignments?: BugAssignment[];
  parentTask?: (Pick<Task, 'id' | 'code' | 'title' | 'projectId'> & {
    project?: Pick<Project, 'id' | 'code' | 'name' | 'color' | 'allowTypedEvidence'> | null;
  }) | null;
  attachments?: { id: string; kind: string | null }[];
};

export function statusFromBugDb(s: BugStatus): string {
  return statusFromDb[s] || s;
}

export function statusToBugDb(label: string): BugStatus {
  const v = statusToDbMap[label];
  if (!v) throw new Error('Invalid bug status: ' + label);
  return v;
}

export function severityToBugDb(label: string): BugSeverity {
  const v = severityToDbMap[label];
  if (!v) throw new Error('Invalid severity: ' + label);
  return v;
}

export function serializeBug(b: BugRow) {
  const parent = b.parentTask;
  const project = parent?.project;
  const assignments = (b.assignments || []).map((a) => ({
    employeeId: a.employeeId,
    allocatedHours: Number(a.allocatedHours),
  }));
  return {
    id: b.id,
    code: b.code,
    parentTaskId: b.parentTaskId,
    parentTask: parent
      ? {
          id: parent.id,
          code: parent.code,
          title: parent.title,
          projectId: parent.projectId,
        }
      : null,
    projectId: parent?.projectId || null,
    project: project
      ? {
          id: project.id,
          code: project.code,
          name: project.name,
          color: project.color,
          allowTypedEvidence: project.allowTypedEvidence,
        }
      : null,
    title: b.title,
    description: b.description,
    reproSteps: b.reproSteps,
    expected: b.expected,
    actual: b.actual,
    severity: severityFromDb[b.severity],
    priority: b.priority,
    assigneeId: b.assigneeId,
    assignee: b.assignee
      ? {
          id: b.assignee.id,
          name: b.assignee.name,
          code: b.assignee.code,
          avatarColor: b.assignee.avatarColor,
        }
      : null,
    reporterId: b.reporterId,
    reporter: b.reporter
      ? {
          id: b.reporter.id,
          name: b.reporter.name,
          code: b.reporter.code,
          avatarColor: b.reporter.avatarColor,
        }
      : null,
    assignments,
    allocatedHours: Number(b.allocatedHours),
    status: statusFromBugDb(b.status),
    resolutionNotes: b.resolutionNotes,
    blocking: b.blocking,
    unitTestEvidence: b.unitTestEvidence,
    createdAt: b.createdAt.toISOString(),
    updatedAt: b.updatedAt.toISOString(),
  };
}

export { BugStatus, BugSeverity };
