import { getOrderUpdateForDeliveryInvitationAction, hashInvitationToken, isActiveInvitationState, } from "../_shared/delivery-invitations.ts"; import { createServiceClient } from "../_shared/chatbot.ts"; import { insertIntegrationEvent } from "../_shared/integration-events.ts"; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type", }; Deno.serve(async (request) => { if (request.method === "OPTIONS") { return new Response("ok", { headers: corsHeaders }); } if (request.method !== "POST") { return new Response(JSON.stringify({ error: "Method not allowed" }), { status: 405, headers: { ...corsHeaders, "Content-Type": "application/json", }, }); } try { const body = (await request.json()) as { token?: string; deliveryDate?: string; deliveryTime?: string; }; if (!body.token) { return new Response(JSON.stringify({ error: "token is required" }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json", }, }); } const tokenHash = await hashInvitationToken(body.token); const supabase = createServiceClient(); const { data: invitation, error: invitationError } = await supabase .from("delivery_invitations") .select("*") .eq("token_hash", tokenHash) .single(); if (invitationError) { if (invitationError.code === "PGRST116") { return new Response( JSON.stringify({ ok: false, error: "Invitation not found" }), { status: 404, headers: { ...corsHeaders, "Content-Type": "application/json", }, }, ); } throw invitationError; } const { data: currentOrder, error: orderError } = await supabase .from("orders") .select("id, status, delivery_agreement_status") .eq("id", invitation.order_id) .single(); if (orderError) { throw orderError; } if (!isActiveInvitationState(invitation.state) || !["Ожидает ответа клиента", "Ожидает согласования доставки"].includes(currentOrder.status)) { return new Response( JSON.stringify({ ok: false, error: "Invitation is no longer active", }), { status: 409, headers: { ...corsHeaders, "Content-Type": "application/json", }, }, ); } const orderUpdate = getOrderUpdateForDeliveryInvitationAction("confirm_delivery_choice"); const deliveryDate = body.deliveryDate || new Date().toISOString().slice(0, 10); const deliveryTime = body.deliveryTime || "Первая половина дня"; const { error: invitationUpdateError } = await supabase .from("delivery_invitations") .update({ state: "agreed", delivery_date: deliveryDate, delivery_time: deliveryTime, confirmed_at: new Date().toISOString(), }) .eq("id", invitation.id); if (invitationUpdateError) { throw invitationUpdateError; } const { error: orderUpdateError } = await supabase .from("orders") .update({ status: orderUpdate?.status, delivery_agreement_status: orderUpdate?.deliveryAgreementStatus, }) .eq("id", invitation.order_id); if (orderUpdateError) { throw orderUpdateError; } const { error: slotError } = await supabase.from("delivery_slots").insert({ order_id: invitation.order_id, delivery_date: deliveryDate, delivery_time: deliveryTime, logistician_id: null, status: "confirmed_by_client", }); if (slotError) { throw slotError; } const { error: historyError } = await supabase.from("order_history").insert({ order_id: invitation.order_id, action: "Подтверждение выбора доставки клиентом", old_status: currentOrder.status, new_status: orderUpdate?.status, metadata: { old_delivery_agreement_status: currentOrder.delivery_agreement_status, new_delivery_agreement_status: orderUpdate?.deliveryAgreementStatus, delivery_date: deliveryDate, delivery_time: deliveryTime, }, }); if (historyError) { throw historyError; } await insertIntegrationEvent(supabase, { order_id: invitation.order_id, event_type: "delivery_choice_confirmed", direction: "inbound", status: "success", payload: { delivery_date: deliveryDate, delivery_time: deliveryTime, }, }); return new Response( JSON.stringify({ ok: true, orderId: invitation.order_id, status: orderUpdate?.status, deliveryAgreementStatus: orderUpdate?.deliveryAgreementStatus, }), { headers: { ...corsHeaders, "Content-Type": "application/json", }, }, ); } catch (error) { return new Response( JSON.stringify({ ok: false, error: error instanceof Error ? error.message : "Unexpected error", }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json", }, }, ); } });