import {
  BillingType,
  Employee,
  Project,
  ProjectInternalStatus,
  QaResult,
  Task,
  TaskAssignment,
  TaskLifecycle,
  TaskStage,
} from '@prisma/client';
import { stageFromDb } from '../lib/stages';

const billingFromDb: Record<BillingType, string> = {
  Billable: 'Billable',
  NonBillable: 'Non-billable',
};

type TaskRow = Task & {
  assignments?: TaskAssignment[];
  assignee?: Pick<Employee, 'id' | 'name' | 'code' | 'avatarColor'> | null;
  project?: (Pick<Project, 'id' | 'code' | 'name' | 'color' | 'clientId'> & {
    client?: { id: string; code: string; name: string } | null;
  }) | null;
  internalStatus?: Pick<ProjectInternalStatus, 'id' | 'text' | 'color' | 'stage'> | null;
  _count?: { subtasks?: number; bugs?: number; notes?: number };
};

export function serializeTask(t: TaskRow) {
  return {
    id: t.id,
    code: t.code,
    title: t.title,
    projectId: t.projectId,
    project: t.project
      ? {
          id: t.project.id,
          code: t.project.code,
          name: t.project.name,
          color: t.project.color,
          clientId: t.project.clientId,
          client: t.project.client
            ? { id: t.project.client.id, code: t.project.client.code, name: t.project.client.name }
            : null,
        }
      : undefined,
    description: t.description,
    acceptanceCriteria: t.acceptanceCriteria,
    stage: stageFromDb(t.stage),
    lifecycle: t.lifecycle || TaskLifecycle.Open,
    internalStatusId: t.internalStatusId,
    internalStatus: t.internalStatus
      ? {
          id: t.internalStatus.id,
          text: t.internalStatus.text,
          color: t.internalStatus.color,
          stage: stageFromDb(t.internalStatus.stage),
        }
      : null,
    priority: t.priority,
    tags: t.tags,
    assigneeId: t.assigneeId,
    assignee: t.assignee
      ? {
          id: t.assignee.id,
          name: t.assignee.name,
          code: t.assignee.code,
          avatarColor: t.assignee.avatarColor,
        }
      : null,
    contributors: t.contributors,
    assignments: (t.assignments || []).map((a) => ({
      employeeId: a.employeeId,
      allocatedHours: Number(a.allocatedHours),
    })),
    allocatedHours: Number(t.allocatedHours),
    billingType: billingFromDb[t.billingType],
    startDate: t.startDate ? t.startDate.toISOString().slice(0, 10) : null,
    dueDate: t.dueDate ? t.dueDate.toISOString().slice(0, 10) : null,
    parentId: t.parentId,
    dependencies: t.dependencies,
    required: t.required,
    baAnalysisComplete: t.baAnalysisComplete,
    developmentComplete: t.developmentComplete,
    unitTestEvidence: t.unitTestEvidence,
    developerCompletionLog: t.developerCompletionLog,
    codeReviewApproved: t.codeReviewApproved,
    qaResult: t.qaResult,
    qaEvidence: t.qaEvidence,
    acceptanceSatisfied: t.acceptanceSatisfied,
    testerApproval: t.testerApproval,
    completionDate: t.completionDate
      ? t.completionDate.toISOString().slice(0, 10)
      : null,
    completedById: t.completedById,
    subtaskCount: t._count?.subtasks,
    bugCount: t._count?.bugs,
    createdAt: t.createdAt.toISOString(),
    updatedAt: t.updatedAt.toISOString(),
  };
}

export function billingToDb(label: string): BillingType {
  if (label === 'Non-billable' || label === 'NonBillable') return BillingType.NonBillable;
  return BillingType.Billable;
}

export function qaResultToDb(v: string | null | undefined): QaResult | null {
  if (!v) return null;
  if (v === 'Passed') return QaResult.Passed;
  if (v === 'Failed') return QaResult.Failed;
  if (v === 'Pending') return QaResult.Pending;
  return null;
}

export { TaskStage };
