import { API_ENDPOINTS } from '@/shared/constants/apiEndpoints';
import { api } from '@/shared/utils/api';
import {
  type SavedFilter,
  type SavedFiltersList,
  type SearchRequest,
  type SearchSuggestion,
  type SearchTicketsResult,
  buildSearchFiltersPayload,
  isQuickFilter,
  isSavedFilter,
  isSearchSuggestion,
  parseSearchTicketsResult,
  parseTicketListFromUnknown,
} from '@/features/search/types/search.types';
import { isPaginatedResponse } from '@/shared/types/pagination.types';
import { isTicketSummary } from '@/features/tickets/types/ticket.types';

function buildSearchBody(request: SearchRequest): Record<string, unknown> {
  const body: Record<string, unknown> = {
    per_page: request.per_page ?? 25,
    page: request.page ?? 1,
    sort_by: request.sort_by ?? 'created_at',
    sort_direction: request.sort_direction ?? 'desc',
  };

  if (request.query?.trim()) {
    body.query = request.query.trim();
  }

  if (request.department_id) {
    body.department_id = request.department_id;
  }

  const filters = request.filters ? buildSearchFiltersPayload(request.filters) : {};
  if (Object.keys(filters).length > 0) {
    body.filters = filters;
  }

  return body;
}

export async function searchTickets(request: SearchRequest): Promise<SearchTicketsResult> {
  const raw: unknown = await api.post(API_ENDPOINTS.SEARCH.TICKETS, buildSearchBody(request));
  return parseSearchTicketsResult(raw);
}

export async function fetchSearchSuggestions(): Promise<SearchSuggestion[]> {
  const raw: unknown = await api.get(API_ENDPOINTS.SEARCH.SUGGESTIONS);

  if (typeof raw === 'object' && raw !== null && 'data' in raw) {
    const data = (raw as { data: unknown }).data;
    if (Array.isArray(data) && data.every(isSearchSuggestion)) {
      return data;
    }
  }

  if (Array.isArray(raw) && raw.every(isSearchSuggestion)) {
    return raw;
  }

  return [];
}

const QUICK_ENDPOINTS: Record<string, string> = {
  'my-tickets': API_ENDPOINTS.SEARCH.QUICK_MY_TICKETS,
  unassigned: API_ENDPOINTS.SEARCH.QUICK_UNASSIGNED,
  overdue: API_ENDPOINTS.SEARCH.QUICK_OVERDUE,
  'high-priority': API_ENDPOINTS.SEARCH.QUICK_HIGH_PRIORITY,
};

export async function fetchQuickFilterTickets(
  quickId: string,
  perPage = 25,
  page = 1,
): Promise<SearchTicketsResult> {
  const endpoint = QUICK_ENDPOINTS[quickId];
  if (!endpoint) {
    throw new Error(`Unknown quick filter: ${quickId}`);
  }

  const raw: unknown = await api.get(`${endpoint}?per_page=${perPage}&page=${page}`);
  const tickets = parseTicketListFromUnknown(raw);

  let pagination = {
    current_page: page,
    per_page: perPage,
    total_pages: 1,
    total_items: tickets.length,
  };

  if (isPaginatedResponse(raw, isTicketSummary)) {
    pagination = {
      current_page: raw.meta.current_page,
      per_page: raw.meta.per_page,
      total_pages: raw.meta.last_page,
      total_items: raw.meta.total,
    };
  }

  return {
    tickets,
    total_count: pagination.total_items,
    search_time_ms: null,
    filters_applied: {},
    pagination,
  };
}

export async function fetchSavedFilters(): Promise<SavedFiltersList> {
  const raw: unknown = await api.get(API_ENDPOINTS.FILTERS.LIST);

  if (typeof raw !== 'object' || raw === null) {
    throw new Error('Invalid saved filters response');
  }

  const data =
    'data' in raw && typeof (raw as { data: unknown }).data === 'object'
      ? ((raw as { data: Record<string, unknown> }).data)
      : (raw as Record<string, unknown>);

  const personal = Array.isArray(data.personal)
    ? data.personal.filter(isSavedFilter)
    : [];
  const shared = Array.isArray(data.shared) ? data.shared.filter(isSavedFilter) : [];
  const quick = Array.isArray(data.quick) ? data.quick.filter(isQuickFilter) : [];

  return { personal, shared, quick };
}

export async function applySavedFilter(
  filterId: string,
  perPage = 25,
  page = 1,
): Promise<SearchTicketsResult> {
  const raw: unknown = await api.post(
    `${API_ENDPOINTS.FILTERS.APPLY(filterId)}?per_page=${perPage}&page=${page}`,
  );
  const tickets = parseTicketListFromUnknown(raw);

  let pagination = {
    current_page: page,
    per_page: perPage,
    total_pages: 1,
    total_items: tickets.length,
  };

  if (isPaginatedResponse(raw, isTicketSummary)) {
    pagination = {
      current_page: raw.meta.current_page,
      per_page: raw.meta.per_page,
      total_pages: raw.meta.last_page,
      total_items: raw.meta.total,
    };
  }

  return {
    tickets,
    total_count: pagination.total_items,
    search_time_ms: null,
    filters_applied: {},
    pagination,
  };
}

export interface CreateSavedFilterPayload {
  name: string;
  description?: string;
  filter_data: Record<string, unknown>;
  is_shared?: boolean;
  is_default?: boolean;
}

export async function createSavedFilter(
  payload: CreateSavedFilterPayload,
): Promise<SavedFilter> {
  const raw: unknown = await api.post(API_ENDPOINTS.FILTERS.CREATE, payload);

  if (typeof raw === 'object' && raw !== null && 'data' in raw) {
    const data = (raw as { data: unknown }).data;
    if (isSavedFilter(data)) {
      return data;
    }
  }

  if (isSavedFilter(raw)) {
    return raw;
  }

  throw new Error('Invalid create filter response');
}

export async function deleteSavedFilter(filterId: string): Promise<void> {
  await api.delete(API_ENDPOINTS.FILTERS.DELETE(filterId));
}
