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

import type { IMaterialGroup, IUuringElement } from './medipost/medipost.types';

export type AnalysisElement = Tables<
  { schema: 'medreport' },
  'analysis_elements'
> & {
  analysis_groups: Tables<{ schema: 'medreport' }, 'analysis_groups'>;
};

export async function getAnalysisElements({
  getAll,
  originalIds,
  ids,
  analysisGroupId,
}: {
  getAll?: boolean;
  originalIds?: string[];
  ids?: number[];
  analysisGroupId?: number;
}): Promise<AnalysisElement[]> {
  const query = getSupabaseServerAdminClient()
    .schema('medreport')
    .from('analysis_elements')
    .select(`*, analysis_groups(*)`)
    .order('order', { ascending: true });

  const hasOriginalIdsFilter = Array.isArray(originalIds);
  const hasIdsFilter = Array.isArray(ids);
  const hasAnalysisGroupIdFilter = typeof analysisGroupId === 'number';

  if (
    !hasOriginalIdsFilter &&
    !hasIdsFilter &&
    !hasAnalysisGroupIdFilter &&
    getAll !== true
  ) {
    throw new Error(
      'Either originalIds, ids, or analysisGroupId must be provided',
    );
  }

  if (hasOriginalIdsFilter) {
    query.in('analysis_id_original', [...new Set(originalIds)]);
  }

  if (hasIdsFilter) {
    query.in('id', ids);
  }

  if (hasAnalysisGroupIdFilter) {
    query.eq('parent_analysis_group_id', analysisGroupId);
  }

  const { data: analysisElements, error } = await query;

  if (error) {
    throw new Error(`Failed to get analysis elements: ${error.message}`);
  }

  return analysisElements ?? [];
}

export async function getAnalysisElementsAdmin({
  ids,
}: {
  ids?: number[];
} = {}): Promise<AnalysisElement[]> {
  const query = getSupabaseServerAdminClient()
    .schema('medreport')
    .from('analysis_elements')
    .select(`*, analysis_groups(*)`)
    .order('order', { ascending: true });

  if (Array.isArray(ids)) {
    query.in('id', ids);
  }

  const { data: analysisElements, error } = await query;

  if (error) {
    throw new Error(`Failed to get analysis elements: ${error.message}`);
  }

  return analysisElements ?? [];
}

export async function createAnalysisElement({
  analysisElement,
  analysisGroupId,
  materialGroups,
}: {
  analysisElement: IUuringElement;
  analysisGroupId: number;
  materialGroups: IMaterialGroup[];
}) {
  const { data: insertedAnalysisElement, error } =
    await getSupabaseServerAdminClient()
      .schema('medreport')
      .from('analysis_elements')
      .upsert(
        {
          analysis_id_oid: analysisElement.UuringIdOID,
          analysis_id_original: analysisElement.UuringId,
          tehik_short_loinc: analysisElement.TLyhend,
          tehik_loinc_name: analysisElement.KNimetus,
          analysis_name_lab: analysisElement.UuringNimi,
          order: analysisElement.Jarjekord,
          parent_analysis_group_id: analysisGroupId,
          material_groups: materialGroups as unknown as Json[],
        },
        { onConflict: 'analysis_id_original', ignoreDuplicates: false },
      )
      .select('id');

  const id = insertedAnalysisElement?.[0]?.id;
  if (error || !id) {
    throw new Error(
      `Failed to insert analysis element (id: ${analysisElement.UuringId}), error: ${error?.message}`,
    );
  }

  return id;
}
