/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/agenda/composables/useAgendaEventPickerBilling.js
| Data: 2026-05-04
|
| A66 sub-sessão 1C-ii-a — handlers de patient picker + billing items +
| 2 watchers (commitment_id auto-fill price, insurance_plan_id limpa
| items + reset campos).
|
| Não inclui (vai pra 1C-ii-b):
|   - Watcher props.modelValue (init form ao abrir — tem dependências
|     em loadPatients/ensureServicesLoaded/loadInsurancePlans/
|     _loadCommitmentItemsForEvent + supabase pra buscar nome do paciente)
|   - Watchers de online slots, solicitações pendentes
|   - Series pills handlers
|   - Slot selection
|   - Quick-creates wiring
|   - onSendManualReminder
|
| Recebe via argumento:
|   composer            — refs + computeds do composer (1B)
|   _actions            — refs internos do actions (1C-i): _restoringConvenio
|   commitmentItems     — ref<Item[]>
|   servicePickerSel    — ref do select picker (limpado ao trocar convenio)
|   selectedPlanService — ref do procedure de convênio
|   services            — ref<Service[]> do useServices
|   loadServices        — fn(ownerId) do useServices
|   getDefaultPrice     — fn() do useServices (preço default sugerido)
|   planServices        — computed<PlanService[]> (de useInsurancePlans + form)
|   loadActiveDiscount  — fn(ownerId, patientId) do usePatientDiscounts
|   _csLoadItems        — fn(eventId) do useCommitmentServices
|   _csLoadItemsOrTemplate — fn(eventId, ruleId, opts) do useCommitmentServices
|   isDynamic           — computed<boolean>
|   props               — props do componente parent
|--------------------------------------------------------------------------
*/
import { ref, watch, nextTick } from 'vue';
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { calcFinalPrice } from './agendaEventHelpers';

export function useAgendaEventPickerBilling({
    composer,
    actions,
    commitmentItems,
    servicePickerSel,
    selectedPlanService,
    services,
    loadServices,
    getDefaultPrice,
    planServices,
    loadActiveDiscount,
    _csLoadItems,
    _csLoadItemsOrTemplate,
    isDynamic,
    props
}) {
    // ── Patient picker state ───────────────────────────────────────
    const pacientePickerOpen = ref(false);
    const pacienteSearch = ref('');
    const pacientesLoading = ref(false);
    const pacientesError = ref('');
    const patients = ref([]);

    // ── Cadastro rápido ────────────────────────────────────────────
    const cadRapidoOpen = ref(false);

    // ── Services lazy-load gate ────────────────────────────────────
    let _servicesLoaded = false;

    // ────────────────────────────────────────────────────────────────
    // Services pré-carga (lazy: só uma vez por sessão do dialog)
    // ────────────────────────────────────────────────────────────────
    async function ensureServicesLoaded() {
        if (_servicesLoaded || !props.ownerId) return;
        _servicesLoaded = true;
        await loadServices(props.ownerId);
    }

    // Reseta o gate (chamado pelo watcher de open na 1C-ii-b)
    function resetServicesGate() {
        _servicesLoaded = false;
    }

    function applyDefaultPrice() {
        // Skip particular: preço vem dos commitmentItems
        if (composer.billingType.value === 'particular') return;
        // Só auto-preenche em criação (edição preserva o valor salvo)
        if (!composer.isEdit.value) {
            const suggested = getDefaultPrice();
            if (suggested != null) composer.form.value.price = suggested;
        }
    }

    // ────────────────────────────────────────────────────────────────
    // Billing items (commitment_services)
    // ────────────────────────────────────────────────────────────────

    /**
     * Adiciona um serviço ao billing. Regras:
     *  - Não duplica: se já existe item do mesmo service_id, incrementa quantity
     *  - Aplica desconto ativo do paciente (se houver)
     *  - Recalcula final_price via helper puro
     */
    async function addItem(svc) {
        if (!svc?.id) return;
        const existing = commitmentItems.value.find((i) => i.service_id === svc.id);
        if (existing) {
            existing.quantity++;
            existing.final_price = calcFinalPrice(existing.unit_price, existing.quantity, existing.discount_pct, existing.discount_flat);
            return;
        }
        const unit_price = Number(svc.price);
        const patientId = composer.form.value.patient_id ?? composer.form.value.paciente_id ?? null;
        let discount_pct = 0;
        let discount_flat = 0;

        if (patientId && props.ownerId) {
            const discount = await loadActiveDiscount(props.ownerId, patientId);
            if (discount) {
                discount_pct = Number(discount.discount_pct ?? 0);
                discount_flat = Number(discount.discount_flat ?? 0);
            }
        }

        commitmentItems.value.push({
            service_id: svc.id,
            service_name: svc.name,
            quantity: 1,
            unit_price,
            discount_pct,
            discount_flat,
            final_price: calcFinalPrice(unit_price, 1, discount_pct, discount_flat)
        });
    }

    function removeItem(index) {
        commitmentItems.value.splice(index, 1);
        // Lista vazia em modo dinâmico → restaura duração padrão
        if (commitmentItems.value.length === 0 && isDynamic.value) {
            composer.form.value.duracaoMin = props.agendaSettings?.session_duration_min ?? 50;
        }
    }

    function onItemChange(item) {
        item.final_price = calcFinalPrice(item.unit_price, item.quantity, item.discount_pct, item.discount_flat);
    }

    /**
     * Carrega items do evento (ou template da série) e detecta billingType.
     * Heurística: se eventRow tem insurance_plan_id → 'convenio'; senão,
     * presença de items → 'particular', vazio → 'gratuito'.
     */
    async function _loadCommitmentItemsForEvent(eventId) {
        const ruleId = props.eventRow?.recurrence_id ?? null;
        const isCustomized = props.eventRow?.services_customized ?? false;
        const origPlanId = props.eventRow?.insurance_plan_id ?? null;
        const origGuide = props.eventRow?.insurance_guide_number ?? null;
        const origInsValue = props.eventRow?.insurance_value != null ? Number(props.eventRow.insurance_value) : null;

        function applyConvenio() {
            const origPsId = props.eventRow?.insurance_plan_service_id ?? null;
            actions._restoringConvenio.value = true;
            composer.form.value.insurance_plan_id = origPlanId;
            composer.form.value.insurance_guide_number = origGuide;
            composer.form.value.insurance_value = origInsValue;
            composer.form.value.insurance_plan_service_id = origPsId;
            composer.billingType.value = 'convenio';
            nextTick(() => {
                if (origPsId && planServices.value.find((s) => s.id === origPsId)) {
                    selectedPlanService.value = origPsId;
                } else {
                    selectedPlanService.value = null;
                }
                actions._restoringConvenio.value = false;
            });
        }

        if (!eventId && !ruleId) {
            commitmentItems.value = [];
            if (origPlanId) applyConvenio();
            else composer.billingType.value = 'particular';
            return;
        }
        try {
            commitmentItems.value = ruleId
                ? await _csLoadItemsOrTemplate(eventId, ruleId, { allowEmpty: isCustomized })
                : await _csLoadItems(eventId);
            if (origPlanId) applyConvenio();
            else composer.billingType.value = commitmentItems.value.length > 0 ? 'particular' : 'gratuito';
        } catch (e) {
            // eslint-disable-next-line no-console
            console.warn('[useAgendaEventPickerBilling] commitment_services load error:', e?.message);
            commitmentItems.value = [];
            if (origPlanId) applyConvenio();
            else composer.billingType.value = 'gratuito';
        }
    }

    /**
     * Setter do procedimento de convênio (form.insurance_plan_service_id).
     * Quando muda, atualiza form.insurance_value baseado no value do procedimento.
     */
    function onProcedureSelect(psId) {
        composer.form.value.insurance_plan_service_id = psId ?? null;
        if (!psId) {
            composer.form.value.insurance_value = null;
            return;
        }
        const ps = planServices.value.find((s) => s.id === psId);
        composer.form.value.insurance_value = ps?.value != null ? Number(ps.value) : null;
    }

    // ────────────────────────────────────────────────────────────────
    // Patient picker
    // ────────────────────────────────────────────────────────────────

    function selectCommitment(c) {
        if (!c?.id) return;
        composer.form.value.commitment_id = c.id;
        composer.form.value.extra_fields = {};
        if (Array.isArray(c.fields)) {
            for (const f of c.fields) composer.form.value.extra_fields[f.key] = '';
        }
        composer.step.value = 2;
        if (composer.requiresPatient.value) loadPatients(true);
    }

    function goBack() {
        if (composer.isEdit.value || !composer.allowBack.value) return;
        composer.step.value = 1;
        composer.form.value.commitment_id = null;
        composer.form.value.paciente_id = null;
        composer.form.value.paciente_nome = '';
    }

    function openPacientePicker() {
        if (!composer.requiresPatient.value) return;
        pacientePickerOpen.value = true;
        loadPatients(false);
    }

    function clearPatientsCache() {
        patients.value = [];
        pacientesError.value = '';
        pacienteSearch.value = '';
    }

    async function loadPatients(force = false) {
        try {
            if (pacientesLoading.value) return;
            if (!force && patients.value?.length) return;
            pacientesError.value = '';
            pacientesLoading.value = true;

            let q = tenantDb().from('patients')
                .select('id,nome_completo,email_principal,telefone,status,avatar_url,responsible_member_id,created_at')
                .order('created_at', { ascending: false })
                .limit(500);

            if (props.restrictPatientsToOwner && props.patientScopeOwnerId) {
                q = q.eq('responsible_member_id', props.patientScopeOwnerId);
            }

            const { data, error } = await q;
            if (error) throw error;

            patients.value = (data || []).map((r) => ({
                id: r.id,
                nome: r.nome_completo ?? '',
                email: r.email_principal ?? '',
                telefone: r.telefone ?? '',
                status: r.status ?? '',
                avatar_url: r.avatar_url ?? ''
            }));
        } catch (e) {
            pacientesError.value = e?.message || 'Falha ao carregar pacientes.';
            patients.value = [];
        } finally {
            pacientesLoading.value = false;
        }
    }

    function selectPaciente(p) {
        if (!p?.id) return;
        // Bloqueia clique em paciente arquivado/inativo — defesa em camadas:
        // o template do picker ja marca esses items como disabled, mas se
        // alguem chamar selectPaciente programaticamente (cache stale, etc),
        // a regra precisa valer.
        if (p.status && p.status !== 'Ativo') return;
        composer.form.value.paciente_id = p.id;
        composer.form.value.paciente_nome = p.nome || '';
        composer.form.value.paciente_avatar = p.avatar_url || '';
        // Sem isso, form.paciente_status fica '' e canSave nao consegue
        // aplicar getPatientAgendaPermissions — qualquer falha do filtro
        // acima vira sessao criavel com paciente fora do escopo.
        composer.form.value.paciente_status = p.status || '';
        pacientePickerOpen.value = false;
    }

    function clearPaciente() {
        composer.form.value.paciente_id = null;
        composer.form.value.paciente_nome = '';
        composer.form.value.paciente_avatar = '';
        composer.form.value.paciente_status = '';
        actions.samePatientConflict.value = null;
    }

    function openCadastroRapido() {
        cadRapidoOpen.value = true;
    }

    function abrirCadastroCompleto() {
        if (!props.newPatientRoute) return;
        // Abre em nova aba pra o user voltar pro dialog depois
        window.open(props.newPatientRoute, '_blank', 'noopener');
    }

    // ────────────────────────────────────────────────────────────────
    // Watchers
    // ────────────────────────────────────────────────────────────────

    /**
     * Auto-fill de price quando o user troca commitment em criação.
     * Ignorado em edição pra preservar o valor salvo.
     */
    watch(
        () => composer.form.value.commitment_id,
        async (newId) => {
            if (!newId || composer.isEdit.value || !composer.visible.value) return;
            await ensureServicesLoaded();
            applyDefaultPrice();
        }
    );

    /**
     * Limpa procedure + campos de convênio quando muda plano.
     * Quando seleciona convênio: zera items (exclusividade convênio vs serviços).
     * `_restoringConvenio` ignora o watch durante restauração de eventRow editado.
     */
    watch(
        () => composer.form.value.insurance_plan_id,
        (planId) => {
            if (actions._restoringConvenio.value) return;
            selectedPlanService.value = null;
            composer.form.value.insurance_plan_service_id = null;
            if (!planId) {
                composer.form.value.insurance_value = null;
                composer.form.value.insurance_guide_number = null;
                return;
            }
            commitmentItems.value = [];
            servicePickerSel.value = null;
        }
    );

    return {
        // refs do picker
        pacientePickerOpen,
        pacienteSearch,
        pacientesLoading,
        pacientesError,
        patients,
        cadRapidoOpen,
        // billing/services
        ensureServicesLoaded,
        resetServicesGate,
        applyDefaultPrice,
        addItem,
        removeItem,
        onItemChange,
        _loadCommitmentItemsForEvent,
        onProcedureSelect,
        // picker
        selectCommitment,
        goBack,
        openPacientePicker,
        clearPatientsCache,
        loadPatients,
        selectPaciente,
        clearPaciente,
        openCadastroRapido,
        abrirCadastroCompleto
    };
}
