import { Job, JobCollection } from '../../domain/entities/job';
import { JobRepositoryInterface } from '../../domain/repository/JobRepositoryInterface';

export class ApiJobRepository extends JobRepositoryInterface {
    /**
     * Récupère la liste des jobs
     * @param {Object} options Les options de filtrage et pagination
     * @param {number} options.page Numéro de la page
     * @param {number} options.limit Nombre d'éléments par page
     * @param {string} options.sortBy Champ pour le tri
     * @param {string} options.sortOrder Direction du tri ('ASC' ou 'DESC')
     * @param {Array<string>} options.status Liste des statuts à filtrer
     * @returns {Promise<JobCollection>} Collection de jobs
     */
    async getJobs(options = {}) {
        const { page = 1, limit = 100, sortBy = 'createdAt', sortOrder = 'DESC', status = [], type = null } = options;

        try {
            let url = `/api/jobs?page=${page}&limit=${limit}&sortBy=${sortBy}&sortOrder=${sortOrder}`;

            // Ajouter les filtres de statut s'ils sont fournis
            if (status && status.length > 0) {
                url += `&status=${status.join(',')}`;
            }

            // Ajouter le filtre de type si fourni
            if (type) {
                url += `&type=${type}`;
            }

            const response = await fetch(url);

            if (!response.ok) {
                throw new Error('Failed to fetch jobs');
            }

            const data = await response.json();

            // Gérer différents formats de réponse API
            let jobs, total, currentPage, limit_returned, hasNext, hasPrev;

            if (Array.isArray(data)) {
                // Si l'API retourne directement un tableau
                jobs = data;
                total = data.length;
                currentPage = page;
                limit_returned = limit;
                hasNext = false;
                hasPrev = false;
            } else if (data.items || data.data) {
                // Si l'API retourne un objet avec les données dans items ou data
                jobs = data.items || data.data || [];
                total = data.total || data.totalCount || jobs.length;
                currentPage = data.page || data.currentPage || page;
                limit_returned = data.limit || data.perPage || limit;
                hasNext = data.hasNextPage || data.hasNext || (currentPage * limit_returned < total);
                hasPrev = data.hasPreviousPage || data.hasPrev || currentPage > 1;
            } else {
                // Format par défaut
                jobs = data || [];
                total = data.total || 0;
                currentPage = data.page || 1;
                limit_returned = data.limit || limit;
                hasNext = !!data.hasNextPage;
                hasPrev = !!data.hasPreviousPage;
            }

            return new JobCollection(
                jobs,
                total,
                currentPage,
                limit_returned,
                hasNext,
                hasPrev
            );
        } catch (error) {
            throw error;
        }
    }

    /**
     * Récupère un job par son ID
     * @param {string} id Identifiant du job
     * @returns {Promise<Job>} Job
     */
    async getJobById(id) {
        try {
            const response = await fetch(`/api/jobs/${id}`);

            if (!response.ok) {
                throw new Error('Failed to fetch job');
            }

            const data = await response.json();
            return Job.create(data);
        } catch (error) {
            throw error;
        }
    }

    /**
     * Supprime un job
     * @param {string} id Identifiant du job
     * @returns {Promise<boolean>} Succès de l'opération
     */
    async deleteJob(id) {
        try {
            const response = await fetch(`/api/jobs/${id}`, {
                method: 'DELETE'
            });

            if (!response.ok) {
                throw new Error('Failed to delete job');
            }

            return true;
        } catch (error) {
            throw error;
        }
    }

    /**
     * Supprime tous les jobs correspondant aux critères
     * @param {Object} criteria Critères de suppression
     * @returns {Promise<number>} Nombre de jobs supprimés
     */
    async deleteJobs(criteria = {}) {
        try {
            const queryParams = new URLSearchParams();

            // Ajouter les critères à l'URL
            Object.entries(criteria).forEach(([key, value]) => {
                if (Array.isArray(value)) {
                    queryParams.append(key, value.join(','));
                } else {
                    queryParams.append(key, value);
                }
            });

            const response = await fetch(`/api/jobs?${queryParams.toString()}`, {
                method: 'DELETE'
            });

            if (!response.ok) {
                throw new Error('Failed to delete jobs');
            }

            const data = await response.json();
            return data.deleted || 0;
        } catch (error) {
            throw error;
        }
    }
}
