import type { InquiryTask, CustomerServiceChat, ChatMessage } from '@/types';
import { getSupabaseClient } from '@/lib/supabase';
import { getCurrentDataAccessScope, getVisibleBatchIdsForScope } from '@/services/dataAccessScope';

export interface InquiryBatchOption {
  batch_id: string;
  candidate_count: number;
  task_count: number;
}

interface ChatRow {
  id: string;
  batch_id: string;
  search_result_id: string | null;
  merchant_name: string;
  merchant_url: string;
  contact_url: string;
  offer_url: string;
  title: string;
  current_round: number;
  status: string;
  retry_count: number;
  extracted_data: Record<string, unknown> | null;
  ask_context: Record<string, string> | null;
  last_interacted_at: string | null;
  created_at: string;
  updated_at: string;
}

interface MessageRow {
  id: string;
  chat_id: string;
  round: number;
  direction: 'SENT' | 'RECEIVED';
  content: string;
  llm_intent?: Record<string, unknown> | null;
  created_at: string;
}

function mapChatMessages(messages: MessageRow[]): ChatMessage[] {
  return messages
    .sort((a, b) => a.created_at.localeCompare(b.created_at))
    .filter(message => !message.llm_intent)
    .map(m => ({
      role: m.direction === 'SENT' ? 'self' as const : 'other' as const,
      content: m.content,
    }));
}

async function resolveInquiryBatchScope(requestedBatchId?: string) {
  const scope = await getCurrentDataAccessScope();

  if (scope.isAdmin) {
    return {
      isAdmin: true,
      visibleBatchIds: requestedBatchId ? [requestedBatchId] : null,
    };
  }

  const visibleBatchIds = await getVisibleBatchIdsForScope(scope, { includeArchived: true });
  if (requestedBatchId) {
    return {
      isAdmin: false,
      visibleBatchIds: visibleBatchIds.includes(requestedBatchId) ? [requestedBatchId] : [],
    };
  }

  return {
    isAdmin: false,
    visibleBatchIds,
  };
}

export async function fetchInquiryTasks(params?: {
  batchId?: string;
  status?: string;
}): Promise<InquiryTask[]> {
  const supabase = getSupabaseClient();
  const scope = await resolveInquiryBatchScope(params?.batchId);

  if (!scope.isAdmin && (scope.visibleBatchIds?.length ?? 0) === 0) {
    return [];
  }

  let query = supabase
    .from('customer_service_chats')
    .select('*')
    .order('updated_at', { ascending: false });

  if (scope.visibleBatchIds) {
    query = query.in('batch_id', scope.visibleBatchIds);
  } else if (params?.batchId) {
    query = query.eq('batch_id', params.batchId);
  }
  if (params?.status && params.status !== 'all') {
    query = query.eq('status', params.status);
  }

  const { data: chats, error: chatsError } = await query;
  if (chatsError) throw chatsError;
  if (!chats || chats.length === 0) return [];

  // Fetch all related chat messages
  const chatIds = chats.map((c: ChatRow) => c.id);
  const { data: messages, error: msgsError } = await supabase
    .from('chat_messages')
    .select('*')
    .in('chat_id', chatIds)
    .order('created_at', { ascending: true });

  if (msgsError) throw msgsError;

  const msgMap = new Map<string, MessageRow[]>();
  for (const msg of (messages ?? []) as MessageRow[]) {
    const arr = msgMap.get(msg.chat_id) ?? [];
    arr.push(msg);
    msgMap.set(msg.chat_id, arr);
  }

  return (chats as ChatRow[]).map(chat => ({
    id: chat.id,
    batch_id: chat.batch_id,
    merchant_name: chat.merchant_name,
    offer_url: chat.offer_url,
    title: chat.title,
    current_round: chat.current_round,
    status: chat.status as InquiryTask['status'],
    retry_count: chat.retry_count,
    extracted_data: chat.extracted_data,
    ask_context: chat.ask_context ?? {},
    chat_history: mapChatMessages(msgMap.get(chat.id) ?? []),
    created_at: chat.created_at,
    updated_at: chat.updated_at,
    last_interacted_at: chat.last_interacted_at,
  }));
}

export async function fetchCustomerServiceChats(params?: {
  search?: string;
}): Promise<CustomerServiceChat[]> {
  const supabase = getSupabaseClient();
  const scope = await resolveInquiryBatchScope();

  if (!scope.isAdmin && (scope.visibleBatchIds?.length ?? 0) === 0) {
    return [];
  }

  let query = supabase
    .from('customer_service_chats')
    .select('*')
    .order('created_at', { ascending: false });

  if (scope.visibleBatchIds) {
    query = query.in('batch_id', scope.visibleBatchIds);
  }

  const { data: chats, error: chatsError } = await query;
  if (chatsError) throw chatsError;
  if (!chats || chats.length === 0) return [];

  const chatIds = chats.map((c: ChatRow) => c.id);
  const { data: messages, error: msgsError } = await supabase
    .from('chat_messages')
    .select('*')
    .in('chat_id', chatIds)
    .order('created_at', { ascending: true });

  if (msgsError) throw msgsError;

  const msgMap = new Map<string, MessageRow[]>();
  for (const msg of (messages ?? []) as MessageRow[]) {
    const arr = msgMap.get(msg.chat_id) ?? [];
    arr.push(msg);
    msgMap.set(msg.chat_id, arr);
  }

  let results = (chats as ChatRow[]).map(chat => ({
    id: chat.id,
    product_url: chat.offer_url,
    batch_id: chat.batch_id,
    search_result_id: chat.search_result_id ?? undefined,
    contact_url: chat.contact_url,
    merchant_name: chat.merchant_name,
    title: chat.title,
    current_round: chat.current_round,
    status: chat.status,
    last_interacted_at: chat.last_interacted_at,
    chat_history: mapChatMessages(msgMap.get(chat.id) ?? []),
    created_at: chat.created_at,
  }));

  if (params?.search) {
    const s = params.search.toLowerCase();
    results = results.filter(c =>
      c.product_url.toLowerCase().includes(s) ||
      (c.contact_url ?? '').toLowerCase().includes(s) ||
      (c.merchant_name ?? '').toLowerCase().includes(s) ||
      (c.title ?? '').toLowerCase().includes(s) ||
      c.chat_history.some(m => m.content.toLowerCase().includes(s)),
    );
  }

  return results;
}

export async function fetchInquiryBatchIds(): Promise<string[]> {
  const options = await fetchInquiryBatchOptions();
  return options.map(option => option.batch_id);
}

export async function fetchInquiryBatchOptions(): Promise<InquiryBatchOption[]> {
  const supabase = getSupabaseClient();
  const scope = await resolveInquiryBatchScope();

  if (!scope.isAdmin && (scope.visibleBatchIds?.length ?? 0) === 0) {
    return [];
  }

  const chatQuery = supabase.from('customer_service_chats').select('batch_id');
  const finalQuery = supabase.from('final_result_products').select('batch_id');

  const [chatRes, finalRes] = scope.visibleBatchIds
    ? await Promise.all([
      chatQuery.in('batch_id', scope.visibleBatchIds),
      finalQuery.in('batch_id', scope.visibleBatchIds),
    ])
    : await Promise.all([chatQuery, finalQuery]);

  if (chatRes.error) throw chatRes.error;
  if (finalRes.error) throw finalRes.error;

  const taskCounts = new Map<string, number>();
  const finalCounts = new Map<string, number>();

  for (const row of chatRes.data ?? []) {
    if (!row.batch_id) continue;
    taskCounts.set(row.batch_id, (taskCounts.get(row.batch_id) ?? 0) + 1);
  }

  for (const row of finalRes.data ?? []) {
    if (!row.batch_id) continue;
    finalCounts.set(row.batch_id, (finalCounts.get(row.batch_id) ?? 0) + 1);
  }

  const allBatchIds = new Set<string>([
    ...taskCounts.keys(),
    ...finalCounts.keys(),
  ]);

  return [...allBatchIds]
    .sort((left, right) => right.localeCompare(left))
    .map(batch_id => ({
      batch_id,
      candidate_count: finalCounts.get(batch_id) ?? 0,
      task_count: taskCounts.get(batch_id) ?? 0,
    }));
}
