import { api } from '@/shared/utils/api';
import {
  isPaginatedResponse,
  type PaginatedResponse,
} from '@/shared/types/pagination.types';
import { isProjectSummary } from '@/features/projects/types/project.types';
import type {
  BurndownSeries,
  PortfolioGanttTimeline,
  ProjectGanttTimeline,
  CrossProjectDependency,
  PaginatedDependencies,
  PortfolioCoordinationDashboard,
  KanbanBoard,
  KanbanColumnKey,
  ProjectBoard,
  PortfolioDashboard,
  ProjectHealth,
  ProjectHealthExplanation,
  ProjectListFilters,
  ProjectMember,
  ProjectRisk,
  ProjectSprint,
  ProjectSummary,
  BacklogDashboard,
  CapacityPlanningDashboard,
  ProjectCommandCenter,
  ProjectEpic,
  ProjectWorkItem,
  RiskMatrixData,
  MilestoneTimelineItem,
  RiskMetrics,
  WorkItemDetail,
  AcceptanceCriterion,
  SprintCapacitySummary,
  VelocityData,
  WorkloadData,
} from '@/features/projects/types/project.types';

function unwrap<T>(payload: { data: T } | T): T {
  if (payload && typeof payload === 'object' && 'data' in payload) {
    return (payload as { data: T }).data;
  }
  return payload as T;
}

export async function fetchProjects(
  filters: ProjectListFilters,
): Promise<PaginatedResponse<ProjectSummary>> {
  const raw: unknown = await api.get('/projects', {
    params: {
      ...filters,
      include_progress: 1,
      include_health: 1,
    },
  });

  if (isPaginatedResponse(raw, isProjectSummary)) {
    return raw;
  }

  if (Array.isArray(raw) && raw.every(isProjectSummary)) {
    return {
      data: raw,
      meta: {
        current_page: 1,
        last_page: 1,
        per_page: raw.length,
        total: raw.length,
      },
    };
  }

  throw new Error('Invalid projects list response');
}

export async function fetchProject(id: string): Promise<ProjectSummary> {
  const { data } = await api.get<{ data: ProjectSummary }>(`/projects/${id}`);
  return unwrap(data);
}

export async function createProject(payload: Record<string, unknown>): Promise<ProjectSummary> {
  const { data } = await api.post<{ data: ProjectSummary }>('/projects', payload);
  return unwrap(data);
}

export async function updateProject(
  id: string,
  payload: Record<string, unknown>,
): Promise<ProjectSummary> {
  const { data } = await api.patch<{ data: ProjectSummary }>(`/projects/${id}`, payload);
  return unwrap(data);
}

export async function deleteProject(id: string): Promise<void> {
  await api.delete(`/projects/${id}`);
}

export async function archiveProject(id: string): Promise<ProjectSummary> {
  const { data } = await api.patch<{ data: ProjectSummary }>(`/projects/${id}/archive`);
  return unwrap(data);
}

export interface ClosureRule {
  key: string;
  label: string;
  pass: boolean;
  detail: string;
}

export interface ClosureChecklist {
  blockers: string[];
  details: Record<string, number>;
  rules?: ClosureRule[];
  health_level?: string;
  close_mode?: string;
}

export async function fetchProjectClosureChecklist(projectId: string): Promise<ClosureChecklist> {
  const { data } = await api.get<{ data: ClosureChecklist }>(
    `/projects/${projectId}/closure-checklist`,
  );
  return unwrap(data);
}

export async function fetchSprintClosureChecklist(
  projectId: string,
  sprintId: string,
): Promise<ClosureChecklist> {
  const { data } = await api.get<{ data: ClosureChecklist }>(
    `/projects/${projectId}/sprints/${sprintId}/closure-checklist`,
  );
  return unwrap(data);
}

export async function closeSprint(
  projectId: string,
  sprintId: string,
  closureOverrideReason?: string,
): Promise<ProjectSprint> {
  const { data } = await api.patch<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}/close`,
    { closure_override_reason: closureOverrideReason },
  );
  return unwrap(data);
}

export async function fetchProjectMembers(projectId: string): Promise<ProjectMember[]> {
  const { data } = await api.get<{ data: ProjectMember[] }>(`/projects/${projectId}/members`);
  return Array.isArray(data) ? data : unwrap(data);
}

export async function fetchBacklog(
  projectId: string,
  params?: Record<string, string>,
): Promise<BacklogDashboard> {
  const { data } = await api.get<{ data: BacklogDashboard }>(`/projects/${projectId}/backlog`, {
    params,
  });
  return unwrap(data);
}

export async function fetchEpics(projectId: string): Promise<ProjectEpic[]> {
  const { data } = await api.get<{ data: ProjectEpic[] }>(`/projects/${projectId}/epics`);
  return Array.isArray(data) ? data : unwrap(data);
}

export async function createEpic(
  projectId: string,
  payload: { name: string; color?: string; description?: string },
): Promise<ProjectEpic> {
  const { data } = await api.post<{ data: ProjectEpic }>(`/projects/${projectId}/epics`, payload);
  return unwrap(data);
}

export async function fetchWorkItem(
  projectId: string,
  ticketId: string,
): Promise<WorkItemDetail> {
  const { data } = await api.get<{ data: WorkItemDetail }>(
    `/projects/${projectId}/work-items/${ticketId}`,
  );
  return unwrap(data);
}

export async function updateWorkItem(
  projectId: string,
  ticketId: string,
  payload: Record<string, unknown>,
): Promise<WorkItemDetail> {
  const { data } = await api.patch<{ data: WorkItemDetail }>(
    `/projects/${projectId}/work-items/${ticketId}`,
    payload,
  );
  return unwrap(data);
}

export async function cloneWorkItem(projectId: string, ticketId: string): Promise<WorkItemDetail> {
  const { data } = await api.post<{ data: WorkItemDetail }>(
    `/projects/${projectId}/work-items/${ticketId}/clone`,
  );
  return unwrap(data);
}

export async function moveTicketToBacklog(
  projectId: string,
  ticketId: string,
): Promise<ProjectWorkItem> {
  const { data } = await api.patch<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/tickets/${ticketId}/move-to-backlog`,
  );
  return unwrap(data);
}

export async function removeTicketFromSprint(
  projectId: string,
  ticketId: string,
): Promise<ProjectWorkItem> {
  const { data } = await api.patch<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/tickets/${ticketId}/remove-from-sprint`,
  );
  return unwrap(data);
}

export async function createAcceptanceCriterion(
  projectId: string,
  ticketId: string,
  description: string,
): Promise<AcceptanceCriterion> {
  const { data } = await api.post<{ data: AcceptanceCriterion }>(
    `/projects/${projectId}/work-items/${ticketId}/acceptance-criteria`,
    { description },
  );
  return unwrap(data);
}

export async function updateAcceptanceCriterion(
  projectId: string,
  ticketId: string,
  criterionId: string,
  payload: Partial<Pick<AcceptanceCriterion, 'description' | 'is_completed'>>,
): Promise<AcceptanceCriterion> {
  const { data } = await api.patch<{ data: AcceptanceCriterion }>(
    `/projects/${projectId}/work-items/${ticketId}/acceptance-criteria/${criterionId}`,
    payload,
  );
  return unwrap(data);
}

export async function deleteAcceptanceCriterion(
  projectId: string,
  ticketId: string,
  criterionId: string,
): Promise<void> {
  await api.delete(
    `/projects/${projectId}/work-items/${ticketId}/acceptance-criteria/${criterionId}`,
  );
}

export async function reorderAcceptanceCriteria(
  projectId: string,
  ticketId: string,
  orderedIds: string[],
): Promise<void> {
  await api.patch(
    `/projects/${projectId}/work-items/${ticketId}/acceptance-criteria/reorder`,
    { ordered_ids: orderedIds },
  );
}

export async function createBacklogItem(
  projectId: string,
  payload: Record<string, unknown>,
): Promise<ProjectWorkItem> {
  const { data } = await api.post<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/backlog/tickets`,
    payload,
  );
  return unwrap(data);
}

export async function reorderBacklog(projectId: string, ticketIds: string[]): Promise<void> {
  await api.patch(`/projects/${projectId}/backlog/reorder`, { ticket_ids: ticketIds });
}

export async function bulkUpdateBacklog(
  projectId: string,
  payload: {
    ticket_ids: string[];
    ticket_priority_id?: string;
    current_assignee_id?: string;
    epic_id?: string;
    business_value?: number;
    labels?: string[];
  },
): Promise<{ updated_count: number }> {
  const response = await api.patch<{ message: string; updated_count: number }>(
    `/projects/${projectId}/backlog/bulk`,
    payload,
  );
  return { updated_count: response.updated_count };
}

export async function fetchSprints(projectId: string): Promise<ProjectSprint[]> {
  const { data } = await api.get<{ data: ProjectSprint[] }>(`/projects/${projectId}/sprints`);
  return Array.isArray(data) ? data : unwrap(data);
}

export async function fetchSprintTickets(
  projectId: string,
  sprintId: string,
): Promise<ProjectWorkItem[]> {
  const { data } = await api.get<{ data: ProjectWorkItem[] }>(
    `/projects/${projectId}/sprints/${sprintId}/tickets`,
  );
  return Array.isArray(data) ? data : unwrap(data);
}

export async function createSprint(
  projectId: string,
  payload: Record<string, unknown>,
): Promise<ProjectSprint> {
  const { data } = await api.post<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints`,
    payload,
  );
  return unwrap(data);
}

export async function updateSprint(
  projectId: string,
  sprintId: string,
  payload: Record<string, unknown>,
): Promise<ProjectSprint> {
  const { data } = await api.patch<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}`,
    payload,
  );
  return unwrap(data);
}

export async function deleteSprint(projectId: string, sprintId: string): Promise<void> {
  await api.delete(`/projects/${projectId}/sprints/${sprintId}`);
}

export async function startSprint(projectId: string, sprintId: string): Promise<ProjectSprint> {
  const { data } = await api.patch<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}/start`,
  );
  return unwrap(data);
}

export async function cancelSprint(projectId: string, sprintId: string): Promise<ProjectSprint> {
  const { data } = await api.patch<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}/cancel`,
  );
  return unwrap(data);
}

export async function archiveSprint(projectId: string, sprintId: string): Promise<ProjectSprint> {
  const { data } = await api.patch<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}/archive`,
  );
  return unwrap(data);
}

export async function restoreSprint(projectId: string, sprintId: string): Promise<ProjectSprint> {
  const { data } = await api.patch<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}/restore`,
  );
  return unwrap(data);
}

export async function duplicateSprint(projectId: string, sprintId: string): Promise<ProjectSprint> {
  const { data } = await api.post<{ data: ProjectSprint }>(
    `/projects/${projectId}/sprints/${sprintId}/duplicate`,
  );
  return unwrap(data);
}

export async function moveTicketToSprint(
  projectId: string,
  ticketId: string,
  sprintId: string,
): Promise<ProjectWorkItem> {
  if (!sprintId?.trim()) {
    throw new Error('Sprint id is required to move a work item into a sprint.');
  }

  const { data } = await api.patch<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/tickets/${ticketId}/move-to-sprint/${sprintId}`,
  );
  return unwrap(data);
}

export async function fetchProjectGantt(projectId: string): Promise<ProjectGanttTimeline> {
  const { data } = await api.get<{ data: ProjectGanttTimeline }>(`/projects/${projectId}/gantt`);
  return unwrap(data);
}

export async function fetchPortfolioGantt(params: {
  range?: 'year' | 'quarter' | 'month';
  year?: number;
  quarter?: number;
  month?: number;
  department_id?: string;
  owner_user_id?: string;
  owner_user_ids?: string[];
  status?: string;
  health_filter?: 'healthy' | 'at_risk' | 'critical';
  search?: string;
  active_only?: boolean;
  delayed_only?: boolean;
  blocked_only?: boolean;
  at_risk_only?: boolean;
}): Promise<PortfolioGanttTimeline> {
  const { owner_user_ids, ...rest } = params;
  const { data } = await api.get<{ data: PortfolioGanttTimeline }>('/portfolio/gantt', {
    params: {
      ...rest,
      owner_user_ids: owner_user_ids?.length ? owner_user_ids.join(',') : undefined,
    },
  });
  return unwrap(data);
}

/** @deprecated Use fetchPortfolioGantt — alias for /projects/gantt */
export async function fetchGlobalGantt(params: {
  range: 'year' | 'quarter' | 'month';
  year: number;
  quarter?: number;
  month?: number;
}): Promise<PortfolioGanttTimeline> {
  const { data } = await api.get<{ data: PortfolioGanttTimeline }>('/projects/gantt', {
    params,
  });
  return unwrap(data);
}

export async function fetchCrossProjectDependencies(): Promise<CrossProjectDependency[]> {
  const { data } = await api.get<{ data: CrossProjectDependency[] }>('/portfolio/dependencies');
  return unwrap(data);
}

export async function fetchPortfolioCoordinationDashboard(): Promise<PortfolioCoordinationDashboard> {
  const { data } = await api.get<{ data: PortfolioCoordinationDashboard }>('/portfolio/coordination');
  return unwrap(data);
}

export async function fetchPortfolioDependenciesRegistry(params?: {
  page?: number;
  per_page?: number;
  filter?: string;
  search?: string;
  sort?: string;
  direction?: 'asc' | 'desc';
}): Promise<PaginatedDependencies> {
  return api.get<PaginatedDependencies>('/portfolio/dependencies', {
    params: { paginate: 1, ...params },
  });
}

export async function updatePortfolioDependency(
  id: string,
  payload: {
    action?: 'resolve' | 'escalate';
    status?: string;
    owner_user_id?: string | null;
    notes?: string | null;
    is_critical?: boolean;
  },
): Promise<CrossProjectDependency> {
  const { data } = await api.patch<{ data: CrossProjectDependency }>(
    `/portfolio/dependencies/${id}`,
    payload,
  );
  return unwrap(data);
}

export interface ProjectDependencyRow {
  id: string;
  source_ticket_id: string;
  target_ticket_id: string;
  type: string;
  resolved: boolean;
  source?: {
    id: string;
    ticket_number: string;
    subject: string;
    status?: string;
    is_done?: boolean;
  } | null;
  target?: {
    id: string;
    ticket_number: string;
    subject: string;
    status?: string;
    is_done?: boolean;
  } | null;
}

export interface ProjectDependenciesDashboard {
  metrics: {
    total: number;
    blocking: number;
    unresolved: number;
    blocked_work: number;
  };
  items: ProjectDependencyRow[];
}

export async function fetchProjectDependencies(
  projectId: string,
): Promise<ProjectDependenciesDashboard> {
  const { data } = await api.get<{ data: ProjectDependenciesDashboard }>(
    `/projects/${projectId}/dependencies`,
  );
  return unwrap(data);
}

export interface ReportHubCardData {
  key: string;
  metric: string;
}

export async function fetchReportsHub(projectId: string): Promise<ReportHubCardData[]> {
  const { data } = await api.get<{ data: ReportHubCardData[] }>(
    `/projects/${projectId}/reports-hub`,
  );
  return unwrap(data);
}

export async function createProjectDependency(
  projectId: string,
  payload: {
    source_ticket_id: string;
    target_ticket_id: string;
    dependency_type?: string;
    notes?: string;
    reason?: string;
    lag_days?: number;
  },
): Promise<void> {
  await api.post(`/projects/${projectId}/dependencies`, payload);
}

export async function addProjectMember(
  projectId: string,
  payload: { user_id: string; role: string },
): Promise<void> {
  await api.post(`/projects/${projectId}/members`, payload);
}

export async function updateProjectMember(
  projectId: string,
  userId: string,
  payload: { role: string },
): Promise<void> {
  await api.patch(`/projects/${projectId}/members/${userId}`, payload);
}

export async function removeProjectMember(projectId: string, userId: string): Promise<void> {
  await api.delete(`/projects/${projectId}/members/${userId}`);
}

export async function fetchProjectBoard(
  projectId: string,
  filters?: Record<string, unknown>,
): Promise<ProjectBoard> {
  const { data } = await api.get<{ data: ProjectBoard }>(`/projects/${projectId}/board`, {
    params: filters,
  });
  return unwrap(data);
}

export async function moveBoardTicket(
  projectId: string,
  ticketId: string,
  payload: {
    kanban_column?: string;
    ticket_status_id?: string;
    sprint_id?: string;
    dependency_override_reason?: string;
  },
): Promise<ProjectWorkItem> {
  const { data } = await api.patch<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/board/tickets/${ticketId}`,
    payload,
  );
  return unwrap(data);
}

/** @deprecated Legacy Kanban API — prefer fetchProjectBoard */
export async function fetchKanban(projectId: string): Promise<KanbanBoard> {
  const { data } = await api.get<{ data: KanbanBoard }>(`/projects/${projectId}/kanban`);
  return unwrap(data);
}

export async function fetchSprintBoard(
  projectId: string,
  filters?: Record<string, unknown>,
): Promise<ProjectBoard> {
  const { data } = await api.get<{ data: ProjectBoard }>(`/projects/${projectId}/sprint-board`, {
    params: filters,
  });
  return unwrap(data);
}

export async function moveKanbanTicket(
  projectId: string,
  ticketId: string,
  payload: { kanban_column: KanbanColumnKey; sprint_id?: string | null },
): Promise<ProjectWorkItem> {
  const { data } = await api.patch<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/kanban/tickets/${ticketId}`,
    payload,
  );
  return unwrap(data);
}

export async function fetchBurndown(projectId: string): Promise<BurndownSeries> {
  const { data } = await api.get<{ data: BurndownSeries }>(`/projects/${projectId}/burndown`);
  return unwrap(data);
}

export async function fetchSprintBurndown(
  projectId: string,
  sprintId: string,
): Promise<BurndownSeries> {
  const { data } = await api.get<{ data: BurndownSeries }>(
    `/projects/${projectId}/sprints/${sprintId}/burndown`,
  );
  return unwrap(data);
}

export async function fetchVelocity(projectId: string): Promise<VelocityData> {
  const { data } = await api.get<{ data: VelocityData }>(`/projects/${projectId}/velocity`);
  return unwrap(data);
}

export async function fetchProjectHealth(projectId: string): Promise<ProjectHealth> {
  const { data } = await api.get<{ data: ProjectHealth }>(`/projects/${projectId}/health`);
  return unwrap(data);
}

export async function fetchProjectHealthExplanation(
  projectId: string,
): Promise<ProjectHealthExplanation> {
  const { data } = await api.get<{ data: ProjectHealthExplanation }>(
    `/projects/${projectId}/health-explanation`,
  );
  return unwrap(data);
}

export async function fetchWorkload(projectId: string): Promise<WorkloadData> {
  const { data } = await api.get<{ data: WorkloadData }>(`/projects/${projectId}/workload`);
  return unwrap(data);
}

export async function fetchSprintCapacity(
  projectId: string,
  sprintId: string,
): Promise<SprintCapacitySummary> {
  const { data } = await api.get<{ data: SprintCapacitySummary }>(
    `/projects/${projectId}/sprints/${sprintId}/capacity`,
  );
  return unwrap(data);
}

export async function fetchCapacityPlanning(
  projectId: string,
  sprintId?: string,
): Promise<CapacityPlanningDashboard> {
  const { data } = await api.get<{ data: CapacityPlanningDashboard }>(
    `/projects/${projectId}/capacity-planning`,
    { params: sprintId ? { sprint_id: sprintId } : undefined },
  );
  return unwrap(data);
}

export async function syncSprintCapacityAllocations(
  projectId: string,
  sprintId: string,
  allocations: { user_id: string; capacity_md: number }[],
): Promise<CapacityPlanningDashboard> {
  const { data } = await api.put<{ data: CapacityPlanningDashboard }>(
    `/projects/${projectId}/sprints/${sprintId}/capacity-allocations`,
    { allocations },
  );
  return unwrap(data);
}

export async function fetchProjectCommandCenter(projectId: string): Promise<ProjectCommandCenter> {
  const { data } = await api.get<{ data: ProjectCommandCenter }>(
    `/projects/${projectId}/command-center`,
  );
  return unwrap(data);
}

export async function fetchRisks(
  projectId: string,
): Promise<{ risks: ProjectRisk[]; metrics: RiskMetrics }> {
  const response = await api.get<{ data: ProjectRisk[]; metrics: RiskMetrics }>(
    `/projects/${projectId}/risks`,
  );
  return { risks: response.data, metrics: response.metrics };
}

export async function createRisk(
  projectId: string,
  payload: Record<string, unknown>,
): Promise<ProjectRisk> {
  const { data } = await api.post<{ data: ProjectRisk }>(`/projects/${projectId}/risks`, payload);
  return unwrap(data);
}

export async function fetchRiskMatrix(projectId: string): Promise<RiskMatrixData> {
  const { data } = await api.get<{ data: RiskMatrixData }>(
    `/projects/${projectId}/risks/matrix`,
  );
  return unwrap(data);
}

export async function fetchRiskHistory(projectId: string, riskId: string) {
  const { data } = await api.get<{
    data: Array<{
      id: string;
      field_changed: string;
      old_value: string | null;
      new_value: string | null;
      changed_by: string;
      changed_at: string;
    }>;
  }>(`/projects/${projectId}/risks/${riskId}/history`);
  return unwrap(data);
}

export async function fetchBlockedDependencyChains(projectId: string) {
  const { data } = await api.get<{
    data: {
      chains: Array<{
        dependency_id: string;
        type: string;
        source: { id: string; ticket_number: string; subject: string };
        target: { id: string; ticket_number: string; subject: string };
      }>;
      count: number;
    };
  }>(`/projects/${projectId}/dependencies/blocked-chains`);
  return unwrap(data);
}

export async function fetchMilestoneTimeline(projectId: string): Promise<MilestoneTimelineItem[]> {
  const { data } = await api.get<{ data: MilestoneTimelineItem[] }>(
    `/projects/${projectId}/milestones/timeline`,
  );
  return unwrap(data);
}

export async function fetchMilestones(projectId: string) {
  const res = await api.get<{
    data: Array<{ id: string; name: string; due_date: string; status: string }>;
    metrics: { upcoming: number; overdue: number; completed: number };
  }>(`/projects/${projectId}/milestones`);
  return { milestones: res.data, metrics: res.metrics };
}

export async function createMilestone(projectId: string, payload: Record<string, unknown>) {
  const { data } = await api.post<{ data: unknown }>(`/projects/${projectId}/milestones`, payload);
  return unwrap(data);
}

export async function completeMilestone(projectId: string, milestoneId: string) {
  const { data } = await api.patch<{ data: unknown }>(
    `/projects/${projectId}/milestones/${milestoneId}/complete`,
  );
  return unwrap(data);
}

export async function fetchPortfolio(filters?: Record<string, unknown>): Promise<PortfolioDashboard> {
  const { data } = await api.get<{ data: PortfolioDashboard }>('/projects/portfolio', {
    params: filters,
  });
  return unwrap(data);
}

export interface WorkItemSearchHit {
  id: string;
  ticket_number: string;
  subject: string;
  label: string;
}

export async function searchProjectWorkItems(
  projectId: string,
  q: string,
  excludeId?: string,
): Promise<WorkItemSearchHit[]> {
  const { data } = await api.get<{ data: WorkItemSearchHit[] }>(
    `/projects/${projectId}/work-items/search`,
    { params: { q, exclude_id: excludeId } },
  );
  return Array.isArray(data) ? data : unwrap(data);
}

export interface TicketDependencyView {
  id: string;
  dependency_type: string;
  ticket: {
    id: string;
    ticket_number: string;
    subject: string;
    is_done: boolean;
    status?: { name_en: string; is_closed: boolean };
  } | null;
}

export async function fetchTicketDependencies(ticketId: string): Promise<{
  blocked_by: TicketDependencyView[];
  blocking: TicketDependencyView[];
  warnings: TicketDependencyView[];
}> {
  const { data } = await api.get<{
    data: {
      blocked_by: TicketDependencyView[];
      blocking: TicketDependencyView[];
      warnings: TicketDependencyView[];
    };
  }>(`/tickets/${ticketId}/dependencies`);
  return unwrap(data);
}

export async function addTicketDependency(
  ticketId: string,
  sourceTicketId: string,
): Promise<void> {
  await api.post(`/tickets/${ticketId}/dependencies`, {
    source_ticket_id: sourceTicketId,
    dependency_type: 'FS',
  });
}

export async function removeTicketDependency(
  ticketId: string,
  dependencyId: string,
): Promise<void> {
  await api.delete(`/tickets/${ticketId}/dependencies/${dependencyId}`);
}

export async function fetchWorkItemSubtasks(
  projectId: string,
  ticketId: string,
): Promise<ProjectWorkItem[]> {
  const { data } = await api.get<{ data: ProjectWorkItem[] }>(
    `/projects/${projectId}/work-items/${ticketId}/subtasks`,
  );
  return Array.isArray(data) ? data : unwrap(data);
}

export async function createWorkItemSubtask(
  projectId: string,
  ticketId: string,
  payload: Record<string, unknown>,
): Promise<ProjectWorkItem> {
  const { data } = await api.post<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/work-items/${ticketId}/subtasks`,
    payload,
  );
  return unwrap(data);
}

export async function updateWorkItemSubtask(
  projectId: string,
  ticketId: string,
  subtaskId: string,
  payload: Record<string, unknown>,
): Promise<ProjectWorkItem> {
  const { data } = await api.patch<{ data: ProjectWorkItem }>(
    `/projects/${projectId}/work-items/${ticketId}/subtasks/${subtaskId}`,
    payload,
  );
  return unwrap(data);
}

export async function deleteWorkItemSubtask(
  projectId: string,
  ticketId: string,
  subtaskId: string,
): Promise<void> {
  await api.delete(`/projects/${projectId}/work-items/${ticketId}/subtasks/${subtaskId}`);
}

export interface AgileComment {
  id: string;
  body: string;
  created_at: string;
  user?: { id: string; name: string };
}

export async function fetchWorkItemComments(ticketId: string): Promise<AgileComment[]> {
  const res = await api.get<{ data: AgileComment[] } | AgileComment[]>(
    `/tickets/${ticketId}/replies`,
  );
  const raw = res as { data?: AgileComment[] };
  return Array.isArray(raw.data) ? raw.data : (Array.isArray(res) ? res : []);
}

export async function addWorkItemComment(ticketId: string, body: string): Promise<AgileComment> {
  const { data } = await api.post<{ data: AgileComment }>(`/tickets/${ticketId}/replies`, { body });
  return unwrap(data);
}

export interface AuditLogEntry {
  id: string;
  event: string;
  created_at: string;
  user?: { name: string };
  metadata?: Record<string, unknown>;
  old_values?: Record<string, unknown>;
  new_values?: Record<string, unknown>;
}

export async function fetchWorkItemHistory(ticketId: string): Promise<AuditLogEntry[]> {
  const res = await api.get<{ data: AuditLogEntry[] }>(
    `/audit-logs/model/ticket/${ticketId}`,
    { params: { per_page: 50 } },
  );
  const payload = res as { data?: AuditLogEntry[] };
  if (Array.isArray(payload.data)) {
    return payload.data;
  }
  const paginated = res as { data?: { data?: AuditLogEntry[] } };
  return paginated.data?.data ?? [];
}

/** @alias searchProjectWorkItems */
export const searchWorkItems = searchProjectWorkItems;

export async function updateRisk(
  projectId: string,
  riskId: string,
  payload: Record<string, unknown>,
): Promise<ProjectRisk> {
  const { data } = await api.patch<{ data: ProjectRisk }>(
    `/projects/${projectId}/risks/${riskId}`,
    payload,
  );
  return unwrap(data);
}

export interface ExecutiveDashboard {
  project: {
    id: string;
    name: string;
    key: string;
    status: string;
    start_date: string | null;
    due_date: string | null;
    is_overdue: boolean;
    completion_percent: number;
  };
  health: {
    score: number;
    level: string;
    message?: string | null;
    ready?: boolean;
    explanation: string[];
    breakdown: {
      work_items: {
        total: number;
        completed: number;
        blocked: number;
        overdue: number;
        completion_rate: number;
      };
      risks: {
        open: number;
        critical: number;
        total: number;
      };
      milestones: {
        total: number;
        completed: number;
        overdue: number;
      };
      dependencies: {
        total: number;
        blocking: number;
      };
    };
  };
  risk_summary: {
    total: number;
    open: number;
    critical: number;
    mitigated: number;
    closed: number;
    by_category: Record<string, number>;
    by_status: Record<string, number>;
    matrix: Array<{ probability: number; impact: number; score: number; count: number }>;
    total_risk_score: number;
  };
  risk_trend: Array<{ date: string; score: number; level: string }>;
  velocity: {
    current: number;
    trend: string;
    history: Array<{
      sprint_id: string;
      sprint_name: string;
      completed_at: string;
      velocity_md: number;
      completed_items: number;
    }>;
  };
  burndown: {
    sprint_id: string;
    sprint_name: string;
    start_date: string;
    due_date: string;
    current_remaining_md: number | null;
    expected_remaining_md: number | null;
    variance_percent: number | null;
    status: string;
    chart_data: {
      actual: Array<{ date: string; value: number }>;
      ideal: Array<{ date: string; value: number }>;
    };
  } | null;
  blocked_work: {
    count: number;
    items: Array<{
      id: string;
      ticket_number: string;
      subject: string;
      blocked_by: Array<{
        id: string;
        ticket_number: string;
        subject: string;
        type: string;
      }>;
    }>;
  };
  open_dependencies: {
    count: number;
    items: Array<{
      id: string;
      type: string;
      source: { id: string; ticket_number: string; subject: string };
      target: { id: string; ticket_number: string; subject: string };
    }>;
  };
  upcoming_milestones: Array<{
    id: string;
    name: string;
    due_date: string;
    status: string;
    is_overdue: boolean;
    days_until: number;
    progress_percent: number;
  }>;
  sprint_status: {
    has_active: boolean;
    sprint?: {
      id: string;
      name: string;
      start_date: string;
      due_date: string;
      goal: string | null;
    };
    health?: {
      status: string;
      score: number;
      classification?: string;
      breakdown?: Record<
        string,
        { score: number; weight: number; weighted_score: number; explanation: string }
      >;
      recommendations?: string[];
    };
    progress?: {
      time_percent: number;
      days_remaining: number;
      is_overdue: boolean;
    };
    items?: {
      total: number;
      completed: number;
      in_progress: number;
      todo: number;
    };
    next_sprint?: {
      id: string;
      name: string;
      start_date: string;
    } | null;
  } | null;
  capacity_utilization: {
    total_capacity_md: number;
    assigned_md: number;
    remaining_capacity_md: number;
    utilization_percent: number;
    status: string;
    team_members: number;
    overloaded_members: number;
  } | null;
  forecast: {
    can_forecast: boolean;
    reason?: string;
    remaining_work_md?: number;
    average_velocity_md?: number;
    sprints_remaining?: number;
    days_remaining?: number;
    forecast_date?: string;
    project_due_date?: string | null;
    is_late?: boolean;
    days_variance?: number | null;
  };
  attention_items: Array<{
    type: string;
    severity: string;
    title: string;
    description: string;
    entity_id: string;
    action: string;
  }>;
  projects_at_risk: {
    is_at_risk: boolean;
    health_level: string;
    health_score: number | null;
    indicators: Array<{ type: string; message: string; severity: string }>;
  };
  capacity_bottlenecks: {
    has_bottlenecks: boolean;
    overloaded_members: Array<{
      user_id: string;
      name: string;
      utilization_percent: number;
      overload_md: number;
    }>;
    total_overload_md: number;
    recommendation?: string;
  };
  critical_dependencies: {
    total_blocking: number;
    critical_count: number;
    dependencies: Array<{
      id: string;
      type: string;
      blocker: { id: string; ticket_number: string; subject: string; due_date: string | null };
      blocked: { id: string; ticket_number: string; subject: string; due_date: string | null };
    }>;
  };
  delayed_milestones: Array<{ id: string; name: string; due_date: string; days_overdue: number }>;
  upcoming_deadlines: Array<{ type: string; name: string; due_date: string; days_until: number }>;
  forecast_accuracy: {
    can_calculate: boolean;
    reason?: string;
    average_accuracy_percent?: number;
    sprints_analyzed?: number;
  };
}

export async function fetchExecutiveDashboard(projectId: string): Promise<ExecutiveDashboard> {
  const { data } = await api.get<{ data: ExecutiveDashboard }>(
    `/projects/${projectId}/executive-dashboard`,
  );
  return unwrap(data);
}

export interface SprintParticipant {
  id: string;
  project_sprint_id: string;
  user_id: string;
  capacity_md: number | null;
  user?: {
    id: string;
    name: string;
    email: string;
    avatar_url: string | null;
    departments?: Array<{ id: string; name: string; code: string }>;
  };
  added_by?: { id: string; name: string; email: string } | null;
  created_at: string;
  updated_at: string;
}

export interface SprintParticipantWithWorkload extends SprintParticipant {
  assigned_md: number;
  remaining_md: number;
  utilization_percent: number;
  assigned_items: number;
  completed_items: number;
  health: 'green' | 'yellow' | 'red';
}

export async function fetchSprintParticipants(
  projectId: string,
  sprintId: string,
): Promise<SprintParticipant[]> {
  const { data } = await api.get<{ data: SprintParticipant[] }>(
    `/projects/${projectId}/sprints/${sprintId}/participants`,
  );
  return unwrap(data);
}

export async function addSprintParticipant(
  projectId: string,
  sprintId: string,
  userId: string,
  capacityMd?: number | null,
): Promise<SprintParticipant> {
  const { data } = await api.post<{ data: SprintParticipant }>(
    `/projects/${projectId}/sprints/${sprintId}/participants`,
    { user_id: userId, capacity_md: capacityMd },
  );
  return unwrap(data);
}

export async function updateParticipantCapacity(
  projectId: string,
  sprintId: string,
  userId: string,
  capacityMd: number | null,
): Promise<SprintParticipant> {
  const { data } = await api.patch<{ data: SprintParticipant }>(
    `/projects/${projectId}/sprints/${sprintId}/participants/${userId}`,
    { capacity_md: capacityMd },
  );
  return unwrap(data);
}

export async function removeSprintParticipant(
  projectId: string,
  sprintId: string,
  userId: string,
): Promise<void> {
  await api.delete(`/projects/${projectId}/sprints/${sprintId}/participants/${userId}`);
}

export async function syncSprintParticipants(
  projectId: string,
  sprintId: string,
  participants: Array<{ user_id: string; capacity_md?: number | null }>,
): Promise<SprintParticipant[]> {
  const { data } = await api.put<{ data: SprintParticipant[] }>(
    `/projects/${projectId}/sprints/${sprintId}/participants/sync`,
    { participants },
  );
  return unwrap(data);
}

export interface EligibleMember {
  user_id: string;
  role: string;
  user: {
    id: string;
    name: string;
    email: string;
    avatar_url: string | null;
  };
}

export async function fetchEligibleParticipants(
  projectId: string,
  sprintId: string,
  search?: string,
): Promise<EligibleMember[]> {
  const { data } = await api.get<{ data: EligibleMember[] }>(
    `/projects/${projectId}/sprints/${sprintId}/participants/eligible`,
    { params: { search } },
  );
  return unwrap(data);
}

export interface AssignmentRecommendation {
  user_id: string;
  name: string;
  email: string;
  avatar_url: string | null;
  match_score: number;
  department: string | null;
  is_overloaded: boolean;
  utilization_percent: number;
  capacity_md: number;
  assigned_md: number;
  remaining_md: number;
  factors: Record<string, { score: number; label: string }>;
  warnings: string[];
}

export async function fetchAssignmentRecommendations(
  projectId: string,
  options?: {
    sprintId?: string;
    ticketId?: string;
    activeSprint?: boolean;
    limit?: number;
  },
): Promise<AssignmentRecommendation[]> {
  const { data } = await api.get<{ data: AssignmentRecommendation[] }>(
    `/projects/${projectId}/assignment-recommendations`,
    {
      params: {
        sprint_id: options?.sprintId,
        ticket_id: options?.ticketId,
        active_sprint: options?.activeSprint,
        limit: options?.limit,
      },
    },
  );
  return unwrap(data);
}

export interface TeamAnalytics {
  top_overloaded: Array<{
    user_id: string;
    name: string;
    utilization_percent: number;
    assigned_md: number;
    capacity_md: number;
    overload_md: number;
  }>;
  top_underutilized: Array<{
    user_id: string;
    name: string;
    utilization_percent: number;
    assigned_md: number;
    capacity_md: number;
    remaining_md: number;
  }>;
  team_health_score: {
    score: number | null;
    status: string;
    factors: {
      healthy_members: number;
      near_capacity: number;
      overloaded: number;
      total_members: number;
      avg_utilization: number;
    };
  };
  capacity_forecast: {
    total_capacity_md: number;
    total_assigned_md: number;
    remaining_capacity_md: number;
    avg_velocity_md: number;
    can_sustain_velocity: boolean | null;
    forecast_message: string;
  };
  bus_factor: {
    factor: number | null;
    risk_level: string;
    key_contributors: Array<{
      user_id: string;
      name: string;
      items: number;
      percentage: number;
    }>;
  };
  delivery_reliability: {
    reliability_percent: number | null;
    trend: string;
    sprints_analyzed: number;
    history: Array<{
      sprint_id: string;
      sprint_name: string;
      completed_at: string;
      completion_rate: number;
      total_items: number;
      completed_items: number;
    }>;
  };
  utilization_trend: {
    data: Array<{
      sprint_id: string;
      sprint_name: string;
      start_date: string;
      utilization_percent: number;
      capacity_md: number;
      assigned_md: number;
    }>;
    avg_utilization: number;
  };
  contribution_distribution: {
    distribution: Array<{
      user_id: string;
      name: string;
      items_count: number;
      work_md: number;
      percentage: number;
    }>;
    gini_coefficient: number | null;
    is_balanced: boolean;
  };
}

export async function fetchTeamAnalytics(projectId: string): Promise<TeamAnalytics> {
  const { data } = await api.get<{ data: TeamAnalytics }>(
    `/projects/${projectId}/team-analytics`,
  );
  return unwrap(data);
}
