/**
 * Client HTTP per rendicontazione-api (microservizio BFLOWS).
 * Usa fetch nativa come NetworkService. Il microservizio valida lo stesso JWT di GEPAFIN-BE.
 *
 * Env var: REACT_APP_RENDICONTAZIONE_API_URL (es. http://78.46.41.91:18090)
 */
import { storeGet } from '../../../store';

const BASE_URL = process.env.REACT_APP_RENDICONTAZIONE_API_URL || '';

const buildHeaders = () => {
    const token = storeGet('getToken');
    const h = { 'Content-Type': 'application/json' };
    if (token) {
        h['Authorization'] = `Bearer ${token}`;
    }
    return h;
};

const handleResponse = async (response, onSuccess, onError) => {
    let body = null;
    try {
        body = await response.json();
    } catch (e) {
        body = { detail: response.statusText };
    }
    if (response.status >= 200 && response.status < 300) {
        if (onSuccess) onSuccess(body);
    } else {
        if (onError) onError({ status: response.status, ...body });
    }
};

const handleError = (err, onError) => {
    if (onError) onError({ status: 0, detail: err.message });
};

const RendicontazioneService = {
    getSchemaByCallId(callId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/${callId}`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    initializeRestartTemplate(callId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/${callId}/initialize-restart`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    updateSchema(callId, schemaJson, onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/${callId}`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ schema_json: schemaJson })
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    publishSchema(callId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/${callId}/publish`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    deleteSchema(callId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/${callId}`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    getRestartTemplatePreview(onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/templates/restart`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    }
};

export default RendicontazioneService;

// =========================================================================
// v2.1 — Picker schema (blank / template / clone)
// =========================================================================

export const schemaPickerService = {
    listTemplates(onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/templates`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    listClonableCalls(onSuccess, onError) {
        fetch(`${BASE_URL}/api/rendicontazione-schemas/clonable-calls`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    },

    initializeSchema(callId, payload, onSuccess, onError) {
        // payload = { source: "blank"|"template"|"clone", template_id?, source_call_id? }
        fetch(`${BASE_URL}/api/rendicontazione-schemas/${callId}/initialize`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(payload)
        })
            .then(r => handleResponse(r, onSuccess, onError))
            .catch(e => handleError(e, onError));
    }
};


// ====================== PRATICHE BENEFICIARIO ======================

const extendPractice = {
    listMine(onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/mine`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    startPractice(applicationId, onSuccess, onError, opts = {}) {
        // opts: { period_label?: string, copy_ula_from_previous?: bool }
        fetch(`${BASE_URL}/api/remission-practices/start`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({
                application_id: applicationId,
                period_label: opts.period_label ?? null,
                copy_ula_from_previous: opts.copy_ula_from_previous !== false,
            })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    copyUlaOptions(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/copy-ula-options`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    getPractice(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    updatePractice(practiceId, patch, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(patch)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    addInvoice(practiceId, invoice, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/invoices`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(invoice)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    deleteInvoice(practiceId, invoiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/invoices/${invoiceId}`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    addUlaEmployee(practiceId, emp, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/ula-employees`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(emp)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    deleteUlaEmployee(practiceId, empId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/ula-employees/${empId}`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    upsertDocument(practiceId, docCode, payload, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/documents/${docCode}`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ doc_code: docCode, ...payload })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    clearDocument(practiceId, docCode, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/documents/${docCode}`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    gateCheck(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/gate-check`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    submitPractice(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/submit`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    // dev-only: impersonation per test beneficiary
    impersonate(email, onSuccess, onError) {
        fetch(`${BASE_URL}/api/debug/impersonate`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ email })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    }
};

// Attach to main export
Object.assign(RendicontazioneService, extendPractice);


// ====================== ISTRUTTORE ======================

const extendInstructor = {
    instructorQueue(onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/queue`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    instructorViewPractice(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    claimPractice(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/claim`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    approvePractice(practiceId, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/approve`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body || {})
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    rejectPractice(practiceId, reason, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/reject`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ rejection_reason: reason })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    createAmendment(practiceId, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    closeAmendment(practiceId, amendmentId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/close`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    respondAmendmentBeneficiary(practiceId, amendmentId, responseText, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/respond-beneficiary`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ response_text: responseText })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    // ====== AMENDMENT v3: DRAFT lifecycle + extend + reminder + uploads ======

    updateAmendment(practiceId, amendmentId, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    deleteAmendment(practiceId, amendmentId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    sendAmendment(practiceId, amendmentId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/send`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    extendAmendment(practiceId, amendmentId, extendedDays, motivation, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/extend`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ extended_days: extendedDays, motivation })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    sendAmendmentReminder(practiceId, amendmentId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/reminder`, {
            method: 'POST', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    uploadAmendmentDocument(practiceId, amendmentId, file, onSuccess, onError) {
        const fd = new FormData();
        fd.append('file', file);
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/upload-document`, {
            method: 'POST', mode: 'cors',
            headers: _buildBearerOnly(),
            body: fd
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    deleteAmendmentDocument(practiceId, amendmentId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/upload-document`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    uploadResponseDocument(practiceId, amendmentId, file, onSuccess, onError) {
        const fd = new FormData();
        fd.append('file', file);
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/amendment/${amendmentId}/upload-response-document`, {
            method: 'POST', mode: 'cors',
            headers: _buildBearerOnly(),
            body: fd
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    }
};

Object.assign(RendicontazioneService, extendInstructor);


// ====================== VERIFICA SINGOLA RIGA ISTRUTTORE ======================

const extendVerify = {
    verifyInvoice(practiceId, invoiceId, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/invoices/${invoiceId}/verify`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    verifyUlaEmployee(practiceId, empId, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/ula-employees/${empId}/verify`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    verifyDocument(practiceId, docCode, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/documents/${docCode}/verify`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    setInstructorFinalNotes(practiceId, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/final-notes`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    }
};

Object.assign(RendicontazioneService, extendVerify);


// ====================== FILE UPLOAD ======================

const _buildBearerOnly = () => {
    const token = storeGet('getToken');
    return token ? { 'Authorization': `Bearer ${token}` } : {};
};

const extendFiles = {
    /**
     * Upload file per entita (invoice/ula/document).
     * Restituisce i metadata del file via onSuccess.
     */
    uploadEntityFile(entityType, entityId, file, onSuccess, onError) {
        const fd = new FormData();
        fd.append('file', file);
        fetch(`${BASE_URL}/api/remission-files/${entityType}/${entityId}/upload`, {
            method: 'POST', mode: 'cors',
            headers: _buildBearerOnly(),   // no Content-Type: browser mette boundary
            body: fd
        }).then(r => handleResponse(r, onSuccess, onError))
          .catch(e => handleError(e, onError));
    },

    /**
     * Collega un remission_document a un company_document del repository Gepafin.
     * Alternativa all upload dal PC: copia filename/expires_at/storage_path dal sorgente
     * e traccia source_company_document_id per lookup live dello status (VALID/DUE/EXPIRED).
     * Usato solo su entityType='document'.
     */
    linkDocumentFromRepository(remissionDocumentId, companyDocumentId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-files/document/${remissionDocumentId}/link-from-repository`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({ company_document_id: companyDocumentId })
        }).then(r => handleResponse(r, onSuccess, onError))
          .catch(e => handleError(e, onError));
    },

    /**
     * Elimina file allegato a una entita.
     */
    deleteEntityFile(entityType, entityId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-files/${entityType}/${entityId}`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError))
          .catch(e => handleError(e, onError));
    },

    /**
     * Fetch file come Blob (per preview in iframe tramite object URL).
     * onSuccess({blob, objectUrl, filename}).
     */
    fetchEntityFileBlob(entityType, entityId, inline, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-files/${entityType}/${entityId}?inline=${inline ? 1 : 0}`, {
            method: 'GET', mode: 'cors', headers: _buildBearerOnly()
        }).then(async r => {
            if (r.status < 200 || r.status >= 300) {
                let detail = r.statusText;
                try { const j = await r.json(); detail = j.detail || detail; } catch(e){}
                if (onError) onError({ status: r.status, detail });
                return;
            }
            // estrae filename da Content-Disposition
            let filename = 'file';
            const cd = r.headers.get('Content-Disposition') || '';
            const m = cd.match(/filename="([^"]+)"/);
            if (m) filename = m[1];
            const blob = await r.blob();
            const objectUrl = URL.createObjectURL(blob);
            if (onSuccess) onSuccess({ blob, objectUrl, filename });
        }).catch(e => handleError(e, onError));
    },

    /**
     * Download forzato: apre finestra "save as" del browser.
     */
    downloadEntityFile(entityType, entityId, onError) {
        this.fetchEntityFileBlob(entityType, entityId, false,
            ({ objectUrl, filename }) => {
                const a = document.createElement('a');
                a.href = objectUrl;
                a.download = filename;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                setTimeout(() => URL.revokeObjectURL(objectUrl), 60000);
            },
            onError
        );
    }
};

Object.assign(RendicontazioneService, extendFiles);


// ====================== VERBALE ISTRUTTORIA ======================

const extendVerbale = {
    /**
     * Scarica il verbale di istruttoria come PDF (download forzato).
     */
    downloadVerbale(practiceId, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/verbale.pdf`, {
            method: 'GET', mode: 'cors', headers: _buildBearerOnly()
        }).then(async r => {
            if (r.status < 200 || r.status >= 300) {
                let detail = r.statusText;
                try { const j = await r.json(); detail = j.detail || detail; } catch(e){}
                if (onError) onError({ status: r.status, detail });
                return;
            }
            const blob = await r.blob();
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `verbale_istruttoria_${practiceId.slice(0, 8)}.pdf`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            setTimeout(() => URL.revokeObjectURL(url), 60000);
        }).catch(e => { if (onError) onError({ status: 0, detail: e.message }); });
    },

    /**
     * Apre preview HTML del verbale in una nuova tab (debug rapido).
     */
    async openVerbaleHtml(practiceId) {
        const token = storeGet('getToken');
        const r = await fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/verbale.html`, {
            method: 'GET', mode: 'cors',
            headers: token ? { 'Authorization': `Bearer ${token}` } : {}
        });
        if (!r.ok) throw new Error('Verbale HTML fetch failed');
        const html = await r.text();
        const w = window.open('', '_blank');
        if (w) { w.document.open(); w.document.write(html); w.document.close(); }
    }
};

Object.assign(RendicontazioneService, extendVerbale);

// ====================== v2 CUSTOM CHECKS ======================
const extendCustomChecks = {
    listCustomChecks(practiceId, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/custom-checks`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    declareCustomCheck(practiceId, code, declared, file, onSuccess, onError) {
        const fd = new FormData();
        fd.append('beneficiary_declared', declared ? 'true' : 'false');
        if (file) fd.append('file', file);
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/custom-checks/${code}/declare`, {
            method: 'PUT', mode: 'cors',
            headers: _buildBearerOnly(),  // no Content-Type: boundary auto
            body: fd
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    deleteCustomCheckDocument(practiceId, code, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/custom-checks/${code}/document`, {
            method: 'DELETE', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    verifyCustomCheck(practiceId, code, body, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/custom-checks/${code}/verify`, {
            method: 'PUT', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify(body)
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    fetchCustomCheckDocumentBlob(practiceId, code, inline, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/${practiceId}/custom-checks/${code}/document?inline=${inline ? 1 : 0}`, {
            method: 'GET', mode: 'cors', headers: _buildBearerOnly()
        }).then(async r => {
            if (r.status < 200 || r.status >= 300) {
                let detail = r.statusText;
                try { const j = await r.json(); detail = j.detail || detail; } catch(e){}
                if (onError) onError({ status: r.status, detail });
                return;
            }
            let filename = 'file';
            const cd = r.headers.get('Content-Disposition') || '';
            const m = cd.match(/filename="([^"]+)"/);
            if (m) filename = m[1];
            const blob = await r.blob();
            const objectUrl = URL.createObjectURL(blob);
            if (onSuccess) onSuccess({ blob, objectUrl, filename });
        }).catch(e => handleError(e, onError));
    }
};
Object.assign(RendicontazioneService, extendCustomChecks);


// ====================== v2 MANAGER ISTRUTTORE ======================
const extendAssignmentManager = {
    managerAssignments(onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor-manager/assignments`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    managerInstructorsList(onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor-manager/instructors`, {
            method: 'GET', mode: 'cors', headers: buildHeaders()
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    },

    reassignInstructor(practiceId, newInstructorId, reason, onSuccess, onError) {
        fetch(`${BASE_URL}/api/remission-practices/instructor/${practiceId}/reassign`, {
            method: 'POST', mode: 'cors', headers: buildHeaders(),
            body: JSON.stringify({
                new_instructor_id: newInstructorId,
                reassignment_reason: reason || null,
            })
        }).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
    }
};
Object.assign(RendicontazioneService, extendAssignmentManager);
