/**
 * 근태관리 서버 액션
 *
 * 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 { isNextRedirectError } from '@/lib/utils/redirect-error';
import { cookies } from 'next/headers';
import { serverFetch } from '@/lib/api/fetch-wrapper';
import type {
  AttendanceRecord,
  AttendanceApiData,
  AttendanceFormData,
  AttendanceStats,
  EmployeeOption,
} from './types';

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

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

interface PaginatedResponse<T> {
  current_page: number;
  data: T[];
  total: number;
  per_page: number;
  last_page: number;
}

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

// API URL
const API_URL = `${process.env.NEXT_PUBLIC_API_URL}/api`;

/**
 * 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 searchParams = new URLSearchParams();
  searchParams.set('per_page', '100'); // API 최대 500, 드롭다운용 100 충분
  searchParams.set('status', 'active'); // 재직자만

  const url = `${API_URL}/v1/employees?${searchParams.toString()}`;

  const { response, error } = await serverFetch(url, { method: 'GET' });

  if (error || !response) {
    console.error('[AttendanceActions] GET employees error:', error?.message);
    return [];
  }

  const result: ApiResponse<PaginatedResponse<EmployeeApiData>> = await response.json();

  if (!result.success || !result.data?.data) {
    console.warn('[AttendanceActions] No employees data');
    return [];
  }

  // API는 TenantUserProfile을 반환하지만, Attendance.user_id는 User.id를 참조
  // 따라서 user.id를 사용해야 함
  return result.data.data.map((emp) => ({
    id: String(emp.user?.id || emp.user_id), // 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 searchParams = new URLSearchParams();

  if (params?.page) searchParams.set('page', String(params.page));
  if (params?.per_page) searchParams.set('per_page', String(params.per_page));
  if (params?.user_id) searchParams.set('user_id', params.user_id);
  if (params?.date) searchParams.set('date', params.date);
  if (params?.date_from) searchParams.set('date_from', params.date_from);
  if (params?.date_to) searchParams.set('date_to', params.date_to);
  if (params?.status && params.status !== 'all') {
    searchParams.set('status', params.status);
  }
  if (params?.department_id) searchParams.set('department_id', params.department_id);
  if (params?.sort_by) searchParams.set('sort_by', params.sort_by);
  if (params?.sort_dir) searchParams.set('sort_dir', params.sort_dir);

  const url = `${API_URL}/v1/attendances?${searchParams.toString()}`;

  const { response, error } = await serverFetch(url, { method: 'GET' });

  if (error || !response) {
    console.error('[AttendanceActions] GET list error:', error?.message);
    return { data: [], total: 0, lastPage: 1 };
  }

  const result: ApiResponse<PaginatedResponse<AttendanceApiData>> = await response.json();

  if (!result.success || !result.data?.data) {
    console.warn('[AttendanceActions] No data in response');
    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 { response, error } = await serverFetch(`${API_URL}/v1/attendances/${id}`, { method: 'GET' });

  if (error || !response) {
    console.error('[AttendanceActions] GET attendance error:', error?.message);
    return null;
  }

  const result: ApiResponse<AttendanceApiData> = await response.json();

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

  return transformApiToFrontend(result.data);
}

/**
 * 근태 등록
 */
export async function createAttendance(
  data: AttendanceFormData
): Promise<{ success: boolean; data?: AttendanceRecord; error?: string }> {
  const apiData = transformFrontendToApi(data);
  console.log('[AttendanceActions] POST attendance request:', apiData);

  const { response, error } = await serverFetch(`${API_URL}/v1/attendances`, {
    method: 'POST',
    body: JSON.stringify(apiData),
  });

  if (error || !response) {
    return { success: false, error: error?.message || '근태 등록에 실패했습니다.' };
  }

  const result = await response.json();
  console.log('[AttendanceActions] POST attendance response:', result);

  if (!result.success) {
    return {
      success: false,
      error: result.message || '근태 등록에 실패했습니다.',
    };
  }

  return {
    success: true,
    data: transformApiToFrontend(result.data),
  };
}

/**
 * 근태 수정
 */
export async function updateAttendance(
  id: string,
  data: AttendanceFormData
): Promise<{ success: boolean; data?: AttendanceRecord; error?: string }> {
  const apiData = transformFrontendToApi(data);
  console.log('[AttendanceActions] PATCH attendance request:', apiData);

  const { response, error } = await serverFetch(`${API_URL}/v1/attendances/${id}`, {
    method: 'PATCH',
    body: JSON.stringify(apiData),
  });

  if (error || !response) {
    return { success: false, error: error?.message || '근태 수정에 실패했습니다.' };
  }

  const result = await response.json();
  console.log('[AttendanceActions] PATCH attendance response:', result);

  if (!result.success) {
    return {
      success: false,
      error: result.message || '근태 수정에 실패했습니다.',
    };
  }

  return {
    success: true,
    data: transformApiToFrontend(result.data),
  };
}

/**
 * 근태 삭제
 */
export async function deleteAttendance(id: string): Promise<{ success: boolean; error?: string }> {
  const { response, error } = await serverFetch(`${API_URL}/v1/attendances/${id}`, { method: 'DELETE' });

  if (error || !response) {
    return { success: false, error: error?.message || '근태 삭제에 실패했습니다.' };
  }

  const result = await response.json();
  console.log('[AttendanceActions] DELETE attendance response:', result);

  if (!result.success) {
    return {
      success: false,
      error: result.message || '근태 삭제에 실패했습니다.',
    };
  }

  return { success: true };
}

/**
 * 근태 일괄 삭제
 */
export async function deleteAttendances(ids: string[]): Promise<{ success: boolean; error?: string }> {
  const { response, error } = await serverFetch(`${API_URL}/v1/attendances/bulk-delete`, {
    method: 'POST',
    body: JSON.stringify({ ids: ids.map(id => parseInt(id, 10)) }),
  });

  if (error || !response) {
    return { success: false, error: error?.message || '근태 일괄 삭제에 실패했습니다.' };
  }

  const result = await response.json();
  console.log('[AttendanceActions] BULK DELETE attendance response:', result);

  if (!result.success) {
    return {
      success: false,
      error: result.message || '근태 일괄 삭제에 실패했습니다.',
    };
  }

  return { success: true };
}

/**
 * 월간 통계 조회
 */
export async function getMonthlyStats(params: {
  year: number;
  month: number;
  user_id?: string;
}): Promise<AttendanceStats | null> {
  const searchParams = new URLSearchParams();

  searchParams.set('year', String(params.year));
  searchParams.set('month', String(params.month));
  if (params.user_id) searchParams.set('user_id', params.user_id);

  const url = `${API_URL}/v1/attendances/monthly-stats?${searchParams.toString()}`;

  const { response, error } = await serverFetch(url, { method: 'GET' });

  if (error || !response) {
    console.error('[AttendanceActions] GET monthly-stats error:', error?.message);
    return null;
  }

  const result = await response.json();

  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,
  };
}

// ============================================
// 엑셀 내보내기
// ============================================

/**
 * 근태 엑셀 내보내기
 */
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 searchParams = new URLSearchParams();
    if (params?.date_from) searchParams.set('date_from', params.date_from);
    if (params?.date_to) searchParams.set('date_to', params.date_to);
    if (params?.user_id) searchParams.set('user_id', params.user_id);
    if (params?.status && params.status !== 'all') {
      searchParams.set('status', params.status);
    }
    if (params?.department_id) searchParams.set('department_id', params.department_id);

    const queryString = searchParams.toString();
    const url = `${API_URL}/v1/attendances/export${queryString ? `?${queryString}` : ''}`;

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

    if (!response.ok) {
      console.warn('[AttendanceActions] GET export error:', response.status);
      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;
    console.error('[AttendanceActions] exportAttendanceExcel error:', error);
    return {
      success: false,
      error: '서버 오류가 발생했습니다.',
    };
  }
}
