/**
 * 결재함 서버 액션
 *
 * API Endpoints:
 * - GET /api/v1/approvals/inbox - 결재함 목록 조회
 * - GET /api/v1/approvals/inbox/summary - 결재함 통계
 * - POST /api/v1/approvals/{id}/approve - 승인 처리
 * - POST /api/v1/approvals/{id}/reject - 반려 처리
 */

'use server';


import { executeServerAction, type ActionResult } from '@/lib/api/execute-server-action';
import { buildApiUrl } from '@/lib/api/query-params';
import type { PaginatedApiResponse } from '@/lib/api/types';
import type { ApprovalRecord, ApprovalType, ApprovalStatus } from './types';

// ============================================
// API 응답 타입 정의
// ============================================

interface InboxSummary {
  total: number;
  requested: number;
  scheduled: number;
  completed: number;
  rejected: number;
}

interface InboxApiData {
  id: number;
  document_number: string;
  title: string;
  status: string;
  form?: { id: number; name: string; code: string; category: string };
  drafter?: { id: number; name: string; position?: string; department?: { name: string } };
  steps?: InboxStepApiData[];
  created_at: string;
  updated_at: string;
}

interface InboxStepApiData {
  id: number;
  step_order: number;
  step_type: string;
  approver_id: number;
  approver?: { id: number; name: string; position?: string; department?: { name: string } };
  status: string;
  processed_at?: string;
  comment?: string;
}

// ============================================
// 헬퍼 함수
// ============================================

function mapApiStatus(apiStatus: string): ApprovalStatus {
  const statusMap: Record<string, ApprovalStatus> = {
    'requested': 'requested', 'scheduled': 'scheduled', 'completed': 'completed', 'rejected': 'rejected',
    // legacy fallback
    'pending': 'requested', 'approved': 'completed',
  };
  return statusMap[apiStatus] || 'requested';
}

function mapTabToApiStatus(tabStatus: string): string | undefined {
  const statusMap: Record<string, string> = {
    'requested': 'requested', 'scheduled': 'scheduled', 'completed': 'completed', 'rejected': 'rejected',
  };
  return statusMap[tabStatus];
}

function mapApprovalType(formCategory?: string): ApprovalType {
  const typeMap: Record<string, ApprovalType> = {
    'expense_report': 'expense_report', 'proposal': 'proposal', 'expense_estimate': 'expense_estimate', '문서': 'document', 'document': 'document',
  };
  return typeMap[formCategory || ''] || 'proposal';
}

function mapDocumentStatus(status: string): string {
  const statusMap: Record<string, string> = {
    'pending': '진행중', 'approved': '완료', 'rejected': '반려',
    'cancelled': '회수', 'on_hold': '보류',
  };
  return statusMap[status] || '진행중';
}

function transformApiToFrontend(data: InboxApiData): ApprovalRecord {
  const currentStep = data.steps?.find(s => s.step_type === 'approval' || s.step_type === 'agreement');
  const approver = currentStep?.approver;
  const stepStatus = currentStep?.status || 'pending';

  return {
    id: String(data.id),
    documentNo: data.document_number,
    approvalType: mapApprovalType(data.form?.category),
    formCode: data.form?.code,
    formName: data.form?.name,
    documentStatus: mapDocumentStatus(data.status),
    title: data.title,
    draftDate: data.created_at.replace('T', ' ').substring(0, 16),
    drafter: data.drafter?.name || '',
    drafterDepartment: data.drafter?.department?.name || '',
    drafterPosition: data.drafter?.position || '',
    approvalDate: currentStep?.processed_at?.replace('T', ' ').substring(0, 16),
    approver: approver?.name,
    status: mapApiStatus(stepStatus),
    priority: 'normal',
    createdAt: data.created_at,
    updatedAt: data.updated_at,
  };
}

// ============================================
// API 함수
// ============================================

export async function getInbox(params?: {
  page?: number; per_page?: number; search?: string; status?: string;
  approval_type?: string; sort_by?: string; sort_dir?: 'asc' | 'desc';
  start_date?: string; end_date?: string;
}): Promise<{ data: ApprovalRecord[]; total: number; lastPage: number; __authError?: boolean }> {
  const result = await executeServerAction<PaginatedApiResponse<InboxApiData>>({
    url: buildApiUrl('/api/v1/approvals/inbox', {
      page: params?.page,
      per_page: params?.per_page,
      search: params?.search,
      status: params?.status && params.status !== 'all' ? mapTabToApiStatus(params.status) : undefined,
      approval_type: params?.approval_type !== 'all' ? params?.approval_type : undefined,
      sort_by: params?.sort_by,
      sort_dir: params?.sort_dir,
      start_date: params?.start_date,
      end_date: params?.end_date,
    }),
    errorMessage: '결재함 목록 조회에 실패했습니다.',
  });

  if (result.__authError) return { data: [], total: 0, lastPage: 1, __authError: true };
  if (!result.success || !result.data?.data) return { data: [], total: 0, lastPage: 1 };

  return {
    data: result.data.data.map(transformApiToFrontend),
    total: result.data.total,
    lastPage: result.data.last_page,
  };
}

export async function getInboxSummary(): Promise<InboxSummary | null> {
  const result = await executeServerAction<InboxSummary>({
    url: buildApiUrl('/api/v1/approvals/inbox/summary'),
    errorMessage: '결재함 통계 조회에 실패했습니다.',
  });
  return result.success ? result.data || null : null;
}

export async function approveDocument(id: string, comment?: string): Promise<ActionResult> {
  return executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}/approve`),
    method: 'POST',
    body: { comment: comment || '' },
    errorMessage: '승인 처리에 실패했습니다.',
  });
}

export async function rejectDocument(id: string, comment: string): Promise<ActionResult> {
  if (!comment?.trim()) return { success: false, error: '반려 사유를 입력해주세요.' };
  return executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}/reject`),
    method: 'POST',
    body: { comment },
    errorMessage: '반려 처리에 실패했습니다.',
  });
}

export async function approveDocumentsBulk(ids: string[], comment?: string): Promise<{ success: boolean; failedIds?: string[]; error?: string }> {
  const failedIds: string[] = [];
  for (const id of ids) {
    const result = await approveDocument(id, comment);
    if (!result.success) failedIds.push(id);
  }
  if (failedIds.length > 0) {
    return { success: false, failedIds, error: `${failedIds.length}건의 승인 처리에 실패했습니다.` };
  }
  return { success: true };
}

// ============================================
// 연결 문서(Document) 조회
// ============================================

interface LinkedDocumentApiData {
  id: number;
  document_number: string;
  title: string;
  status: string;
  drafter?: {
    id: number; name: string; position?: string;
    department?: { name: string };
    tenant_profile?: { position_key?: string; department?: { name: string } };
  };
  steps?: InboxStepApiData[];
  linkable?: {
    id: number;
    title: string;
    document_no: string;
    status: string;
    created_at: string;
    linkable_type?: string;
    linkable_id?: number;
    template?: { id: number; name: string; code: string };
    data?: Array<{ id: number; field_key: string; field_label?: string; field_value?: unknown; value?: unknown }>;
    approvals?: Array<{ id: number; step: number; status: string; acted_at?: string; user?: { id: number; name: string } }>;
    attachments?: Array<{ id: number; display_name: string; file_path: string }>;
  };
}

interface LinkedDocumentResult {
  documentNo: string;
  createdAt: string;
  title: string;
  templateName: string;
  templateCode: string;
  status: string;
  workOrderId?: number;
  documentData: Array<{ fieldKey: string; fieldLabel: string; value: unknown }>;
  approvers: Array<{ id: string; name: string; position: string; department: string; status: 'pending' | 'approved' | 'rejected' | 'none' }>;
  drafter: { id: string; name: string; position: string; department: string; status: 'approved' | 'pending' | 'rejected' | 'none' };
  attachments?: Array<{ id: number; name: string; url: string }>;
}

function getPositionLabel(positionKey: string | null | undefined): string {
  if (!positionKey) return '';
  const labels: Record<string, string> = {
    'EXECUTIVE': '임원', 'DIRECTOR': '부장', 'MANAGER': '과장',
    'SENIOR': '대리', 'STAFF': '사원', 'INTERN': '인턴',
  };
  return labels[positionKey] ?? positionKey;
}

export async function getDocumentApprovalById(id: number): Promise<{
  success: boolean;
  data?: LinkedDocumentResult;
  error?: string;
}> {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const result = await executeServerAction<any>({
    url: buildApiUrl(`/api/v1/approvals/${id}`),
    errorMessage: '문서 조회에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };

  const apiData = result.data as LinkedDocumentApiData;
  const linkable = apiData.linkable;

  const drafter = {
    id: String(apiData.drafter?.id || ''),
    name: apiData.drafter?.name || '',
    position: apiData.drafter?.tenant_profile?.position_key
      ? getPositionLabel(apiData.drafter.tenant_profile.position_key)
      : (apiData.drafter?.position || ''),
    department: apiData.drafter?.tenant_profile?.department?.name
      || apiData.drafter?.department?.name || '',
    status: 'approved' as const,
  };

  const approvers = (apiData.steps || [])
    .filter(s => s.step_type === 'approval' || s.step_type === 'agreement')
    .map(step => ({
      id: String(step.approver?.id || step.approver_id),
      name: step.approver?.name || '',
      position: step.approver?.position || '',
      department: step.approver?.department?.name || '',
      status: (step.status === 'approved' ? 'approved'
        : step.status === 'rejected' ? 'rejected'
        : step.status === 'pending' ? 'pending'
        : 'none') as 'pending' | 'approved' | 'rejected' | 'none',
    }));

  // work_order 연결 문서인 경우 workOrderId 추출
  const workOrderId = linkable?.linkable_type === 'work_order' ? linkable.linkable_id : undefined;

  return {
    success: true,
    data: {
      documentNo: linkable?.document_no || apiData.document_number,
      createdAt: linkable?.created_at || '',
      title: linkable?.title || apiData.title,
      templateName: linkable?.template?.name || '',
      templateCode: linkable?.template?.code || '',
      status: linkable?.status || apiData.status,
      workOrderId,
      documentData: (linkable?.data || []).map(d => ({
        fieldKey: d.field_key,
        fieldLabel: d.field_label || d.field_key,
        value: d.field_value ?? d.value,
      })),
      approvers,
      drafter,
      attachments: (linkable?.attachments || []).map(a => ({
        id: a.id,
        name: a.display_name,
        url: `/api/proxy/files/${a.id}/download`,
      })),
    },
  };
}

// ============================================
// 워크플로우 액션 (보류/보류해제/전결)
// ============================================

export async function holdDocument(id: string, comment?: string): Promise<ActionResult> {
  return executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}/hold`),
    method: 'POST',
    body: { comment: comment || '' },
    errorMessage: '보류 처리에 실패했습니다.',
  });
}

export async function releaseHoldDocument(id: string, comment?: string): Promise<ActionResult> {
  return executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}/release-hold`),
    method: 'POST',
    body: { comment: comment || '' },
    errorMessage: '보류 해제에 실패했습니다.',
  });
}

export async function preDecideDocument(id: string, comment?: string): Promise<ActionResult> {
  return executeServerAction({
    url: buildApiUrl(`/api/v1/approvals/${id}/pre-decide`),
    method: 'POST',
    body: { comment: comment || '' },
    errorMessage: '전결 처리에 실패했습니다.',
  });
}

export async function rejectDocumentsBulk(ids: string[], comment: string): Promise<{ success: boolean; failedIds?: string[]; error?: string }> {
  if (!comment?.trim()) return { success: false, error: '반려 사유를 입력해주세요.' };
  const failedIds: string[] = [];
  for (const id of ids) {
    const result = await rejectDocument(id, comment);
    if (!result.success) failedIds.push(id);
  }
  if (failedIds.length > 0) {
    return { success: false, failedIds, error: `${failedIds.length}건의 반려 처리에 실패했습니다.` };
  }
  return { success: true };
}