import type {
    AbsenceBalance,
    AbsencePolicy,
    AbsencePolicyWrite,
    AbsencePreviewPayload,
    AbsencePreviewResult,
    AbsenceRequest,
    AbsenceRequestWrite,
    AbsenceStatus,
    AbsenceType,
} from './dto/absence'
import type { HydraCollection } from '~/utils/api'
import { extractHydraMembers } from '~/utils/api'

export type AbsenceRequestFilters = {
    status?: AbsenceStatus
    type?: AbsenceType
    year?: number
    user?: number
}

export function useAbsenceService() {
    const api = useApi()

    // --- Requests ---

    async function getRequests(filters: AbsenceRequestFilters = {}): Promise<AbsenceRequest[]> {
        const query: Record<string, unknown> = {}
        if (filters.status) query.status = filters.status
        if (filters.type) query.type = filters.type
        if (filters.year) query.year = filters.year
        if (filters.user) query.user = `/api/users/${filters.user}`
        const data = await api.get<HydraCollection<AbsenceRequest>>('/absence_requests', query)
        return extractHydraMembers(data)
    }

    async function getRequest(id: number): Promise<AbsenceRequest> {
        return api.get<AbsenceRequest>(`/absence_requests/${id}`)
    }

    async function create(payload: AbsenceRequestWrite): Promise<AbsenceRequest> {
        return api.post<AbsenceRequest>('/absence_requests', payload as Record<string, unknown>, {
            toastSuccessKey: 'absences.toast.created',
        })
    }

    async function preview(payload: AbsencePreviewPayload): Promise<AbsencePreviewResult> {
        return api.post<AbsencePreviewResult>('/absence_requests/preview', payload as Record<string, unknown>, {
            toast: false,
        })
    }

    async function approve(id: number): Promise<AbsenceRequest> {
        return api.patch<AbsenceRequest>(`/absence_requests/${id}/approve`, {}, {
            toastSuccessKey: 'absences.toast.approved',
        })
    }

    async function reject(id: number, rejectionReason: string): Promise<AbsenceRequest> {
        return api.patch<AbsenceRequest>(`/absence_requests/${id}/reject`, { rejectionReason }, {
            toastSuccessKey: 'absences.toast.rejected',
        })
    }

    async function cancel(id: number): Promise<AbsenceRequest> {
        return api.patch<AbsenceRequest>(`/absence_requests/${id}/cancel`, {}, {
            toastSuccessKey: 'absences.toast.cancelled',
        })
    }

    async function uploadJustification(id: number, file: File): Promise<AbsenceRequest> {
        const form = new FormData()
        form.append('file', file)
        return api.post<AbsenceRequest>(`/absence_requests/${id}/justificatif`, form as unknown as Record<string, unknown>, {
            toastSuccessKey: 'absences.toast.justificationUploaded',
        })
    }

    // --- Balances ---

    async function getBalances(filters: { user?: number; period?: string; type?: AbsenceType } = {}): Promise<AbsenceBalance[]> {
        const query: Record<string, unknown> = {}
        if (filters.user) query.user = `/api/users/${filters.user}`
        if (filters.period) query.period = filters.period
        if (filters.type) query.type = filters.type
        const data = await api.get<HydraCollection<AbsenceBalance>>('/absence_balances', query)
        return extractHydraMembers(data)
    }

    async function adjustBalance(id: number, payload: { acquired?: number; acquiring?: number; taken?: number }): Promise<AbsenceBalance> {
        return api.patch<AbsenceBalance>(`/absence_balances/${id}`, payload as Record<string, unknown>, {
            toastSuccessKey: 'absences.toast.balanceAdjusted',
        })
    }

    // --- Policies ---

    async function getPolicies(): Promise<AbsencePolicy[]> {
        const data = await api.get<HydraCollection<AbsencePolicy>>('/absence_policies')
        return extractHydraMembers(data)
    }

    async function updatePolicy(id: number, payload: AbsencePolicyWrite): Promise<AbsencePolicy> {
        return api.patch<AbsencePolicy>(`/absence_policies/${id}`, payload as Record<string, unknown>, {
            toastSuccessKey: 'absences.toast.policyUpdated',
        })
    }

    // --- Admin calendar ---

    async function getCalendar(from: string, to: string): Promise<AbsenceRequest[]> {
        return api.get<AbsenceRequest[]>('/admin/absences/calendar', { from, to })
    }

    // --- Public holidays (computed server-side) ---

    async function getPublicHolidays(from: string, to: string): Promise<Record<string, string>> {
        return api.get<Record<string, string>>('/public_holidays', { from, to }, { toast: false })
    }

    return {
        getRequests,
        getRequest,
        create,
        preview,
        approve,
        reject,
        cancel,
        uploadJustification,
        getBalances,
        adjustBalance,
        getPolicies,
        updatePolicy,
        getCalendar,
        getPublicHolidays,
    }
}
