import type { StoreOrder } from '@medusajs/types';

import type { Tables } from '@kit/supabase/database';
import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client';
import { getSupabaseServerClient } from '@kit/supabase/server-client';

import type { AnalysisOrder, TTOOrder } from '../types/order';

export async function createAnalysisOrder({
  medusaOrder,
  orderedAnalysisElements,
}: {
  medusaOrder: StoreOrder;
  orderedAnalysisElements: {
    analysisElementId?: number;
    analysisId?: number;
  }[];
}) {
  const supabase = getSupabaseServerClient();

  const {
    data: { user },
  } = await supabase.auth.getUser();
  if (!user) {
    throw new Error('User not found');
  }
  const orderResult = await supabase
    .schema('medreport')
    .from('analysis_orders')
    .insert({
      analysis_element_ids: orderedAnalysisElements
        .map(({ analysisElementId }) => analysisElementId)
        .filter(Boolean) as number[],
      analysis_ids: orderedAnalysisElements
        .map(({ analysisId }) => analysisId)
        .filter(Boolean) as number[],
      status: 'QUEUED',
      user_id: user.id,
      medusa_order_id: medusaOrder.id,
    })
    .select('id')
    .single()
    .throwOnError();

  if (orderResult.error || !orderResult.data?.id) {
    throw new Error(
      `Failed to create order, message=${orderResult.error}, data=${JSON.stringify(orderResult)}`,
    );
  }

  return orderResult.data.id;
}

export async function getAnalysisOrder({
  medusaOrderId,
  analysisOrderId,
}: {
  medusaOrderId?: string;
  analysisOrderId?: number;
}) {
  const query = getSupabaseServerAdminClient()
    .schema('medreport')
    .from('analysis_orders')
    .select('*');
  if (medusaOrderId) {
    query.eq('medusa_order_id', medusaOrderId);
  } else if (analysisOrderId) {
    query.eq('id', analysisOrderId);
  } else {
    throw new Error('Either medusaOrderId or orderId must be provided');
  }

  const { data: order, error } = await query.single();
  if (error) {
    throw new Error(
      `Failed to get order by medusaOrderId=${medusaOrderId} or analysisOrderId=${analysisOrderId}, message=${error.message}, data=${JSON.stringify(order)}`,
    );
  }
  return order as AnalysisOrder;
}

export async function getAnalysisOrders({
  orderStatus,
}: {
  orderStatus?: Tables<{ schema: 'medreport' }, 'analysis_orders'>['status'];
} = {}) {
  const client = getSupabaseServerClient();

  const {
    data: { user },
  } = await client.auth.getUser();
  if (!user) {
    throw new Error('Unauthorized');
  }

  const query = client
    .schema('medreport')
    .from('analysis_orders')
    .select('*')
    .eq('user_id', user.id);
  if (orderStatus) {
    query.eq('status', orderStatus);
  }
  const orders = await query
    .order('created_at', { ascending: false })
    .throwOnError();
  return orders.data;
}

export async function getAnalysisOrdersAdmin({
  orderStatus,
  medusaOrderId,
}: {
  orderStatus?: Tables<{ schema: 'medreport' }, 'analysis_orders'>['status'];
  medusaOrderId?: string | null;
} = {}) {
  const query = getSupabaseServerAdminClient()
    .schema('medreport')
    .from('analysis_orders')
    .select('*');
  if (orderStatus) {
    query.eq('status', orderStatus);
  }
  if (medusaOrderId) {
    query.eq('medusa_order_id', medusaOrderId);
  }
  const orders = await query
    .order('created_at', { ascending: false })
    .throwOnError();
  return orders.data;
}

export async function getTtoOrders({
  orderStatus,
  lineItemIds,
}: {
  orderStatus?: TTOOrder['status'];
  lineItemIds?: string[];
} = {}) {
  const client = getSupabaseServerClient();

  const {
    data: { user },
  } = await client.auth.getUser();
  if (!user) {
    throw new Error('Unauthorized');
  }

  const query = client
    .schema('medreport')
    .from('connected_online_reservation')
    .select('*')
    .eq('user_id', user.id);

  if (orderStatus) {
    query.eq('status', orderStatus);
  }

  if (lineItemIds?.length) {
    query.in('medusa_cart_line_item_id', lineItemIds);
  }

  const orders = await query
    .order('created_at', { ascending: false })
    .throwOnError();

  const ordersWithLocation = await Promise.all(
    orders.data.map(async (order) => ({
      ...order,
      location: await getTtoLocation(order.location_sync_id),
    })),
  );

  return ordersWithLocation;
}

export async function getTtoLocation(syncId?: number | null) {
  if (!syncId) {
    return null;
  }

  const client = getSupabaseServerClient();

  const {
    data: { user },
  } = await client.auth.getUser();

  if (!user) {
    throw new Error('Unauthorized');
  }

  const { data, error } = await client
    .schema('medreport')
    .from('connected_online_locations')
    .select('name')
    .eq('sync_id', syncId)
    .single();

  if (error) {
    throw new Error('Could not receive online locations: ', error);
  }

  return data;
}
