/**
 * 근태관리 서버 액션
 *
 * API Endpoints:
 * - GET /api/v1/attendances - 목록 조회
 * - GET /api/v1/attendances/{id} - 상세 조회
 * - POST /api/v1/attendances - 등록
 * - PATCH /api/v1/attendances/{id} - 수정
 * - DELETE /api/v1/attendances/{id} - 삭제
 * - POST /api/v1/attendances/bulk-delete - 일괄 삭제
 * - GET /api/v1/attendances/monthly-stats - 월간 통계
 * - GET /api/v1/attendances/export - 엑셀 내보내기
 */

'use server';


import { executeServerAction } from '@/lib/api/execute-server-action';
import { buildApiUrl } from '@/lib/api/query-params';
import type { PaginatedApiResponse } from '@/lib/api/types';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { cookies } from 'next/headers';
import type {
  AttendanceRecord,
  AttendanceApiData,
  AttendanceFormData,
  AttendanceStats,
  EmployeeOption,
} from './types';

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

/**
 * API 응답 데이터를 프론트엔드 형식으로 변환
 */
function transformApiToFrontend(apiData: AttendanceApiData): AttendanceRecord {
  const jsonDetails = apiData.json_details || {};

  // tenant_profiles 배열에서 첫 번째 프로필 추출 (API with 쿼리 결과)
  const profile = apiData.user?.tenant_profiles?.[0];
  const department = profile?.department;

  // 기존 tenant_profile 호환성 유지
  const legacyProfile = apiData.user?.tenant_profile;

  // check_in/check_out: Model $appends로 최상위 레벨에서 먼저 읽고, 없으면 json_details에서 읽음
  // Model accessor가 check_ins[] 배열에서 가장 빠른 시간, check_outs[]에서 가장 늦은 시간 반환
  const checkIn = apiData.check_in ?? jsonDetails.check_in ?? null;
  const checkOut = apiData.check_out ?? jsonDetails.check_out ?? null;

  return {
    id: String(apiData.id),
    employeeId: String(apiData.user_id),
    employeeName: apiData.user?.name || '',
    department: department?.name || legacyProfile?.department?.name || '',
    position: profile?.position_key || legacyProfile?.position?.name || '',
    rank: legacyProfile?.rank || '',
    baseDate: apiData.base_date,
    checkIn,
    checkOut, // break_minutes: Model $appends로 최상위에서 먼저 읽고, 분 단위를 문자열로 변환
    breakTime: apiData.break_minutes != null
      ? formatMinutesToBreakTime(apiData.break_minutes)
      : (jsonDetails.break_time || null),
    overtimeHours: jsonDetails.overtime_minutes
      ? formatMinutesToHours(jsonDetails.overtime_minutes)
      : null,
    workMinutes: jsonDetails.work_minutes || null,
    reason: jsonDetails.reason || null,
    status: apiData.status,
    remarks: apiData.remarks || null,
    createdAt: apiData.created_at,
    updatedAt: apiData.updated_at,
  };
}

/**
 * 프론트엔드 폼 데이터를 API 형식으로 변환
 */
function transformFrontendToApi(data: AttendanceFormData): Record<string, unknown> {
  const jsonDetails: Record<string, unknown> = {};

  // 출퇴근 시간 변환
  if (data.checkInHour && data.checkInMinute) {
    jsonDetails.check_in = `${data.checkInHour.padStart(2, '0')}:${data.checkInMinute.padStart(2, '0')}:00`;
  }
  if (data.checkOutHour && data.checkOutMinute) {
    jsonDetails.check_out = `${data.checkOutHour.padStart(2, '0')}:${data.checkOutMinute.padStart(2, '0')}:00`;
  }

  // 연장근무 시간 변환 (분 단위)
  const nightOvertimeMinutes =
    (parseInt(data.nightOvertimeHours || '0', 10) * 60) +
    parseInt(data.nightOvertimeMinutes || '0', 10);
  const weekendOvertimeMinutes =
    (parseInt(data.weekendOvertimeHours || '0', 10) * 60) +
    parseInt(data.weekendOvertimeMinutes || '0', 10);

  if (nightOvertimeMinutes > 0 || weekendOvertimeMinutes > 0) {
    jsonDetails.overtime_minutes = nightOvertimeMinutes + weekendOvertimeMinutes;
  }

  return {
    user_id: parseInt(data.employeeId, 10),
    base_date: data.baseDate,
    status: data.status || 'onTime',
    json_details: jsonDetails,
    remarks: data.remarks || null,
  };
}

/**
 * 분을 휴게시간 문자열로 변환 (예: 90 -> "1:30")
 */
function formatMinutesToBreakTime(minutes: number): string {
  const hours = Math.floor(minutes / 60);
  const mins = minutes % 60;
  return `${hours}:${mins.toString().padStart(2, '0')}`;
}

/**
 * 분을 시간 문자열로 변환 (예: 210 -> "3시간 30분")
 */
function formatMinutesToHours(minutes: number): string {
  const hours = Math.floor(minutes / 60);
  const mins = minutes % 60;
  if (hours > 0 && mins > 0) {
    return `${hours}시간 ${mins}분`;
  } else if (hours > 0) {
    return `${hours}시간`;
  } else {
    return `${mins}분`;
  }
}

// ============================================
// 사원 목록 조회 (근태 등록용)
// ============================================

interface EmployeeApiData {
  id: number;
  user_id: number;
  name: string;
  employee_code?: string;
  status: string;
  user?: {
    id: number;
    name: string;
  };
  tenant_user_profile?: {
    department?: { id: number; name: string };
    position?: { id: number; name: string };
    rank?: string;
  };
  department?: { id: number; name: string };
  position_key?: string;
}

export async function getEmployeesForAttendance(): Promise<EmployeeOption[]> {
  const result = await executeServerAction<PaginatedApiResponse<EmployeeApiData>>({
    url: buildApiUrl('/api/v1/employees', { per_page: 100, status: 'active' }),
    errorMessage: '사원 목록 조회에 실패했습니다.',
  });

  if (!result.success || !result.data?.data) return [];

  return result.data.data.map((emp) => ({
    id: String(emp.user?.id || emp.user_id),
    name: emp.user?.name || emp.name,
    department: emp.department?.name || emp.tenant_user_profile?.department?.name || '',
    position: emp.position_key || emp.tenant_user_profile?.position?.name || '',
    rank: emp.tenant_user_profile?.rank || '',
  }));
}

// ============================================
// 근태 API 함수
// ============================================

export async function getAttendances(params?: {
  page?: number; per_page?: number; user_id?: string; date?: string;
  date_from?: string; date_to?: string; status?: string;
  department_id?: string; sort_by?: string; sort_dir?: 'asc' | 'desc';
}): Promise<{ data: AttendanceRecord[]; total: number; lastPage: number }> {
  const result = await executeServerAction<PaginatedApiResponse<AttendanceApiData>>({
    url: buildApiUrl('/api/v1/attendances', {
      page: params?.page,
      per_page: params?.per_page,
      user_id: params?.user_id,
      date: params?.date,
      date_from: params?.date_from,
      date_to: params?.date_to,
      status: params?.status && params.status !== 'all' ? params.status : undefined,
      department_id: params?.department_id,
      sort_by: params?.sort_by,
      sort_dir: params?.sort_dir,
    }),
    errorMessage: '근태 목록 조회에 실패했습니다.',
  });

  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 getAttendanceById(id: string): Promise<AttendanceRecord | null> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/attendances/${id}`),
    transform: (data: AttendanceApiData) => transformApiToFrontend(data),
    errorMessage: '근태 조회에 실패했습니다.',
  });
  return result.success ? result.data || null : null;
}

export async function createAttendance(
  data: AttendanceFormData
): Promise<{ success: boolean; data?: AttendanceRecord; error?: string }> {
  const apiData = transformFrontendToApi(data);
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/attendances'),
    method: 'POST',
    body: apiData,
    transform: (d: AttendanceApiData) => transformApiToFrontend(d),
    errorMessage: '근태 등록에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

export async function updateAttendance(
  id: string,
  data: AttendanceFormData
): Promise<{ success: boolean; data?: AttendanceRecord; error?: string }> {
  const apiData = transformFrontendToApi(data);
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/attendances/${id}`),
    method: 'PATCH',
    body: apiData,
    transform: (d: AttendanceApiData) => transformApiToFrontend(d),
    errorMessage: '근태 수정에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

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

export async function deleteAttendances(ids: string[]): Promise<{ success: boolean; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/attendances/bulk-delete'),
    method: 'POST',
    body: { ids: ids.map(id => parseInt(id, 10)) },
    errorMessage: '근태 일괄 삭제에 실패했습니다.',
  });
  return { success: result.success, error: result.error };
}

export async function getMonthlyStats(params: {
  year: number; month: number; user_id?: string;
}): Promise<AttendanceStats | null> {
  interface MonthlyStatsApiData {
    year: number; month: number; total_days: number;
    by_status: {
      onTime: number; late: number; absent: number; vacation: number;
      businessTrip: number; fieldWork: number; overtime: number; remote: number;
    };
    total_work_minutes: number; total_overtime_minutes: number;
  }

  const result = await executeServerAction<MonthlyStatsApiData>({
    url: buildApiUrl('/api/v1/attendances/monthly-stats', {
      year: params.year,
      month: params.month,
      user_id: params.user_id,
    }),
    errorMessage: '월간 통계 조회에 실패했습니다.',
  });

  if (!result.success || !result.data) return null;

  return {
    year: result.data.year,
    month: result.data.month,
    totalDays: result.data.total_days,
    byStatus: result.data.by_status,
    totalWorkMinutes: result.data.total_work_minutes,
    totalOvertimeMinutes: result.data.total_overtime_minutes,
  };
}

// ============================================
// 엑셀 내보내기 (native fetch - keep as-is)
// ============================================

export async function exportAttendanceExcel(params?: {
  date_from?: string; date_to?: string; user_id?: string;
  status?: string; department_id?: string;
}): Promise<{
  success: boolean; data?: Blob; filename?: string; error?: string;
}> {
  try {
    const cookieStore = await cookies();
    const token = cookieStore.get('access_token')?.value;

    const headers: HeadersInit = {
      'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'Authorization': token ? `Bearer ${token}` : '',
      'X-API-KEY': process.env.API_KEY || '',
    };

    const url = buildApiUrl('/api/v1/attendances/export', {
      date_from: params?.date_from,
      date_to: params?.date_to,
      user_id: params?.user_id,
      status: params?.status && params.status !== 'all' ? params.status : undefined,
      department_id: params?.department_id,
    });

    const response = await fetch(url, { method: 'GET', headers });

    if (!response.ok) {
      return { success: false, error: `API 오류: ${response.status}` };
    }

    const blob = await response.blob();
    const contentDisposition = response.headers.get('Content-Disposition');
    const filenameMatch = contentDisposition?.match(/filename="?(.+)"?/);
    const filename = filenameMatch?.[1] || `근태현황_${params?.date_from || 'all'}.xlsx`;

    return { success: true, data: blob, filename };
  } catch (error) {
    if (isNextRedirectError(error)) throw error;
    return { success: false, error: '서버 오류가 발생했습니다.' };
  }
}
