108 lines
3.2 KiB
TypeScript

// MÓDULO 2.1: APPOINTMENTS - /appointments/cancel
import { validateExternalAuth } from "../_shared/auth.ts";
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":
"authorization, x-client-info, apikey, content-type",
};
function externalRest(path: string, method: string, body?: any): Promise<any> {
const url = `${Deno.env.get("EXTERNAL_SUPABASE_URL")}/rest/v1/${path}`;
return fetch(url, {
method,
headers: {
"Content-Type": "application/json",
apikey: Deno.env.get("EXTERNAL_SUPABASE_KEY")!,
Authorization: `Bearer ${Deno.env.get("EXTERNAL_SUPABASE_KEY")}`,
Prefer: "return=representation",
},
body: body ? JSON.stringify(body) : undefined,
}).then((r) => r.json());
}
Deno.serve(async (req) => {
if (req.method === "OPTIONS")
return new Response("ok", { headers: corsHeaders });
try {
const authHeader = req.headers.get("Authorization");
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_ANON_KEY")!,
{ global: { headers: { Authorization: authHeader! } } }
);
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) throw new Error("Unauthorized");
const { appointment_id, reason } = await req.json();
// Buscar appointment para pegar doctor_id e date
const appointment = await externalRest(
`appointments?id=eq.${appointment_id}`,
"GET"
);
const apt = appointment[0];
// Cancelar no Supabase externo
await externalRest(`appointments?id=eq.${appointment_id}`, "PATCH", {
status: "cancelled",
cancellation_reason: reason,
});
// Log
await supabase.from("user_actions").insert({
user_id: user.id,
external_user_id: apt.patient_id,
action_category: "appointment",
action_type: "cancel",
action_description: `Cancelled appointment ${appointment_id}`,
resource_type: "appointment",
resource_id: appointment_id,
});
// Adicionar próximo da waitlist se existir
const { data: waitlistMatch } = await supabase
.from("waitlist")
.select("*")
.eq("doctor_id", apt.doctor_id)
.eq("status", "waiting")
.order("priority", { ascending: false })
.order("created_at", { ascending: true })
.limit(1);
if (waitlistMatch && waitlistMatch.length > 0) {
// Notificar paciente da waitlist
await supabase.from("notifications_queue").insert({
recipient_id: waitlistMatch[0].patient_id,
type: "sms",
template: "waitlist_slot_available",
data: {
appointment_date: apt.appointment_date,
appointment_time: apt.appointment_time,
},
});
}
return new Response(
JSON.stringify({
success: true,
message: "Appointment cancelled",
waitlist_notified: !!waitlistMatch,
}),
{ headers: { ...corsHeaders, "Content-Type": "application/json" } }
);
} catch (error: any) {
return new Response(
JSON.stringify({ success: false, error: error.message }),
{
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" },
}
);
}
});