/**
 * Fogbreak API Client
 * Centralized HTTP client for all backend communication.
 * All requests include tenant_id for multi-tenant isolation.
 */

import { getToken } from './auth';
import { queueOfflineAction, isOnline } from './offline';

const DEFAULT_TIMEOUT = 15000;

export interface APIConfig {
  baseURL: string;
  tenantId: string | null;
}

let config: APIConfig = {
  baseURL: '',
  tenantId: null,
};

export function configureAPI(baseURL: string, tenantId: string | null): void {
  config = { baseURL, tenantId };
}

export function getAPIConfig(): APIConfig {
  return { ...config };
}

interface APIResponse<T = unknown> {
  success: boolean;
  data?: T;
  message?: string;
  error?: string;
  code?: number;
}

interface RequestOptions {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  body?: Record<string, unknown> | FormData;
  headers?: Record<string, string>;
  timeout?: number;
  offlineAction?: string;
}

async function request<T = unknown>(
  endpoint: string,
  options: RequestOptions = {}
): Promise<APIResponse<T>> {
  const { method = 'GET', body, headers = {}, timeout = DEFAULT_TIMEOUT, offlineAction } = options;

  const online = await isOnline();
  if (!online && offlineAction && body) {
    await queueOfflineAction({
      type: offlineAction,
      endpoint,
      method,
      body: body instanceof FormData ? {} : body,
      timestamp: Date.now(),
    });
    return { success: true, message: 'Queued for sync when online' };
  }

  if (!online) {
    return { success: false, error: 'No network connection', code: 0 };
  }

  const token = await getToken();
  const url = new URL(endpoint, config.baseURL);

  if (config.tenantId) {
    url.searchParams.set('tenant_id', config.tenantId);
  }

  const fetchHeaders: Record<string, string> = {
    ...headers,
  };

  if (token) {
    fetchHeaders['Authorization'] = `Bearer ${token}`;
  }

  let fetchBody: string | FormData | undefined;
  if (body) {
    if (body instanceof FormData) {
      fetchBody = body;
    } else {
      fetchHeaders['Content-Type'] = 'application/json';
      fetchBody = JSON.stringify(body);
    }
  }

  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url.toString(), {
      method,
      headers: fetchHeaders,
      body: fetchBody,
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    const json = await response.json();
    return json as APIResponse<T>;
  } catch (err: unknown) {
    clearTimeout(timeoutId);
    const message = err instanceof Error ? err.message : 'Request failed';
    if (message.includes('aborted')) {
      return { success: false, error: 'Request timed out', code: 408 };
    }
    return { success: false, error: message, code: 0 };
  }
}

// ── Auth ──

export function login(email: string, password: string) {
  return request('/api/auth.php?action=login', {
    method: 'POST',
    body: { email, password },
  });
}

export function loginMagicLink(token: string) {
  return request('/api/auth.php?action=magic_link', {
    method: 'POST',
    body: { token },
  });
}

export function getProfile() {
  return request('/api/auth.php?action=profile');
}

// ── Clients (FUB replacement) ──

export interface Client {
  id: number;
  tenant_id: string | null;
  first_name: string;
  last_name: string;
  email: string;
  phone: string;
  lifecycle: 'lead' | 'active' | 'closed' | 'repeat';
  lead_score: number;
  source: string;
  assigned_agent_id: number | null;
  notes: string;
  created_at: string;
  updated_at: string;
}

export function getClients(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<Client[]>(`/api/admin.php?action=getClients${qs}`);
}

export function getClient(id: number) {
  return request<Client>(`/api/admin.php?action=getClient&id=${id}`);
}

export function createClient(data: Partial<Client>) {
  return request<Client>('/api/admin.php?action=createClient', {
    method: 'POST',
    body: data as Record<string, unknown>,
    offlineAction: 'create_client',
  });
}

export function updateClient(id: number, data: Partial<Client>) {
  return request<Client>('/api/admin.php?action=updateClient', {
    method: 'POST',
    body: { id, ...data } as Record<string, unknown>,
    offlineAction: 'update_client',
  });
}

export function getClientTimeline(clientId: number) {
  return request(`/api/admin.php?action=getInteractions&client_id=${clientId}`);
}

export function logInteraction(data: Record<string, unknown>) {
  return request('/api/admin.php?action=createInteraction', {
    method: 'POST',
    body: data,
    offlineAction: 'log_interaction',
  });
}

// ── Showings (ShowingTime replacement) ──

export interface Showing {
  id: number;
  tenant_id: string | null;
  property_id: number;
  client_id: number;
  agent_id: number;
  showing_date: string;
  showing_time: string;
  status: 'requested' | 'confirmed' | 'cancelled' | 'completed';
  instructions: string;
  lockbox_code: string;
  feedback: string | null;
  rating: number | null;
  latitude: number | null;
  longitude: number | null;
  created_at: string;
}

export function getShowings(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<Showing[]>(`/api/admin.php?action=getShowings${qs}`);
}

export function getTodayShowings() {
  const today = new Date().toISOString().split('T')[0];
  return request<Showing[]>(`/api/admin.php?action=getShowings&date=${today}`);
}

export function updateShowingStatus(id: number, status: Showing['status']) {
  return request('/api/admin.php?action=updateShowing', {
    method: 'POST',
    body: { id, status },
    offlineAction: 'update_showing',
  });
}

export function submitShowingFeedback(id: number, feedback: string, rating: number) {
  return request('/api/admin.php?action=submitShowingFeedback', {
    method: 'POST',
    body: { id, feedback, rating },
    offlineAction: 'submit_feedback',
  });
}

// ── Deals (Paperless Pipeline replacement) ──

export interface Deal {
  id: number;
  tenant_id: string | null;
  client_id: number;
  property_id: number | null;
  property_address: string;
  deal_type: 'buy' | 'sell' | 'dual';
  phase: number;
  phase_name: string;
  status: 'active' | 'pending' | 'closed' | 'cancelled';
  price: number;
  jurisdiction: string;
  close_date: string | null;
  agent_id: number;
  created_at: string;
  updated_at: string;
}

export function getDeals(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<Deal[]>(`/api/transactions.php?action=getTransactions${qs}`);
}

export function getDeal(id: number) {
  return request<Deal>(`/api/transactions.php?action=getTransaction&id=${id}`);
}

export function getDealTasks(dealId: number) {
  return request(`/api/admin.php?action=getTasks&deal_id=${dealId}`);
}

export function updateTask(taskId: number, data: Record<string, unknown>) {
  return request('/api/admin.php?action=updateTask', {
    method: 'POST',
    body: { id: taskId, ...data },
    offlineAction: 'update_task',
  });
}

export function getComplianceItems(dealId: number) {
  return request(`/api/transactions.php?action=getComplianceItems&transaction_id=${dealId}`);
}

export function getDeadlines(dealId: number) {
  return request(`/api/deadlines.php?action=getDeadlines&transaction_id=${dealId}`);
}

// ── Properties (RealScout replacement) ──

export interface Property {
  id: number;
  tenant_id: string | null;
  mls_number: string;
  address: string;
  city: string;
  state: string;
  zip: string;
  price: number;
  bedrooms: number;
  bathrooms: number;
  sqft: number;
  lot_size: string;
  property_type: string;
  status: 'active' | 'pending' | 'sold' | 'withdrawn';
  description: string;
  photos: string[];
  latitude: number | null;
  longitude: number | null;
  listing_agent_id: number | null;
  created_at: string;
  updated_at: string;
}

export function getProperties(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<Property[]>(`/api/properties.php?action=getProperties${qs}`);
}

export function getProperty(id: number) {
  return request<Property>(`/api/properties.php?action=getProperty&id=${id}`);
}

export function getPropertyMatches(clientId: number) {
  return request<Property[]>(`/api/properties.php?action=getMatches&client_id=${clientId}`);
}

export function getNearbyProperties(lat: number, lng: number, radiusMiles: number) {
  return request<Property[]>(
    `/api/properties.php?action=getNearby&lat=${lat}&lng=${lng}&radius=${radiusMiles}`
  );
}

// ── Email ──

export interface EmailMessage {
  id: number;
  tenant_id: string | null;
  from_address: string;
  to_address: string;
  subject: string;
  body: string;
  body_html: string;
  thread_id: string;
  is_read: boolean;
  is_outbound: boolean;
  client_id: number | null;
  created_at: string;
}

export function getEmails(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<EmailMessage[]>(`/api/email.php?action=getInbox${qs}`);
}

export function getEmailThread(threadId: string) {
  return request<EmailMessage[]>(`/api/email.php?action=getThread&thread_id=${threadId}`);
}

export function sendEmail(data: Record<string, unknown>) {
  return request('/api/email.php?action=send', {
    method: 'POST',
    body: data,
  });
}

export function getAIDraft(data: Record<string, unknown>) {
  return request('/api/email.php?action=aiDraft', {
    method: 'POST',
    body: data,
  });
}

// ── Marketing ──

export function getContentCalendar(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request(`/api/admin.php?action=getContentCalendar${qs}`);
}

export function requestVirtualStaging(data: Record<string, unknown>) {
  return request('/api/admin.php?action=requestStaging', {
    method: 'POST',
    body: data,
  });
}

export function requestVideoGeneration(data: Record<string, unknown>) {
  return request('/api/admin.php?action=requestVideo', {
    method: 'POST',
    body: data,
  });
}

// ── Analytics (Sisu replacement) ──

export interface KPIData {
  gci_mtd: number;
  gci_ytd: number;
  deals_closed_mtd: number;
  deals_closed_ytd: number;
  deals_pending: number;
  avg_days_on_market: number;
  leads_mtd: number;
  conversion_rate: number;
  showings_mtd: number;
  listings_active: number;
}

export function getKPIs() {
  return request<KPIData>('/api/admin.php?action=getKPIs');
}

export function getLeaderboard() {
  return request('/api/admin.php?action=getLeaderboard');
}

export function getAgentGoals(agentId: number) {
  return request(`/api/admin.php?action=getGoals&agent_id=${agentId}`);
}

export function getAgentPacing(agentId: number) {
  return request(`/api/admin.php?action=getPacing&agent_id=${agentId}`);
}

// ── Documents (DocuSign replacement) ──

export interface Document {
  id: number;
  tenant_id: string | null;
  deal_id: number | null;
  filename: string;
  file_type: string;
  file_size: number;
  status: 'draft' | 'pending_review' | 'approved' | 'signed';
  uploaded_by: number;
  version: number;
  created_at: string;
  updated_at: string;
}

export function getDocuments(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<Document[]>(`/api/documents.php?action=getDocuments${qs}`);
}

export function uploadDocument(formData: FormData) {
  return request('/api/documents.php?action=upload', {
    method: 'POST',
    body: formData,
  });
}

export function getEnvelope(envelopeId: number) {
  return request(`/api/esign.php?action=getEnvelope&id=${envelopeId}`);
}

export function signDocument(envelopeId: number, signatureData: Record<string, unknown>) {
  return request('/api/esign.php?action=sign', {
    method: 'POST',
    body: { envelope_id: envelopeId, ...signatureData },
  });
}

// ── Calendar ──

export interface CalendarEvent {
  id: number;
  tenant_id: string | null;
  title: string;
  description: string;
  start_time: string;
  end_time: string;
  location: string;
  event_type: string;
  client_id: number | null;
  deal_id: number | null;
  google_event_id: string | null;
  created_at: string;
}

export function getCalendarEvents(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request<CalendarEvent[]>(`/api/calendar.php?action=getEvents${qs}`);
}

export function createCalendarEvent(data: Record<string, unknown>) {
  return request('/api/calendar.php?action=createEvent', {
    method: 'POST',
    body: data,
  });
}

// ── Commissions ──

export function getCommissions(params?: Record<string, string>) {
  const qs = params ? '&' + new URLSearchParams(params).toString() : '';
  return request(`/api/commissions.php?action=getCommissions${qs}`);
}

export function getCommissionForecast() {
  return request('/api/commissions.php?action=getForecast');
}

// ── AI ──

export function chatAI(message: string, context?: Record<string, unknown>) {
  return request('/api/admin.php?action=aiChat', {
    method: 'POST',
    body: { message, context },
  });
}

// ── Tenant Config ──

export interface TenantConfig {
  id: string;
  name: string;
  domain: string;
  primary_color: string;
  accent_color: string;
  bg_color: string;
  text_color: string;
  logo_url: string;
  typography_heading: string;
  typography_body: string;
}

export function getTenantConfig() {
  return request<TenantConfig>('/api/tenants.php?action=getConfig');
}

// ── Notifications Registration ──

export function registerPushToken(token: string, platform: string) {
  return request('/api/admin.php?action=registerPushToken', {
    method: 'POST',
    body: { push_token: token, platform },
  });
}

export default {
  configureAPI,
  getAPIConfig,
  login,
  loginMagicLink,
  getProfile,
  getClients,
  getClient,
  createClient,
  updateClient,
  getClientTimeline,
  logInteraction,
  getShowings,
  getTodayShowings,
  updateShowingStatus,
  submitShowingFeedback,
  getDeals,
  getDeal,
  getDealTasks,
  updateTask,
  getComplianceItems,
  getDeadlines,
  getProperties,
  getProperty,
  getPropertyMatches,
  getNearbyProperties,
  getEmails,
  getEmailThread,
  sendEmail,
  getAIDraft,
  getContentCalendar,
  requestVirtualStaging,
  requestVideoGeneration,
  getKPIs,
  getLeaderboard,
  getAgentGoals,
  getAgentPacing,
  getDocuments,
  uploadDocument,
  getEnvelope,
  signDocument,
  getCalendarEvents,
  createCalendarEvent,
  getCommissions,
  getCommissionForecast,
  chatAI,
  getTenantConfig,
  registerPushToken,
};
