'use server';

import { executeServerAction } from '@/lib/api/execute-server-action';
import { buildApiUrl } from '@/lib/api/query-params';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { cookies } from 'next/headers';
import type {
  PayrollRecord,
  PayrollDetail,
  PayrollSummary,
  PayrollSettings,
  PayrollStatus,
  NameAmountItem,
} from './types';

// ===== API 응답 타입 =====
interface PayrollApiData {
  id: number;
  tenant_id: number;
  user_id: number;
  pay_year: number;
  pay_month: number;
  base_salary: string | number;
  overtime_pay: string | number;
  bonus: string | number;
  allowances: { name: string; amount: number }[] | null;
  gross_salary: string | number;
  income_tax: string | number;
  resident_tax: string | number;
  health_insurance: string | number;
  long_term_care: string | number;
  pension: string | number;
  employment_insurance: string | number;
  deductions: { name: string; amount: number }[] | null;
  total_deductions: string | number;
  net_salary: string | number;
  status: PayrollStatus;
  confirmed_at: string | null;
  confirmed_by: number | null;
  paid_at: string | null;
  withdrawal_id: number | null;
  note: string | null;
  options: Record<string, unknown> | null;
  user?: {
    id: number;
    name: string;
    email?: string;
    employee_profile?: {
      department?: { id: number; name: string } | null;
      position_label?: string | null;
      job_title_label?: string | null;
      rank?: string | null;
    } | null;
  } | null;
  created_at: string;
  updated_at: string;
}

interface PaginationApiData {
  data: PayrollApiData[];
  current_page: number;
  last_page: number;
  per_page: number;
  total: number;
}

interface SummaryApiData {
  year: number;
  month: number;
  total_count: number;
  draft_count: number;
  confirmed_count: number;
  paid_count: number;
  total_gross: number;
  total_deductions: number;
  total_net: number;
}

interface SettingsApiData {
  id?: number;
  health_insurance_rate: number;
  long_term_care_rate: number;
  pension_rate: number;
  employment_insurance_rate: number;
  income_tax_rate: number;
  resident_tax_rate: number;
  pension_max_salary: number;
  pension_min_salary: number;
  pay_day: number;
  auto_calculate: boolean;
  allowance_types: { code: string; name: string; is_taxable?: boolean }[] | null;
  deduction_types: { code: string; name: string }[] | null;
}

// ===== 변환 함수 =====
function toNum(v: string | number | null | undefined): number {
  if (v == null) return 0;
  return typeof v === 'string' ? parseFloat(v) || 0 : v;
}

function transformToRecord(d: PayrollApiData): PayrollRecord {
  const profile = d.user?.employee_profile;
  return {
    id: d.id,
    userId: d.user_id,
    userName: d.user?.name || '-',
    department: profile?.department?.name || '-',
    baseSalary: toNum(d.base_salary),
    overtimePay: toNum(d.overtime_pay),
    bonus: toNum(d.bonus),
    allowancesTotal: (d.allowances || []).reduce((s, a) => s + a.amount, 0),
    grossSalary: toNum(d.gross_salary),
    totalDeductions: toNum(d.total_deductions),
    netSalary: toNum(d.net_salary),
    status: d.status,
    payYear: d.pay_year,
    payMonth: d.pay_month,
    note: d.note,
    createdAt: d.created_at,
  };
}

function transformToDetail(d: PayrollApiData): PayrollDetail {
  const profile = d.user?.employee_profile;
  return {
    id: d.id,
    userId: d.user_id,
    userName: d.user?.name || '-',
    userEmail: d.user?.email || '',
    department: profile?.department?.name || '-',
    position: profile?.job_title_label || profile?.position_label || '-',
    rank: profile?.rank || '-',
    baseSalary: toNum(d.base_salary),
    overtimePay: toNum(d.overtime_pay),
    bonus: toNum(d.bonus),
    allowances: d.allowances || [],
    grossSalary: toNum(d.gross_salary),
    pension: toNum(d.pension),
    healthInsurance: toNum(d.health_insurance),
    longTermCare: toNum(d.long_term_care),
    employmentInsurance: toNum(d.employment_insurance),
    incomeTax: toNum(d.income_tax),
    residentTax: toNum(d.resident_tax),
    deductions: d.deductions || [],
    totalDeductions: toNum(d.total_deductions),
    netSalary: toNum(d.net_salary),
    status: d.status,
    payYear: d.pay_year,
    payMonth: d.pay_month,
    note: d.note,
    confirmedAt: d.confirmed_at,
    paidAt: d.paid_at,
  };
}

function transformSettings(d: SettingsApiData): PayrollSettings {
  return {
    id: d.id,
    healthInsuranceRate: d.health_insurance_rate,
    longTermCareRate: d.long_term_care_rate,
    pensionRate: d.pension_rate,
    employmentInsuranceRate: d.employment_insurance_rate,
    incomeTaxRate: d.income_tax_rate,
    residentTaxRate: d.resident_tax_rate,
    pensionMaxSalary: d.pension_max_salary,
    pensionMinSalary: d.pension_min_salary,
    payDay: d.pay_day,
    autoCalculate: d.auto_calculate,
    allowanceTypes: d.allowance_types || [],
    deductionTypes: d.deduction_types || [],
  };
}

// ============================
// 급여 목록 조회
// ============================
export async function getPayrolls(params?: {
  year?: number;
  month?: number;
  search?: string;
  status?: string;
  user_id?: number;
  sort_by?: string;
  sort_dir?: string;
  page?: number;
  per_page?: number;
}): Promise<{
  success: boolean;
  data?: PayrollRecord[];
  pagination?: { total: number; currentPage: number; lastPage: number };
  error?: string;
}> {
  const result = await executeServerAction<PaginationApiData>({
    url: buildApiUrl('/api/v1/payrolls', {
      year: params?.year,
      month: params?.month,
      search: params?.search,
      status: params?.status && params.status !== 'all' ? params.status : undefined,
      user_id: params?.user_id,
      sort_by: params?.sort_by,
      sort_dir: params?.sort_dir,
      page: params?.page,
      per_page: params?.per_page,
    }),
    errorMessage: '급여 목록을 불러오는데 실패했습니다.',
  });

  if (!result.success || !result.data) return { success: false, error: result.error };

  return {
    success: true,
    data: result.data.data.map(transformToRecord),
    pagination: {
      total: result.data.total,
      currentPage: result.data.current_page,
      lastPage: result.data.last_page,
    },
  };
}

// ============================
// 급여 상세 조회
// ============================
export async function getPayroll(id: number): Promise<{
  success: boolean;
  data?: PayrollDetail;
  error?: string;
}> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/payrolls/${id}`),
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '급여 상세를 불러오는데 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

// ============================
// 월간 요약
// ============================
export async function getPayrollSummary(params: {
  year: number;
  month: number;
}): Promise<{
  success: boolean;
  data?: PayrollSummary;
  error?: string;
}> {
  const result = await executeServerAction<SummaryApiData>({
    url: buildApiUrl('/api/v1/payrolls/summary', {
      year: params.year,
      month: params.month,
    }),
    errorMessage: '급여 요약을 불러오는데 실패했습니다.',
  });

  if (!result.success || !result.data) return { success: false, error: result.error };

  const d = result.data;
  return {
    success: true,
    data: {
      year: d.year,
      month: d.month,
      totalCount: d.total_count,
      draftCount: d.draft_count,
      confirmedCount: d.confirmed_count,
      paidCount: d.paid_count,
      totalGross: d.total_gross,
      totalDeductions: d.total_deductions,
      totalNet: d.total_net,
    },
  };
}

// ============================
// 급여 등록
// ============================
export async function createPayroll(data: {
  user_id: number;
  pay_year: number;
  pay_month: number;
  base_salary: number;
  overtime_pay?: number;
  bonus?: number;
  allowances?: NameAmountItem[];
  income_tax?: number;
  resident_tax?: number;
  health_insurance?: number;
  long_term_care?: number;
  pension?: number;
  employment_insurance?: number;
  deductions?: NameAmountItem[];
  note?: string;
}): Promise<{ success: boolean; data?: PayrollDetail; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/payrolls'),
    method: 'POST',
    body: data,
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '급여 등록에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

// ============================
// 급여 수정 (draft만)
// ============================
export async function updatePayroll(
  id: number,
  data: {
    base_salary?: number;
    overtime_pay?: number;
    bonus?: number;
    allowances?: NameAmountItem[];
    income_tax?: number;
    resident_tax?: number;
    health_insurance?: number;
    long_term_care?: number;
    pension?: number;
    employment_insurance?: number;
    deductions?: NameAmountItem[];
    note?: string;
  }
): Promise<{ success: boolean; data?: PayrollDetail; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/payrolls/${id}`),
    method: 'PUT',
    body: data,
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '급여 수정에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

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

// ============================
// 확정
// ============================
export async function confirmPayroll(id: number): Promise<{
  success: boolean;
  data?: PayrollDetail;
  error?: string;
}> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/payrolls/${id}/confirm`),
    method: 'POST',
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '급여 확정에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

// ============================
// 확정 취소
// ============================
export async function unconfirmPayroll(id: number): Promise<{
  success: boolean;
  data?: PayrollDetail;
  error?: string;
}> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/payrolls/${id}/unconfirm`),
    method: 'POST',
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '확정 취소에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

// ============================
// 지급 처리
// ============================
export async function payPayroll(
  id: number,
  withdrawalId?: number
): Promise<{ success: boolean; data?: PayrollDetail; error?: string }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/payrolls/${id}/pay`),
    method: 'POST',
    body: withdrawalId ? { withdrawal_id: withdrawalId } : undefined,
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '지급 처리에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

// ============================
// 지급 취소 (슈퍼관리자)
// ============================
export async function unpayPayroll(id: number): Promise<{
  success: boolean;
  data?: PayrollDetail;
  error?: string;
}> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/payrolls/${id}/unpay`),
    method: 'POST',
    transform: (d: PayrollApiData) => transformToDetail(d),
    errorMessage: '지급 취소에 실패했습니다.',
  });
  return { success: result.success, data: result.data, error: result.error };
}

// ============================
// 일괄 계산 (draft 재계산)
// ============================
export async function calculatePayrolls(params: {
  year: number;
  month: number;
  user_ids?: number[];
}): Promise<{ success: boolean; data?: PayrollRecord[]; error?: string }> {
  const result = await executeServerAction<PayrollApiData[]>({
    url: buildApiUrl('/api/v1/payrolls/calculate'),
    method: 'POST',
    body: params,
    errorMessage: '일괄 계산에 실패했습니다.',
  });

  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, data: result.data.map(transformToRecord) };
}

// ============================
// 일괄 확정
// ============================
export async function bulkConfirmPayrolls(params: {
  year: number;
  month: number;
}): Promise<{ success: boolean; count?: number; error?: string }> {
  const result = await executeServerAction<{ count: number }>({
    url: buildApiUrl('/api/v1/payrolls/bulk-confirm'),
    method: 'POST',
    body: params,
    errorMessage: '일괄 확정에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, count: result.data.count };
}

// ============================
// 재직사원 일괄 생성
// ============================
export async function bulkGeneratePayrolls(params: {
  year: number;
  month: number;
}): Promise<{ success: boolean; count?: number; error?: string }> {
  const result = await executeServerAction<{ count: number } | PayrollApiData[]>({
    url: buildApiUrl('/api/v1/payrolls/bulk-generate'),
    method: 'POST',
    body: params,
    errorMessage: '일괄 생성에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };

  const count = Array.isArray(result.data)
    ? result.data.length
    : (result.data as { count: number }).count;
  return { success: true, count };
}

// ============================
// 전월 급여 복사
// ============================
export async function copyFromPrevious(params: {
  year: number;
  month: number;
}): Promise<{ success: boolean; count?: number; error?: string }> {
  const result = await executeServerAction<{ count: number } | PayrollApiData[]>({
    url: buildApiUrl('/api/v1/payrolls/copy-from-previous'),
    method: 'POST',
    body: params,
    errorMessage: '전월 복사에 실패했습니다.',
  });
  if (!result.success || !result.data) return { success: false, error: result.error };

  const count = Array.isArray(result.data)
    ? result.data.length
    : (result.data as { count: number }).count;
  return { success: true, count };
}

// ============================
// 급여명세서
// ============================
export async function getPayslip(id: number): Promise<{
  success: boolean;
  data?: {
    period: string;
    employee: { id: number; name: string; email: string };
    earnings: {
      base_salary: number;
      overtime_pay: number;
      bonus: number;
      allowances: NameAmountItem[];
      allowances_total: number;
      gross_total: number;
    };
    deductions: {
      income_tax: number;
      resident_tax: number;
      health_insurance: number;
      pension: number;
      employment_insurance: number;
      other_deductions: NameAmountItem[];
      other_total: number;
      total: number;
    };
    net_salary: number;
    status: string;
    status_label: string;
    paid_at: string | null;
  };
  error?: string;
}> {
  interface PayslipApiData {
    period: string;
    employee: { id: number; name: string; email: string };
    earnings: {
      base_salary: number;
      overtime_pay: number;
      bonus: number;
      allowances: NameAmountItem[];
      allowances_total: number;
      gross_total: number;
    };
    deductions: {
      income_tax: number;
      resident_tax: number;
      health_insurance: number;
      pension: number;
      employment_insurance: number;
      other_deductions: NameAmountItem[];
      other_total: number;
      total: number;
    };
    net_salary: number;
    status: string;
    status_label: string;
    paid_at: string | null;
  }

  const result = await executeServerAction<PayslipApiData>({
    url: buildApiUrl(`/api/v1/payrolls/${id}/payslip`),
    errorMessage: '급여명세서를 불러오는데 실패했습니다.',
  });
  return { success: result.success, data: result.data ?? undefined, error: result.error };
}

// ============================
// 급여 설정 조회
// ============================
export async function getPayrollSettings(): Promise<{
  success: boolean;
  data?: PayrollSettings;
  error?: string;
}> {
  const result = await executeServerAction<SettingsApiData>({
    url: buildApiUrl('/api/v1/settings/payroll'),
    errorMessage: '급여 설정을 불러오는데 실패했습니다.',
  });

  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, data: transformSettings(result.data) };
}

// ============================
// 급여 설정 수정
// ============================
export async function updatePayrollSettings(data: {
  health_insurance_rate?: number;
  long_term_care_rate?: number;
  pension_rate?: number;
  employment_insurance_rate?: number;
  income_tax_rate?: number;
  resident_tax_rate?: number;
  pension_max_salary?: number;
  pension_min_salary?: number;
  pay_day?: number;
  auto_calculate?: boolean;
  allowance_types?: { code: string; name: string; is_taxable?: boolean }[];
  deduction_types?: { code: string; name: string }[];
}): Promise<{ success: boolean; data?: PayrollSettings; error?: string }> {
  const result = await executeServerAction<SettingsApiData>({
    url: buildApiUrl('/api/v1/settings/payroll'),
    method: 'PUT',
    body: data,
    errorMessage: '급여 설정 저장에 실패했습니다.',
  });

  if (!result.success || !result.data) return { success: false, error: result.error };
  return { success: true, data: transformSettings(result.data) };
}

// ============================
// 엑셀 내보내기
// ============================
export async function exportPayrollExcel(params?: {
  year?: number;
  month?: number;
  status?: 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/payrolls/export', {
      year: params?.year,
      month: params?.month,
      status: params?.status && params.status !== 'all' ? params.status : undefined,
    });

    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?.year || 'all'}_${params?.month || 'all'}.xlsx`;

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

// ============================
// 전표 생성
// ============================
export async function createJournalEntries(params: {
  year: number;
  month: number;
  entry_date?: string;
}): Promise<{ success: boolean; error?: string; data?: unknown }> {
  return executeServerAction({
    url: buildApiUrl('/api/v1/payrolls/journal-entries'),
    method: 'POST',
    body: params,
    errorMessage: '전표 생성에 실패했습니다.',
  });
}
