/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/patients/composables/usePatientSessions.js
|
| Carrega sessões (agenda_eventos) do paciente. Limit 100 reais + expansão
| de recorrências do owner dentro de uma janela de 18 meses. Merge desc por
| inicio_em pra alimentar prontuário/timeline.
|
| I/O delegada ao patientsRepository. Expansão de recorrência continua via
| useRecurrence (composable da agenda — não é supabase direto, é orquestração).
|--------------------------------------------------------------------------
*/
import { ref, computed } from 'vue';
import { supabase } from '@/lib/supabase/client';
import { useRecurrence } from '@/features/agenda/composables/useRecurrence';
import {
    listSessionsByPatient,
    createPatientSession,
    updatePatientSessionStatus,
    findSessionByRecurrence
} from '@/features/patients/services/patientsRepository';

export function usePatientSessions() {
    const sessions = ref([]);
    const loading = ref(false);
    const error = ref('');
    const busy = ref(false);
    // State per-instância — não vaza
    let _lastPatientId = null;

    const { loadAndExpand } = useRecurrence();

    async function load(patientId) {
        _lastPatientId = patientId || null;
        if (!patientId) {
            sessions.value = [];
            return;
        }
        loading.value = true;
        error.value = '';
        sessions.value = [];
        try {
            // 1. Linhas reais via repository
            const realRows = await listSessionsByPatient(patientId);

            // 2. Expande recorrências do owner + filtra pra este paciente.
            //    Range: 6 meses atrás → 12 meses à frente (histórico + ~1 ano de séries futuras).
            let virtualOccs = [];
            try {
                // auth.getUser é context, não data query — pode ficar inline.
                const { data: userData } = await supabase.auth.getUser();
                const ownerId = userData?.user?.id || null;
                if (ownerId) {
                    let tenantId = null;
                    try {
                        const { useTenantStore } = await import('@/stores/tenantStore');
                        tenantId = useTenantStore().activeTenantId || null;
                    } catch {
                        /* sem tenant store — segue */
                    }

                    const now = new Date();
                    const rangeStart = new Date(now.getFullYear(), now.getMonth() - 6, 1);
                    const rangeEnd = new Date(now.getFullYear() + 1, now.getMonth(), 1);

                    const expanded = await loadAndExpand(ownerId, rangeStart, rangeEnd, realRows, tenantId);
                    virtualOccs = expanded.filter((r) => r.is_occurrence && r.patient_id === patientId);
                }
            } catch (e) {
                // Fallback silencioso — UI segue só com sessões reais.
                // eslint-disable-next-line no-console
                console.warn('[usePatientSessions] recurrence expand falhou:', e);
            }

            // 3. Merge desc por inicio_em
            const merged = [...realRows, ...virtualOccs];
            merged.sort((a, b) => String(b.inicio_em).localeCompare(String(a.inicio_em)));
            sessions.value = merged;
        } catch (e) {
            error.value = e?.message || 'Falha ao carregar sessões.';
            sessions.value = [];
        } finally {
            loading.value = false;
        }
    }

    // ─── Computeds derivados ────────────────────────────────

    const proximaSessao = computed(() => {
        const now = Date.now();
        return (
            [...sessions.value]
                .filter((s) => s.inicio_em && new Date(s.inicio_em).getTime() >= now)
                .sort((a, b) => new Date(a.inicio_em) - new Date(b.inicio_em))[0] || null
        );
    });

    const ultimaSessao = computed(() => {
        const now = Date.now();
        return (
            sessions.value
                .filter((s) => s.inicio_em && new Date(s.inicio_em).getTime() < now)
                .sort((a, b) => new Date(b.inicio_em) - new Date(a.inicio_em))[0] || null
        );
    });

    const totalSessoes = computed(() => sessions.value.length);

    const totalRealizadas = computed(() => sessions.value.filter((s) => /realiz|present/i.test(String(s.status || ''))).length);
    const totalFaltas = computed(() => sessions.value.filter((s) => /falt/i.test(String(s.status || ''))).length);
    const totalCanceladas = computed(() => sessions.value.filter((s) => /cancel|remarca/i.test(String(s.status || ''))).length);

    const ultimasAtendidas = computed(() =>
        sessions.value.filter((s) => /realiz|present|falt|cancel|remarca/i.test(String(s.status || ''))).slice(0, 6)
    );

    // ─── Mutations ─────────────────────────────────────────

    async function createSession(patientId, payload = {}) {
        if (!patientId || busy.value) return { ok: false, error: 'busy' };
        if (!payload?.inicio_em || !payload?.fim_em) {
            return { ok: false, error: 'Início/fim obrigatórios' };
        }
        busy.value = true;
        try {
            const data = await createPatientSession(patientId, payload);
            if (_lastPatientId) await load(_lastPatientId);
            return { ok: true, data };
        } catch (e) {
            return { ok: false, error: e?.message || 'Erro ao agendar sessão' };
        } finally {
            busy.value = false;
        }
    }

    /**
     * Atualiza status — aceita UUID string OU row inteira. Se virtual
     * (is_occurrence), materializa antes via createPatientSession.
     */
    async function updateStatus(sessionOrId, novoStatus) {
        if (!sessionOrId || busy.value) return { ok: false, error: 'busy' };
        busy.value = true;
        try {
            const isObject = typeof sessionOrId === 'object' && sessionOrId !== null;
            const isVirtual = isObject && !!sessionOrId.is_occurrence;

            if (!isVirtual) {
                const realId = isObject ? sessionOrId.id : sessionOrId;
                if (!realId || typeof realId !== 'string' || realId.startsWith('rec::')) {
                    return { ok: false, error: 'ID inválido pra atualizar status (virtual sem row).' };
                }
                await updatePatientSessionStatus(realId, novoStatus);
                if (_lastPatientId) await load(_lastPatientId);
                return { ok: true };
            }

            // Virtual: materializar antes
            const row = sessionOrId;
            const rid = row.recurrence_id;
            const rDate = row.recurrence_date || row.original_date || String(row.inicio_em || '').slice(0, 10);

            if (!rid || !rDate) {
                return { ok: false, error: 'Ocorrência sem recurrence_id/date — não dá pra materializar.' };
            }

            const existing = await findSessionByRecurrence(rid, rDate);
            if (existing?.id) {
                await updatePatientSessionStatus(existing.id, novoStatus);
            } else {
                // Cria row real materializada (createPatientSession suporta recurrence_id/date)
                await createPatientSession(row.patient_id || row.paciente_id || _lastPatientId, {
                    inicio_em: row.inicio_em,
                    fim_em: row.fim_em,
                    status: novoStatus,
                    modalidade: row.modalidade || 'presencial',
                    tipo: row.tipo || 'sessao',
                    titulo: row.titulo,
                    titulo_custom: row.titulo_custom,
                    observacoes: row.observacoes,
                    recurrence_id: rid,
                    recurrence_date: rDate,
                    determined_commitment_id: row.determined_commitment_id,
                    price: row.price
                });
            }

            if (_lastPatientId) await load(_lastPatientId);
            return { ok: true };
        } catch (e) {
            return { ok: false, error: e?.message || 'Erro ao atualizar status' };
        } finally {
            busy.value = false;
        }
    }

    return {
        sessions,
        loading,
        error,
        busy,
        load,
        updateStatus,
        createSession,
        proximaSessao,
        ultimaSessao,
        totalSessoes,
        totalRealizadas,
        totalFaltas,
        totalCanceladas,
        ultimasAtendidas
    };
}
