/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/financeiro/composables/useBillingOrchestrator.js
|
| ORCHESTRATOR central de billing — single entry point pra qualquer mudança
| de cobrança vinculada a evento da agenda. Resolve overlap entre os 3
| caminhos atuais (useAgendaFinanceiro.gerarCobrancaManual, handleStatusChange,
| useMelissaAgenda._applyStatusDecisions).
|
| ⚠️ FOUNDATION em construção. Decisões #2/#3/#6 (memória project_agenda_billing_decisoes)
| ainda pendentes — state machine completa fica pra sessão dedicada antes do
| rollout dos callers.
|
| Design completo: development/02-auditoria/DESIGN_BILLING_ORCHESTRATOR.md
|
| Plano de migração (Fases A-D do design doc):
|   [x] Fase A — repositories criados (financialRecords, financialExceptions, billingContracts)
|   [x] Fase B — composables thin wrappers criados (useFinancialRecords, useFinancialExceptions, useBillingContracts, este orchestrator)
|   [ ] Fase C — state machine completa + migração dos 3 callers (BLOQUEADA pelas decisões #2/#3/#6)
|   [ ] Fase D — cleanup (deletar src/composables/useFinancialRecords.js + useAgendaFinanceiro.js)
|--------------------------------------------------------------------------
*/
import { ref } from 'vue';
import { useFinancialRecords } from './useFinancialRecords';
import { useFinancialExceptions } from './useFinancialExceptions';
import { useBillingContracts } from './useBillingContracts';

export function useBillingOrchestrator() {
    const loading = ref(false);
    const error = ref('');

    const financialRecords = useFinancialRecords();
    const exceptions = useFinancialExceptions();
    const contracts = useBillingContracts();

    /**
     * Resolve state atual do evento (snapshot pra decisões da transição).
     * @returns {Promise<{records: Array, packageInfo: Object|null}>}
     */
    async function resolveBillingState(eventId, { billing_contract_id } = {}) {
        const records = await financialRecords.fetchByEvent(eventId);
        const packageInfo = billing_contract_id ? await contracts.fetchById(billing_contract_id) : null;
        return { records, packageInfo };
    }

    /**
     * Gera cobrança manual pra evento sem cobrança ainda. Idempotente
     * (RPC create_financial_record_for_session ignora cancelled).
     */
    async function generateChargeForEvent(event, options = {}) {
        if (event.billing_contract_id) {
            return { ok: false, error: 'Sessão faz parte de um pacote. Cobrança gerenciada pelo contrato.' };
        }
        loading.value = true;
        error.value = '';
        try {
            const amount = options.amount ?? event.price ?? 0;
            const dueDate = options.due_date || (event.inicio_em ? new Date(event.inicio_em).toISOString().slice(0, 10) : new Date().toISOString().slice(0, 10));
            const data = await financialRecords.createRecord({
                patient_id: event.patient_id ?? event.paciente_id ?? null,
                agenda_evento_id: event.id,
                amount,
                due_date: dueDate
            });
            return data;
        } catch (e) {
            error.value = e?.message || 'Falha ao gerar cobrança.';
            return { ok: false, error: error.value };
        } finally {
            loading.value = false;
        }
    }

    /**
     * Lista records de um evento. Helper público pra UI.
     */
    async function fetchRecordsForEvent(eventId) {
        return financialRecords.fetchByEvent(eventId);
    }

    /**
     * Cancela TODOS os records pending/overdue de um evento (soft).
     * Use em reverse transitions confirmadas pelo user.
     */
    async function cancelRecordsForEvent(eventId, reason) {
        const records = await financialRecords.fetchByEvent(eventId);
        const cancelable = records.filter((r) => ['pending', 'overdue'].includes(r.status));
        const results = [];
        for (const r of cancelable) {
            const res = await financialRecords.cancelRecord(r.id, { reason });
            results.push({ id: r.id, ...res });
        }
        return results;
    }

    /**
     * 🚧 STATE MACHINE — implementação completa BLOQUEADA pelas decisões #2/#3/#6.
     *
     * Estrutura prevista (do DESIGN_BILLING_ORCHESTRATOR.md):
     *
     *   applyStatusChange({ event, fromStatus, toStatus, decisions? })
     *     → { ok, actions: [...], needsConfirmation?, error? }
     *
     * Transições:
     *   agendado→realizado | agendado→faltou | agendado→cancelado
     *   realizado→agendado (REVERSE) | realizado→faltou (CROSS)
     *   faltou→agendado (REVERSE) | cancelado→agendado (REVERSE)
     *
     * Quando completar:
     *   1. Migrar callers (AgendaEventDialog, useMelissaAgenda._applyStatusDecisions,
     *      callers de gerarCobrancaManual)
     *   2. Deletar src/composables/useFinancialRecords.js
     *   3. Deletar src/composables/useAgendaFinanceiro.js
     */
    async function applyStatusChange(_params) {
        throw new Error(
            'applyStatusChange ainda não implementado. ' +
                'Decisões #2/#3/#6 de billing pendentes (memória project_agenda_billing_decisoes). ' +
                'Ver DESIGN_BILLING_ORCHESTRATOR.md seção 7.4. ' +
                'Caller deve continuar usando useAgendaFinanceiro.handleStatusChange até Fase C estar pronta.'
        );
    }

    function invalidateRules() {
        exceptions.invalidate();
    }

    return {
        loading,
        error,
        // Sub-composables (acesso direto se precisar de algo específico)
        financialRecords,
        exceptions,
        contracts,
        // High-level operations
        resolveBillingState,
        generateChargeForEvent,
        fetchRecordsForEvent,
        cancelRecordsForEvent,
        applyStatusChange,
        invalidateRules
    };
}
