/**
 * 휴가관리 서버 액션
 *
 * API Endpoints:
 * - GET /api/v1/leaves - 휴가 목록 조회
 * - GET /api/v1/leaves/{id} - 휴가 상세 조회
 * - POST /api/v1/leaves - 휴가 신청
 * - PATCH /api/v1/leaves/{id} - 휴가 수정
 * - DELETE /api/v1/leaves/{id} - 휴가 삭제
 * - POST /api/v1/leaves/{id}/approve - 휴가 승인
 * - POST /api/v1/leaves/{id}/reject - 휴가 반려
 * - POST /api/v1/leaves/{id}/cancel - 휴가 취소
 * - GET /api/v1/leaves/balances - 전체 직원 휴가 사용현황 조회
 * - GET /api/v1/leaves/balance - 내 잔여 휴가 조회
 * - GET /api/v1/leaves/balance/{userId} - 특정 사용자 잔여 휴가 조회
 * - PUT /api/v1/leaves/balance - 잔여 휴가 설정
 * - GET /api/v1/leaves/grants - 휴가 부여 이력 조회
 * - POST /api/v1/leaves/grants - 휴가 부여
 * - DELETE /api/v1/leaves/grants/{id} - 휴가 부여 삭제
 */

'use server';


import { executeServerAction } from '@/lib/api/execute-server-action';
import { buildApiUrl } from '@/lib/api/query-params';
import type { PaginatedApiResponse } from '@/lib/api/types';

// ============================================
// 타입 정의
// ============================================

/**
 * 휴가 유형
 */
export type LeaveType = 'annual' | 'half_am' | 'half_pm' | 'sick' | 'family' | 'maternity' | 'parental';

/**
 * 휴가 상태
 */
export type LeaveStatus = 'pending' | 'approved' | 'rejected' | 'cancelled';

/**
 * 휴가 기록 응답 타입
 */
export interface LeaveRecord {
  id: number;
  userId: number;
  leaveType: LeaveType;
  startDate: string;
  endDate: string;
  days: number;
  reason: string | null;
  status: LeaveStatus;
  approvedBy: number | null;
  approvedAt: string | null;
  rejectedReason: string | null;
  createdAt: string;
  updatedAt: string;
  // 관계 데이터
  user?: {
    id: number;
    name: string;
    email: string;
  };
  // 사용자 프로필 (부서/직책/직급)
  userProfile?: {
    id: number;
    department_id: number | null;
    position_key: string | null;
    job_title_key: string | null;
    position_label: string | null;
    job_title_label: string | null;
    rank: string | null;
    department?: {
      id: number;
      name: string;
    } | null;
  } | null;
}

/**
 * 휴가 목록 조회 파라미터
 */
export interface GetLeavesParams {
  userId?: number;
  status?: LeaveStatus;
  leaveType?: LeaveType;
  dateFrom?: string;
  dateTo?: string;
  year?: number;
  departmentId?: number;
  sortBy?: 'created_at' | 'start_date' | 'end_date' | 'days' | 'status';
  sortDir?: 'asc' | 'desc';
  perPage?: number;
  page?: number;
}

/**
 * 휴가 신청 요청 데이터
 */
export interface CreateLeaveRequest {
  userId?: number;
  leaveType: LeaveType;
  startDate: string;
  endDate: string;
  days: number;
  reason?: string;
}

/**
 * 잔여 휴가 정보
 */
export interface LeaveBalance {
  userId: number;
  year: number;
  totalDays: number;
  usedDays: number;
  remainingDays: number;
}

/**
 * 잔여 휴가 설정 요청 데이터
 */
export interface SetLeaveBalanceRequest {
  userId: number;
  year: number;
  totalDays: number;
}

/**
 * 전체 직원 휴가 사용현황 조회 파라미터
 */
export interface GetLeaveBalancesParams {
  year?: number;
  departmentId?: number;
  search?: string;
  sortBy?: 'user_id' | 'department';
  sortDir?: 'asc' | 'desc';
  perPage?: number;
  page?: number;
}

/**
 * 전체 직원 휴가 사용현황 레코드
 */
export interface LeaveBalanceRecord {
  id: number;
  userId: number;
  employeeName: string;
  email: string;
  department: string;
  position: string;      // position_label (부장, 과장 등)
  jobTitle: string;      // job_title_label (팀장, 팀원 등) → 직책으로 사용
  rank: string | null;   // json_extra.rank → 직급으로 사용
  hireDate: string | null;
  displayName: string | null;
  totalDays: number;
  usedDays: number;
  remainingDays: number;
}

interface _ApiResponse<T> {
  success: boolean;
  data: T;
  message: string;
}

/**
 * API 응답에서 프론트엔드 형식으로 변환
 */
function transformApiToFrontend(apiData: Record<string, unknown>): LeaveRecord {
  const user = apiData.user as Record<string, unknown> | undefined;
  const userProfile = apiData.user_profile as Record<string, unknown> | undefined;
  const department = userProfile?.department as Record<string, unknown> | undefined;

  return {
    id: apiData.id as number,
    userId: apiData.user_id as number,
    leaveType: apiData.leave_type as LeaveType,
    startDate: apiData.start_date as string,
    endDate: apiData.end_date as string,
    days: apiData.days as number,
    reason: apiData.reason as string | null,
    status: apiData.status as LeaveStatus,
    approvedBy: apiData.approved_by as number | null,
    approvedAt: apiData.approved_at as string | null,
    rejectedReason: apiData.rejected_reason as string | null,
    createdAt: apiData.created_at as string,
    updatedAt: apiData.updated_at as string,
    user: user
      ? {
        id: user.id as number,
        name: user.name as string,
        email: user.email as string,
      }
      : undefined,
    userProfile: userProfile
      ? {
        id: userProfile.id as number,
        department_id: userProfile.department_id as number | null,
        position_key: userProfile.position_key as string | null,
        job_title_key: userProfile.job_title_key as string | null,
        position_label: userProfile.position_label as string | null,
        job_title_label: userProfile.job_title_label as string | null,
        rank: userProfile.rank as string | null,
        department: department
          ? { id: department.id as number, name: department.name as string }
          : null,
      }
      : null,
  };
}

/**
 * 잔여 휴가 응답 변환
 */
function transformBalanceToFrontend(apiData: Record<string, unknown>): LeaveBalance {
  return {
    userId: apiData.user_id as number,
    year: apiData.year as number,
    totalDays: apiData.total_days as number,
    usedDays: apiData.used_days as number,
    remainingDays: apiData.remaining_days as number,
  };
}

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

/** 휴가 목록 조회 */
export async function getLeaves(params?: GetLeavesParams): Promise<{
  success: boolean;
  data?: { items: LeaveRecord[]; total: number; currentPage: number; lastPage: number };
  error?: string;
}> {
  const result = await executeServerAction<PaginatedApiResponse<Record<string, unknown>>>({
    url: buildApiUrl('/api/v1/leaves', {
      user_id: params?.userId,
      status: params?.status,
      leave_type: params?.leaveType,
      date_from: params?.dateFrom,
      date_to: params?.dateTo,
      year: params?.year,
      department_id: params?.departmentId,
      sort_by: params?.sortBy,
      sort_dir: params?.sortDir,
      per_page: params?.perPage,
      page: params?.page,
    }),
    errorMessage: '휴가 목록 조회에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return {
    success: true,
    data: {
      items: result.data.data.map(transformApiToFrontend),
      total: result.data.total, currentPage: result.data.current_page, lastPage: result.data.last_page,
    },
  };
}

/** 휴가 상세 조회 */
export async function getLeaveById(id: number): Promise<{ success: boolean; data?: LeaveRecord; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/${id}`),
    transform: (data: Record<string, unknown>) => transformApiToFrontend(data),
    errorMessage: '휴가 조회에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 휴가 신청 */
export async function createLeave(data: CreateLeaveRequest): Promise<{ success: boolean; data?: LeaveRecord; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/leaves'),
    method: 'POST',
    body: { user_id: data.userId, leave_type: data.leaveType, start_date: data.startDate, end_date: data.endDate, days: data.days, reason: data.reason },
    transform: (d: Record<string, unknown>) => transformApiToFrontend(d),
    errorMessage: '휴가 신청에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 휴가 승인 */
export async function approveLeave(id: number, comment?: string): Promise<{ success: boolean; data?: LeaveRecord; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/${id}/approve`),
    method: 'POST',
    body: { comment },
    transform: (d: Record<string, unknown>) => transformApiToFrontend(d),
    errorMessage: '휴가 승인에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 휴가 반려 */
export async function rejectLeave(id: number, reason: string): Promise<{ success: boolean; data?: LeaveRecord; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/${id}/reject`),
    method: 'POST',
    body: { reason },
    transform: (d: Record<string, unknown>) => transformApiToFrontend(d),
    errorMessage: '휴가 반려에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 휴가 취소 */
export async function cancelLeave(id: number, reason?: string): Promise<{ success: boolean; data?: LeaveRecord; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/${id}/cancel`),
    method: 'POST',
    body: { reason },
    transform: (d: Record<string, unknown>) => transformApiToFrontend(d),
    errorMessage: '휴가 취소에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 내 잔여 휴가 조회 */
export async function getMyLeaveBalance(year?: number): Promise<{ success: boolean; data?: LeaveBalance; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/leaves/balance', { year }),
    transform: (data: Record<string, unknown>) => transformBalanceToFrontend(data),
    errorMessage: '잔여 휴가 조회에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 특정 사용자 잔여 휴가 조회 */
export async function getUserLeaveBalance(userId: number, year?: number): Promise<{ success: boolean; data?: LeaveBalance; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/balance/${userId}`, { year }),
    transform: (data: Record<string, unknown>) => transformBalanceToFrontend(data),
    errorMessage: '잔여 휴가 조회에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 잔여 휴가 설정 (부여) */
export async function setLeaveBalance(data: SetLeaveBalanceRequest): Promise<{ success: boolean; data?: LeaveBalance; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/leaves/balance'),
    method: 'PUT',
    body: { user_id: data.userId, year: data.year, total_days: data.totalDays },
    transform: (d: Record<string, unknown>) => transformBalanceToFrontend(d),
    errorMessage: '잔여 휴가 설정에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 휴가 삭제 */
export async function deleteLeave(id: number): Promise<{ success: boolean; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/${id}`),
    method: 'DELETE',
    errorMessage: '휴가 삭제에 실패했습니다.',
  });
  return { success: result.success, error: result.error };
}

/** 여러 휴가 일괄 승인 */
export async function approveLeavesMany(ids: number[]): Promise<{
  success: boolean; results?: { id: number; success: boolean; error?: string }[]; error?: string;
}> {
  const results = await Promise.all(
    ids.map(async (id) => {
      const r = await approveLeave(id);
      return { id, success: r.success, error: r.error };
    })
  );
  const allSuccess = results.every((r) => r.success);
  return { success: allSuccess, results, error: allSuccess ? undefined : '일부 휴가 승인에 실패했습니다.' };
}

/** 여러 휴가 일괄 반려 */
export async function rejectLeavesMany(ids: number[], reason: string): Promise<{
  success: boolean; results?: { id: number; success: boolean; error?: string }[]; error?: string;
}> {
  const results = await Promise.all(
    ids.map(async (id) => {
      const r = await rejectLeave(id, reason);
      return { id, success: r.success, error: r.error };
    })
  );
  const allSuccess = results.every((r) => r.success);
  return { success: allSuccess, results, error: allSuccess ? undefined : '일부 휴가 반려에 실패했습니다.' };
}

/** 전체 직원 휴가 사용현황 조회 */
export async function getLeaveBalances(params?: GetLeaveBalancesParams): Promise<{
  success: boolean;
  data?: { items: LeaveBalanceRecord[]; total: number; currentPage: number; lastPage: number };
  error?: string;
}> {
  const result = await executeServerAction<PaginatedApiResponse<Record<string, unknown>>>({
    url: buildApiUrl('/api/v1/leaves/balances', {
      year: params?.year,
      department_id: params?.departmentId,
      search: params?.search,
      sort_by: params?.sortBy,
      sort_dir: params?.sortDir,
      per_page: params?.perPage,
      page: params?.page,
    }),
    errorMessage: '휴가 사용현황 조회에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return {
    success: true,
    data: {
      items: result.data.data.map(transformBalanceRecordToFrontend),
      total: result.data.total, currentPage: result.data.current_page, lastPage: result.data.last_page,
    },
  };
}

/**
 * 휴가 사용현황 레코드 응답 변환
 */
function transformBalanceRecordToFrontend(apiData: Record<string, unknown>): LeaveBalanceRecord {
  const user = apiData.user as Record<string, unknown> | undefined;
  const department = apiData.department as Record<string, unknown> | undefined;
  const totalDays = (apiData.leave_balance_total as number | null) ?? 15; // 기본 15일
  const usedDays = (apiData.leave_balance_used as number | null) ?? 0;

  return {
    id: apiData.id as number,
    userId: apiData.user_id as number,
    employeeName: (user?.name as string) ?? '',
    email: (user?.email as string) ?? '',
    department: (department?.name as string) ?? '-',
    position: (apiData.position_label as string) ?? '-',
    jobTitle: (apiData.job_title_label as string) ?? '-',
    rank: (apiData.rank as string | null) ?? null,  // json_extra.rank
    hireDate: (apiData.hire_date as string | null) ?? null,
    displayName: (apiData.display_name as string | null) ?? null,
    totalDays,
    usedDays,
    remainingDays: totalDays - usedDays,
  };
}

// ============================================
// 휴가 부여 관련 타입 및 API
// ============================================

/**
 * 휴가 부여 유형
 */
export type LeaveGrantType = 'annual' | 'monthly' | 'reward' | 'condolence' | 'other';

/**
 * 휴가 부여 이력 조회 파라미터
 */
export interface GetLeaveGrantsParams {
  userId?: number;
  grantType?: LeaveGrantType;
  dateFrom?: string;
  dateTo?: string;
  year?: number;
  departmentId?: number;
  search?: string;
  sortBy?: 'grant_date' | 'grant_days' | 'created_at';
  sortDir?: 'asc' | 'desc';
  perPage?: number;
  page?: number;
}

/**
 * 휴가 부여 레코드
 */
export interface LeaveGrantRecord {
  id: number;
  userId: number;
  employeeName: string;
  email: string;
  department: string;
  position: string;      // position_label
  jobTitle: string;      // job_title_label → 직책
  rank: string | null;   // json_extra.rank → 직급
  grantType: LeaveGrantType;
  grantDate: string;
  grantDays: number;
  reason: string | null;
  createdBy: number | null;
  creatorName: string | null;
  createdAt: string;
}

/**
 * 휴가 부여 요청 데이터
 */
export interface CreateLeaveGrantRequest {
  userId: number;
  grantType: LeaveGrantType;
  grantDate: string;
  grantDays: number;
  reason?: string;
}

/** 휴가 부여 이력 조회 */
export async function getLeaveGrants(params?: GetLeaveGrantsParams): Promise<{
  success: boolean;
  data?: { items: LeaveGrantRecord[]; total: number; currentPage: number; lastPage: number };
  error?: string;
}> {
  const result = await executeServerAction<PaginatedApiResponse<Record<string, unknown>>>({
    url: buildApiUrl('/api/v1/leaves/grants', {
      user_id: params?.userId,
      grant_type: params?.grantType,
      date_from: params?.dateFrom,
      date_to: params?.dateTo,
      year: params?.year,
      department_id: params?.departmentId,
      search: params?.search,
      sort_by: params?.sortBy,
      sort_dir: params?.sortDir,
      per_page: params?.perPage,
      page: params?.page,
    }),
    errorMessage: '휴가 부여 이력 조회에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return {
    success: true,
    data: {
      items: result.data.data.map(transformGrantRecordToFrontend),
      total: result.data.total, currentPage: result.data.current_page, lastPage: result.data.last_page,
    },
  };
}

/** 휴가 부여 */
export async function createLeaveGrant(data: CreateLeaveGrantRequest): Promise<{ success: boolean; data?: LeaveGrantRecord; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/leaves/grants'),
    method: 'POST',
    body: { user_id: data.userId, grant_type: data.grantType, grant_date: data.grantDate, grant_days: data.grantDays, reason: data.reason },
    transform: (d: Record<string, unknown>) => transformGrantRecordToFrontend(d),
    errorMessage: '휴가 부여에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

/** 휴가 부여 삭제 */
export async function deleteLeaveGrant(id: number): Promise<{ success: boolean; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/leaves/grants/${id}`),
    method: 'DELETE',
    errorMessage: '휴가 부여 삭제에 실패했습니다.',
  });
  return { success: result.success, error: result.error };
}

/**
 * 휴가 부여 이력 레코드 응답 변환
 */
function transformGrantRecordToFrontend(apiData: Record<string, unknown>): LeaveGrantRecord {
  const user = apiData.user as Record<string, unknown> | undefined;
  const tenantProfile = user?.tenant_profile as Record<string, unknown> | undefined;
  const department = tenantProfile?.department as Record<string, unknown> | undefined;
  const creator = apiData.creator as Record<string, unknown> | undefined;

  return {
    id: apiData.id as number,
    userId: apiData.user_id as number,
    employeeName: (user?.name as string) ?? '',
    email: (user?.email as string) ?? '',
    department: (department?.name as string) ?? '-',
    position: (tenantProfile?.position_label as string) ?? '-',
    jobTitle: (tenantProfile?.job_title_label as string) ?? '-',
    rank: (tenantProfile?.rank as string | null) ?? null,  // json_extra.rank
    grantType: apiData.grant_type as LeaveGrantType,
    grantDate: apiData.grant_date as string,
    grantDays: apiData.grant_days as number,
    reason: apiData.reason as string | null,
    createdBy: apiData.created_by as number | null,
    creatorName: (creator?.name as string) ?? null,
    createdAt: apiData.created_at as string,
  };
}

// ============================================
// 직원 목록 조회 (다이얼로그용)
// ============================================

/**
 * 직원 선택 옵션 타입
 */
export interface EmployeeOption {
  id: string;
  userId: number;
  name: string;
  department: string;
  position: string;
}

/** 활성 직원 목록 조회 (휴가 신청/부여용) */
export async function getActiveEmployees(): Promise<{ success: boolean; data?: EmployeeOption[]; error?: string }> {
  interface EmployeePaginatedApiResponse { data: Record<string, unknown>[]; total: number }
  const result = await executeServerAction<EmployeePaginatedApiResponse>({
    url: buildApiUrl('/api/v1/employees', { status: 'active', per_page: 100 }),
    errorMessage: '직원 목록 조회에 실패했습니다.',
  });
  if (!result.success || !result.data?.data) return { success: false, error: result.error };

  const employees: EmployeeOption[] = result.data.data.map((item) => {
    const user = item.user as Record<string, unknown> | undefined;
    const department = item.department as Record<string, unknown> | undefined;
    return {
      id: String(item.id),
      userId: (item.user_id as number) ?? (user?.id as number) ?? (item.id as number),
      name: (user?.name as string) ?? (item.name as string) ?? '',
      department: (department?.name as string) ?? '-',
      position: (item.position_label as string) ?? (item.position_key as string) ?? '-',
    };
  });
  return { success: true, data: employees };
}