/**
 * 모선 워크플로우 API 클라이언트.
 * - 후보/리뷰: 자체 백엔드 (자체 DB의 운영자 결정)
 * - 향후: iran 백엔드의 후보 데이터와 조합 (HYBRID)
 */

const API_BASE = import.meta.env.VITE_API_URL ?? '/api';

export interface ParentResolution {
  id: number;
  groupKey: string;
  subClusterId: number;
  status: 'UNRESOLVED' | 'MANUAL_CONFIRMED' | 'REVIEW_REQUIRED';
  selectedParentMmsi: string | null;
  rejectedCandidateMmsi: string | null;
  approvedBy: string | null;
  approvedAt: string | null;
  rejectedAt: string | null;
  manualComment: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface CandidateExclusion {
  id: number;
  scopeType: 'GROUP' | 'GLOBAL';
  groupKey: string | null;
  subClusterId: number | null;
  excludedMmsi: string;
  reason: string | null;
  actor: string | null;
  actorAcnt: string | null;
  createdAt: string;
  releasedAt: string | null;
  releasedByAcnt: string | null;
}

export interface LabelSession {
  id: number;
  groupKey: string;
  subClusterId: number;
  labelParentMmsi: string;
  status: 'ACTIVE' | 'CANCELLED' | 'COMPLETED';
  activeFrom: string;
  activeUntil: string | null;
  createdByAcnt: string | null;
  cancelledAt: string | null;
  cancelReason: string | null;
  createdAt: string;
}

export interface ReviewLog {
  id: number;
  groupKey: string;
  subClusterId: number | null;
  action: string;
  selectedParentMmsi: string | null;
  actorAcnt: string | null;
  comment: string | null;
  createdAt: string;
}

export interface PageResponse<T> {
  content: T[];
  totalElements: number;
  totalPages: number;
  number: number;
  size: number;
}

async function apiRequest<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(`${API_BASE}${path}`, {
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    ...init,
  });
  if (!res.ok) {
    let errBody = '';
    try { errBody = await res.text(); } catch { /* ignore */ }
    throw new Error(`API ${res.status}: ${path} ${errBody}`);
  }
  return res.json();
}

// ============================================================================
// Resolution
// ============================================================================

export function fetchReviewList(status?: string, page = 0, size = 20) {
  const qs = new URLSearchParams();
  if (status) qs.set('status', status);
  qs.set('page', String(page));
  qs.set('size', String(size));
  return apiRequest<PageResponse<ParentResolution>>(`/parent-inference/review?${qs}`);
}

export function reviewParent(
  groupKey: string,
  subClusterId: number,
  payload: { action: 'CONFIRM' | 'REJECT' | 'RESET'; selectedParentMmsi?: string; comment?: string },
) {
  return apiRequest<ParentResolution>(
    `/parent-inference/groups/${encodeURIComponent(groupKey)}/${subClusterId}/review`,
    { method: 'POST', body: JSON.stringify(payload) },
  );
}

// ============================================================================
// Exclusions
// ============================================================================

export function fetchExclusions(scopeType?: 'GROUP' | 'GLOBAL', page = 0, size = 20) {
  const qs = new URLSearchParams();
  if (scopeType) qs.set('scopeType', scopeType);
  qs.set('page', String(page));
  qs.set('size', String(size));
  return apiRequest<PageResponse<CandidateExclusion>>(`/parent-inference/exclusions?${qs}`);
}

export function excludeForGroup(
  groupKey: string,
  subClusterId: number,
  payload: { excludedMmsi: string; reason?: string },
) {
  return apiRequest<CandidateExclusion>(
    `/parent-inference/groups/${encodeURIComponent(groupKey)}/${subClusterId}/exclusions`,
    { method: 'POST', body: JSON.stringify(payload) },
  );
}

export function excludeGlobal(payload: { excludedMmsi: string; reason?: string }) {
  return apiRequest<CandidateExclusion>(`/parent-inference/exclusions/global`, {
    method: 'POST',
    body: JSON.stringify(payload),
  });
}

export function releaseExclusion(exclusionId: number, reason?: string) {
  return apiRequest<CandidateExclusion>(`/parent-inference/exclusions/${exclusionId}/release`, {
    method: 'POST',
    body: JSON.stringify({ reason }),
  });
}

// ============================================================================
// Label Sessions
// ============================================================================

export function fetchLabelSessions(status?: string, page = 0, size = 20) {
  const qs = new URLSearchParams();
  if (status) qs.set('status', status);
  qs.set('page', String(page));
  qs.set('size', String(size));
  return apiRequest<PageResponse<LabelSession>>(`/parent-inference/label-sessions?${qs}`);
}

export function createLabelSession(
  groupKey: string,
  subClusterId: number,
  payload: { labelParentMmsi: string; anchorSnapshot?: Record<string, unknown> },
) {
  return apiRequest<LabelSession>(
    `/parent-inference/groups/${encodeURIComponent(groupKey)}/${subClusterId}/label-sessions`,
    { method: 'POST', body: JSON.stringify(payload) },
  );
}

export function cancelLabelSession(sessionId: number, reason?: string) {
  return apiRequest<LabelSession>(`/parent-inference/label-sessions/${sessionId}/cancel`, {
    method: 'POST',
    body: JSON.stringify({ reason }),
  });
}

// ============================================================================
// Review Logs (도메인 액션 이력)
// ============================================================================

export function fetchReviewLogs(groupKey?: string, page = 0, size = 50) {
  const qs = new URLSearchParams();
  if (groupKey) qs.set('groupKey', groupKey);
  qs.set('page', String(page));
  qs.set('size', String(size));
  return apiRequest<PageResponse<ReviewLog>>(`/parent-inference/review-logs?${qs}`);
}
