import axios from 'axios';

const ODOO_BASE = import.meta.env.VITE_API_BASE_URL || '/api/odoo';

// ============================================================
// Auth: adjuntar token y manejar 401 globalmente
// ============================================================
axios.interceptors.request.use((config) => {
  const token = localStorage.getItem('skeen_token');
  if (token) {
    config.headers = config.headers || {};
    (config.headers as Record<string, string>).Authorization = `Bearer ${token}`;
  }
  return config;
});

axios.interceptors.response.use(
  (res) => res,
  (error) => {
    if (error?.response?.status === 401) {
      const onLogin = window.location.pathname === '/login';
      const isLoginCall = String(error.config?.url || '').includes('/auth/login');
      if (!onLogin && !isLoginCall) {
        localStorage.removeItem('skeen_token');
        localStorage.removeItem('skeen_user');
        window.location.href = '/login';
      }
    }
    return Promise.reject(error);
  },
);

// ============================================================
// Tipos
// ============================================================
export interface DashboardStats {
  appointments_today: number;
  appointments_month: number;
  new_patients_month: number;
  total_patients: number;
  revenue_month: number;
  pending_payments: number;
  total_wallet_points: number;
  sales_today: number;
}

export interface Appointment {
  id: number;
  reference: string;
  patient_id: number;
  patient: string;
  phone: string;
  service_id: number;
  service: string;
  service_category?: string;
  date: string;
  time: string;
  state: string;
  payment_state: string;
  price: number;
  amount_paid?: number;
  duration?: number;
  is_first_visit?: boolean;
  doctor_id?: number | null;
  doctor?: string;
  branch?: string;
  medium?: string;
  notes?: string;
  package_finished?: boolean;
  package_finished_date?: string | null;
}

export interface Bloqueo {
  id: number;
  doctor_id: number;
  doctor: string;
  date: string;
  all_day: boolean;
  time_from: number;
  time_to: number;
  motivo: string;
}

export type VisitaState = 'en_curso' | 'completada' | 'cancelada';

export interface VisitaInsumo {
  id: number;
  item_id: number;
  item: string;
  unit: string;
  qty: number;
  notes: string;
}

export interface VisitaAdjunto {
  id: number;
  kind: 'antes' | 'despues' | 'documento';
  name: string;
  mimetype: string;
  notes: string;
  create_date: string | null;
  url: string;
}

export interface Visita {
  id: number;
  name: string;
  cita_id: number | null;
  partner_id: number;
  patient: string;
  phone: string;
  doctor_id: number | null;
  doctor: string | null;
  cosmetologa_id: number | null;
  cosmetologa: string | null;
  servicio_id: number | null;
  servicio: string | null;
  motivo: string;
  diagnostico: string;
  tratamiento: string;
  notas: string;
  receta_text?: string;
  state: VisitaState;
  date_start: string | null;
  date_end: string | null;
  insumos: VisitaInsumo[];
  insumos_descargados: boolean;
  adjuntos: VisitaAdjunto[];
}

export interface Patient {
  id: number;
  patient_id: string;
  name: string;
  phone: string;
  email: string;
  birth_date: string | null;
  age?: number;
  gender?: string | false;
  blood_type?: string | false;
  last_visit: string | null;
  total_visits: number;
  wallet_points: number;
  total_spent: number;
  source: string;
  is_vip: boolean;
  primary_doctor_id?: number | null;
  primary_doctor?: string;
  whatsapp?: string;
  has_photo?: boolean;
  photo_url?: string;
  photo?: string;
  // Datos personales extendidos
  birthplace?: string;
  occupation?: string;
  marital_status?: string;
  emergency_contact?: string;
  emergency_phone?: string;
  home_phone?: string;
  mobile?: string;
  address_notes?: string;
  referred_by?: string;
  patient_comments?: string;
  internal_notes?: string;
  // Historia clínica
  is_pregnant?: boolean;
  is_breastfeeding?: boolean;
  uses_contraceptives?: boolean;
  children_count?: number;
  kidney_problems?: boolean;
  back_pain?: boolean;
  heart_disease?: boolean;
  respiratory_problems?: boolean;
  blood_pressure?: boolean;
  diabetes?: boolean;
  thyroid?: boolean;
  colitis?: boolean;
  constipation?: boolean;
  liver_problems?: boolean;
  surgeries?: boolean;
  surgeries_notes?: string;
  varicose_veins?: boolean;
  migraine?: boolean;
  faints_with_needles?: boolean;
  medical_notes?: string;
  // Legacy medical fields
  allergies?: string;
  medical_history?: string;
  current_medication?: string;
  // Completitud de expediente
  expediente_completion?: number;
  expediente_missing?: string[];
}

export interface EstadoCuenta {
  puntos_monedero: number;
  total_gastado: number;
  adeudo: number;
  visitas_total: number;
}

export interface PatientAdjunto {
  id: number;
  kind: 'expediente' | 'imagen';
  name: string;
  mimetype: string;
  notes: string;
  create_date: string | null;
  url: string;
}

export interface ExpedienteReciente {
  id: number;
  patient_id: string;
  name: string;
  phone: string;
  age: number;
  birth_date: string | null;
  primary_doctor: string | null;
  last_visit: string | null;
  internal_notes: string;
  expediente_count: number;
  imagenes_count: number;
  has_photo: boolean;
  photo_url: string;
}

export interface Service {
  id: number;
  code: string;
  name: string;
  category: string;
  price: number;
  package_price?: number;
  package_sessions?: number;
  package_notes?: string;
  duration_min: number;
  description: string;
  color: string;
  service_group: string;
  is_favorite: boolean;
  genera_monedero?: boolean;
}

export interface Doctor {
  id: number;
  name: string;
  job_title: string;
  work_phone: string;
  work_email: string;
  commission_pct: number;
  patient_count?: number;
}

export interface Product {
  id: number;
  name: string;
  list_price: number;
  default_code: string;
  type: string;
}

export interface Wallet {
  id: number;
  patient_id: number;
  patient: string;
  phone: string;
  points: number;
  equivalent_mxn: number;
}

export interface Payment {
  id: number;
  name: string;
  patient: string;
  patient_id: number;
  amount: number;
  payment_method: string;
  state: string;
  payment_url?: string;
  provider_reference?: string;
  create_date?: string;
}

export interface SaleLine {
  id?: number;
  service_id: number;
  service?: string;
  item_id?: number | null;
  item?: string;
  description: string;
  quantity: number;
  price_unit: number;
  subtotal: number;
  is_prescribed?: boolean;
  prescribed_by_id?: number | null;
  prescribed_by?: string | null;
}

export interface CommissionRow {
  doctor_id: number;
  doctor: string;
  job_title: string;
  commission_pct: number;
  base: number;
  commission: number;
  items: number;
  sales: number;
}

export interface Sale {
  id: number;
  name: string;
  patient_id: number;
  patient: string;
  date: string;
  subtotal: number;
  discount: number;
  tax: number;
  total: number;
  amount_paid: number;
  amount_due: number;
  state: string;
  lines: SaleLine[];
  refunded?: boolean;
  refund_amount?: number;
  refund_reason?: string;
  refunded_at?: string | null;
}

export interface CashClosing {
  id: number;
  name: string;
  date: string;
  user: string | false;
  opening_cash: number;
  total_cash: number;
  total_card: number;
  total_transfer: number;
  total_other: number;
  total_sales: number;
  closing_cash: number;
  difference: number;
  state: string;
}

export interface ChartPoint {
  name: string;
  appointments: number;
  revenue: number;
  patients: number;
}

export interface Birthday {
  id: number;
  name: string;
  phone: string;
  birth_date: string;
  occurs_on: string;
  turning_age: number;
  last_visit: string | null;
  total_spent: number;
  amount_due: number;
  is_vip: boolean;
}

export type InventoryKind = 'producto' | 'consumible';
export type InventoryLevel = 'out' | 'critical' | 'low' | 'optimal';
export type InventoryMoveType = 'compra' | 'venta' | 'baja' | 'ajuste';

export interface InventoryItem {
  id: number;
  name: string;
  kind: InventoryKind;
  sku: string;
  category: string;
  unit: string;
  qty: number;
  qty_optimal: number;
  qty_min: number;
  cost: number;
  price?: number;
  inventory_value: number;
  expiry_date: string | null;
  last_count_date: string | null;
  active: boolean;
  genera_monedero?: boolean;
  notes: string;
  stock_level: InventoryLevel;
}

export interface InventoryMove {
  id: number;
  item_id: number;
  type: InventoryMoveType;
  qty: number;
  before_qty: number;
  after_qty: number;
  date: string | null;
  reference: string;
  notes: string;
}

export interface InventorySummary {
  levels: Record<InventoryLevel, number>;
  total_value: number;
  count: number;
}

// WACRM
export interface WacrmConversation {
  id: number;
  external_id: string;
  contact_id?: string;
  contact_name: string;
  contact_phone: string;
  status: string;
  assigned_agent: string;
  assigned_agent_id: string;
  last_message_text: string;
  last_message_at: string | null;
  unread_count: number;
  created_at: string | null;
}

export interface WacrmMessage {
  id: number;
  external_id: string;
  conversation_id: string;
  contact_name: string;
  contact_phone: string;
  sender_type: 'customer' | 'agent' | 'bot';
  content_type: string;
  content_text: string;
  media_url: string;
  template_name: string;
  status: string;
  created_at: string | null;
}

export interface WacrmStage {
  id: number;
  external_id: string;
  name: string;
  position: number;
  color: string;
}

export interface WacrmPipeline {
  id: number;
  external_id: string;
  name: string;
  stages: WacrmStage[];
}

export interface WacrmLead {
  id: number;
  external_id: string;
  title: string;
  contact_id?: string;
  contact_name: string;
  contact_phone: string;
  pipeline: string;
  pipeline_id?: number;
  stage: string;
  stage_id?: number;
  stage_color: string;
  value: number;
  currency: string;
  status: 'open' | 'won' | 'lost';
  expected_close_date: string | null;
  notes: string;
  assigned_to: string;
  partner_id?: number | null;
  conversation_id?: string;
  created_at: string | null;
}

export type FrontendRole = 'admin' | 'recepcion' | 'medico' | 'lectura';

export interface FrontendUser {
  id: number;
  login: string;
  name: string;
  role: FrontendRole;
  must_change_password?: boolean;
  last_login?: string | null;
  active?: boolean;
  allowed_menus?: string[] | null;
}

export interface Receta {
  id: number;
  name: string;
  categoria: string;
  contenido: string;
}

export interface Diagnostico {
  id: number;
  name: string;
  categoria: string;
  descripcion: string;
}

export interface Procedimiento {
  id: number;
  name: string;
  categoria: string;
  descripcion: string;
}

export interface AdeudoRow {
  id: number;
  name: string;
  phone: string;
  num_ventas: number;
  total_adeudo: number;
  ultima_venta: string | null;
}

export interface ComisionRow {
  doctor_id: number;
  doctor: string;
  job_title: string;
  items: number;
  sales: number;
  citas_done: number;
  total_vendido: number;
  commission_pct: number;
  comision: number;
}

export interface MovimientoRow extends InventoryMove {
  item: string;
  unit: string;
}

export interface CaducidadRow {
  id: number;
  name: string;
  category: string;
  qty: number;
  unit: string;
  expiry_date: string;
  dias_restantes: number;
  vencido: boolean;
}

export interface SugerenciaRow {
  id: number;
  name: string;
  category: string;
  unit: string;
  qty: number;
  qty_min: number;
  qty_optimal: number;
  sugerido: number;
  costo_estimado: number;
}

export interface PagoServicioRow {
  servicio: string;
  cantidad: number;
  total: number;
}

export interface PagoClienteRow {
  id: number;
  name: string;
  num_pagos: number;
  total_cobrado: number;
  ultimo_pago: string | null;
}

export interface DevolucionRow {
  id: number;
  folio: string;
  paciente: string;
  fecha: string | null;
  total: number;
  refund_amount: number;
  refund_reason: string;
  refunded_at: string | null;
}

export interface TopClienteRow {
  id: number;
  name: string;
  num_ventas: number;
  total: number;
  ticket_promedio: number;
}

export interface DailyPorMedico {
  medico: string;
  citas: number;
  by_state: Record<string, number>;
  ventas: number;
  cobros: number;
}

export interface DailyPorRecepcion {
  usuario: string;
  ventas_count: number;
  ventas_total: number;
  cobros_total: number;
}

export interface HoraAgendaRow {
  hora: string;
  total: number;
  by_state: Record<string, number>;
}

export interface PaqueteRow {
  id: number;
  name: string;
  package_sessions: number;
  package_price: number;
  price: number;
  citas: number;
  terminados: number;
}

export interface VendedorRow {
  usuario: string;
  num_ventas: number;
  total: number;
  cobrado: number;
}

export interface ConcentradoReport {
  start: string;
  end: string;
  citas: { total: number; by_state: Record<string, number> };
  ventas: { count: number; total: number; total_paid: number; total_due: number };
  pagos: { total: number; count: number; by_method: Record<string, number> };
  devoluciones: { count: number; total: number };
  pacientes_nuevos: number;
  visitas: { total: number; by_state: Record<string, number> };
}

export interface RecomendacionRow {
  recomendador: string;
  pacientes: number;
}

export interface MonederoPuntosReport {
  by_type: Record<string, number>;
  puntos_activos: number;
  cuentas: number;
  equivalente_mxn: number;
}

export interface KpisNoShowMedico {
  medico: string;
  citas: number;
  no_shows: number;
  tasa: number;
}

export interface KpisOcupacionMedico {
  medico: string;
  horas_vendidas: number;
  horas_disponibles: number;
  horas_libres: number;
  ocupacion: number;
}

export interface KpisReport {
  start: string;
  end: string;
  no_show: { tasa: number; total_citas: number; total_no_shows: number; por_medico: KpisNoShowMedico[] };
  ocupacion: { promedio: number; dias_habiles: number; por_medico: KpisOcupacionMedico[] };
  leads: { total: number; ganados: number; tasa: number; dias_promedio_ganar: number | null };
  primera_vez: { primera: number; subsecuentes: number; tasa: number };
}

export interface AppNotification {
  tipo: string;
  titulo: string;
  detalle: string;
  link: string;
  severity: 'info' | 'warning' | 'danger';
}

export interface PosCheckoutPayload {
  partner_id: number;
  lines: { service_id?: number; item_id?: number; quantity: number; price_unit: number; description?: string; prescribed_by_id?: number }[];
  discount?: number;
  payment_method?: string;
  amount_received?: number;
  pay_with_points?: boolean;
  currency?: 'MXN' | 'USD';
}

export interface PosCheckoutResult {
  status: string;
  sale: Sale;
  payment: Payment | null;
  cambio: number;
  cambio_usd?: number;
  rate_used?: number | null;
  recibido_usd?: number;
  puntos_usados: number;
  puntos_ganados: number;
  wallet_points: number;
  stock_warnings?: string[];
}

export interface DailyReport {
  date: string;
  citas: { total: number; by_state: Record<string, number> };
  ventas: { count: number; total: number; total_paid: number; total_due: number };
  pagos: { total: number; count: number; by_method: Record<string, number> };
  inventario: { total: number; by_type: Record<string, number> };
}

export interface InventoryReportSummary {
  total_value: number;
  count: number;
  out: number;
  critical: number;
}

export interface ApiResponse<T> {
  status: string;
  message?: string;
  data?: T;
}

export interface Paginated<T> {
  status: string;
  total: number;
  page: number;
  page_size: number;
  total_pages: number;
  items: T;
}

// ============================================================
// API
// ============================================================
export const odooApi = {
  // Auth (frontend React)
  async login(login: string, password: string): Promise<{ status: string; token: string; user: FrontendUser; message?: string }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/auth/login`, { login, password });
    return data;
  },

  async me(): Promise<{ status: string; user: FrontendUser }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/auth/me`);
    return data;
  },

  async logout(): Promise<{ status: string }> {
    try {
      const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/auth/logout`);
      return data;
    } catch {
      return { status: 'success' };
    }
  },

  async listFrontendUsers(): Promise<{ status: string; users: FrontendUser[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/auth/users`);
    return data;
  },

  async createFrontendUser(payload: { login: string; name: string; password: string; role: FrontendRole }): Promise<{ status: string; user: FrontendUser; message?: string }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/auth/users`, payload);
    return data;
  },

  async updateFrontendUser(id: number, payload: Partial<{ name: string; role: FrontendRole; active: boolean; password: string; must_change_password: boolean; allowed_menus: string[] | null }>): Promise<{ status: string; user: FrontendUser; message?: string }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/auth/users/${id}`, payload);
    return data;
  },

  async deleteFrontendUser(id: number): Promise<{ status: string; message?: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/auth/users/${id}`);
    return data;
  },

  // Health
  async healthCheck(): Promise<unknown> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/health`);
    return data;
  },

  // Dashboard
  async getDashboard(): Promise<{ status: string; stats: DashboardStats }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/dashboard`);
    return data;
  },

  async getWeeklyChart(): Promise<{ status: string; data: ChartPoint[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/weekly_chart`);
    return data;
  },

  // Citas
  async getAppointments(params?: Record<string, string | number>): Promise<{ status: string; appointments: Appointment[]; bloqueos?: Bloqueo[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/appointments`, { params });
    return data;
  },

  async createAppointment(appointment: Partial<Appointment> & { sessions?: number }): Promise<{ status: string; appointment: Appointment; appointments?: Appointment[]; sessions?: number }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/appointments`, appointment);
    return data;
  },

  async updateAppointment(id: number, appointment: Partial<Appointment>): Promise<{ status: string; appointment: Appointment }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/appointments/${id}`, appointment);
    return data;
  },

  async deleteAppointment(id: number): Promise<{ status: string; message: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/appointments/${id}`);
    return data;
  },

  async updateAppointmentStatus(id: number, action: string, reason?: string): Promise<{ status: string; appointment: Appointment }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/appointments/${id}/status`, { action, reason });
    return data;
  },

  async packageFinished(id: number, finished = true): Promise<{ status: string; appointment: Appointment }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/appointments/${id}/package_finished`, { finished });
    return data;
  },

  async getAvailableSlots(date: string, servicio_id: number): Promise<{ status: string; slots: { time: number; time_str: string }[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/appointments/slots`, { params: { date, servicio_id } });
    return data;
  },

  // Bloqueos de agenda
  async getBloqueos(params?: Record<string, string | number>): Promise<{ status: string; bloqueos: Bloqueo[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/bloqueos`, { params });
    return data;
  },

  async createBloqueo(payload: { doctor_id: number; date: string; all_day?: boolean; time_from?: number; time_to?: number; motivo?: string }): Promise<{ status: string; bloqueo: Bloqueo }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/bloqueos`, payload);
    return data;
  },

  async deleteBloqueo(id: number): Promise<{ status: string; message: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/bloqueos/${id}`);
    return data;
  },

  // Visitas clínicas
  async getVisitas(params?: Record<string, string | number>): Promise<{ status: string; visitas: Visita[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/visitas`, { params });
    return data;
  },

  async getVisita(id: number): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}`);
    return data;
  },

  async updateVisita(id: number, visita: Partial<Visita>): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}`, visita);
    return data;
  },

  async completeVisita(id: number): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}/complete`);
    return data;
  },

  async cancelVisita(id: number): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}/cancel`);
    return data;
  },

  async addVisitaInsumo(id: number, payload: { item_id: number; qty: number; notes?: string }): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}/insumos`, payload);
    return data;
  },

  async deleteVisitaInsumo(id: number, lineId: number): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}/insumos/${lineId}`);
    return data;
  },

  async getInventarioItems(search?: string): Promise<{ status: string; items: InventoryItem[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventory/items`, { params: search ? { search } : {} });
    return data;
  },

  async uploadVisitaAdjunto(id: number, payload: { kind: string; name: string; file_b64: string; mimetype: string; notes?: string }): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/visitas/${id}/adjuntos`, payload);
    return data;
  },

  async deleteVisitaAdjunto(adjId: number): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/visitas/adjuntos/${adjId}`);
    return data;
  },

  // URL del binario de un adjunto con el token en query (para <img src>)
  visitaAdjuntoUrl(url: string): string {
    const token = localStorage.getItem('skeen_token') || '';
    return `${ODOO_BASE}${url}?token=${encodeURIComponent(token)}`;
  },

  // Pacientes
  async getPatients(params?: string | { search?: string; page?: number; page_size?: number; incomplete?: number; vip?: number; recent?: number; doctor_id?: number }): Promise<{ status: string; patients: Patient[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const p = typeof params === 'string' ? { search: params } : params || {};
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/patients`, { params: p });
    return data;
  },

  async createPatient(patient: Partial<Patient>): Promise<{ status: string; patient: Patient }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/patients`, patient);
    return data;
  },

  async updatePatient(id: number, patient: Partial<Patient>): Promise<{ status: string; patient: Patient }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/patients/${id}`, patient);
    return data;
  },

  async getPatientHistory(id: number): Promise<{ status: string; appointments: Appointment[]; sales: Sale[]; visitas: Visita[]; estado_cuenta: EstadoCuenta }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/patients/${id}/history`);
    return data;
  },

  // URL de la foto del paciente con el token en query (para <img src>)
  patientPhotoUrl(url: string): string {
    const token = localStorage.getItem('skeen_token') || '';
    return `${ODOO_BASE}${url}?token=${encodeURIComponent(token)}`;
  },

  // Expedientes recientes y adjuntos de paciente
  async getExpedientesRecientes(params?: Record<string, string | number>): Promise<{ status: string; expedientes: ExpedienteReciente[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/expedientes-recientes`, { params });
    return data;
  },

  async getPatientAdjuntos(id: number, kind?: string): Promise<{ status: string; adjuntos: PatientAdjunto[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/patients/${id}/adjuntos`, { params: kind ? { kind } : {} });
    return data;
  },

  async uploadPatientAdjunto(id: number, payload: { kind: string; name: string; file_b64: string; mimetype: string; notes?: string }): Promise<{ status: string; adjunto: PatientAdjunto }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/patients/${id}/adjuntos`, payload);
    return data;
  },

  async deletePatientAdjunto(adjId: number): Promise<{ status: string; message: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/patients/adjuntos/${adjId}`);
    return data;
  },

  // URL del binario de un adjunto de paciente con el token en query (para <img src>)
  patientAdjuntoUrl(url: string): string {
    const token = localStorage.getItem('skeen_token') || '';
    return `${ODOO_BASE}${url}?token=${encodeURIComponent(token)}`;
  },

  // Recetas (plantillas)
  async getRecetas(search?: string): Promise<{ status: string; recetas: Receta[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/recetas`, { params: search ? { search } : {} });
    return data;
  },

  async createReceta(receta: Partial<Receta>): Promise<{ status: string; receta: Receta }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/recetas`, receta);
    return data;
  },

  async updateReceta(id: number, receta: Partial<Receta>): Promise<{ status: string; receta: Receta }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/recetas/${id}`, receta);
    return data;
  },

  async deleteReceta(id: number): Promise<{ status: string; message?: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/recetas/${id}`);
    return data;
  },

  // Catálogos: diagnósticos y procedimientos
  async getDiagnosticos(search?: string): Promise<{ status: string; items: Diagnostico[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/diagnosticos`, { params: search ? { search } : {} });
    return data;
  },

  async createDiagnostico(payload: Partial<Diagnostico>): Promise<{ status: string; item: Diagnostico }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/diagnosticos`, payload);
    return data;
  },

  async updateDiagnostico(id: number, payload: Partial<Diagnostico>): Promise<{ status: string; item: Diagnostico }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/diagnosticos/${id}`, payload);
    return data;
  },

  async deleteDiagnostico(id: number): Promise<{ status: string; message?: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/diagnosticos/${id}`);
    return data;
  },

  async getProcedimientos(search?: string): Promise<{ status: string; items: Procedimiento[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/procedimientos`, { params: search ? { search } : {} });
    return data;
  },

  async createProcedimiento(payload: Partial<Procedimiento>): Promise<{ status: string; item: Procedimiento }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/procedimientos`, payload);
    return data;
  },

  async updateProcedimiento(id: number, payload: Partial<Procedimiento>): Promise<{ status: string; item: Procedimiento }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/procedimientos/${id}`, payload);
    return data;
  },

  async deleteProcedimiento(id: number): Promise<{ status: string; message?: string }> {
    const { data } = await axios.delete(`${ODOO_BASE}/skeen/frontend/v1/procedimientos/${id}`);
    return data;
  },

  // Consultas médicas directas
  async createConsulta(payload: { partner_id: number; doctor_id?: number | null; motivo?: string; diagnostico?: string; tratamiento?: string; notas?: string }): Promise<{ status: string; visita: Visita }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/consultas`, payload);
    return data;
  },

  // Reporte de adeudos (cartera por cobrar)
  async getAdeudos(): Promise<{ status: string; adeudos: AdeudoRow[]; total_cartera: number; total_pacientes: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/adeudos`);
    return data;
  },

  // Servicios
  async getServices(params?: { search?: string; category?: string; page?: number; page_size?: number }): Promise<{ status: string; services: Service[]; total?: number; page?: number; total_pages?: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/services`, { params });
    return data;
  },

  async globalSearch(q: string): Promise<{
    status: string;
    patients: { id: number; name: string; phone: string }[];
    appointments: { id: number; patient: string; service: string; date: string; time: string }[];
    services: { id: number; name: string; price: number }[];
  }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/search`, { params: { q } });
    return data;
  },

  async createService(service: Partial<Service>): Promise<{ status: string; service: Service }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/services`, service);
    return data;
  },

  async updateService(id: number, service: Partial<Service>): Promise<{ status: string; service: Service }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/services/${id}`, service);
    return data;
  },

  // Médicos
  async getDoctors(): Promise<{ status: string; doctors: Doctor[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/doctors`);
    return data;
  },

  async updateDoctor(id: number, payload: { commission_pct: number }): Promise<{ status: string; doctor: Doctor }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/doctors/${id}`, payload);
    return data;
  },

  // Comisiones
  async getCommissions(start?: string, end?: string): Promise<{ status: string; start: string; end: string; total_base: number; total_commission: number; commissions: CommissionRow[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/commissions`, { params: { start, end } });
    return data;
  },

  // Productos
  async getProducts(): Promise<{ status: string; products: Product[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/products`);
    return data;
  },

  // Monederos
  async getWallets(params?: string | { phone?: string; search?: string; page?: number; page_size?: number }): Promise<{ status: string; wallets: Wallet[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const p = typeof params === 'string' ? { phone: params } : params || {};
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wallets`, { params: p });
    return data;
  },

  async getWalletByPhone(phone: string): Promise<{ status: string; wallet: { points: number; equivalent_mxn: number; history: unknown[] } }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wallets/${phone}`);
    return data;
  },

  async walletTransaction(payload: { phone: string; type: 'accrual' | 'redemption'; points: number; description?: string }): Promise<{ status: string; wallet: Wallet }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/wallets/transaction`, payload);
    return data;
  },

  // Pagos
  async getPayments(state?: string): Promise<{ status: string; payments: Payment[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/payments`, { params: state ? { state } : {} });
    return data;
  },

  async createPayment(payment: Partial<Payment>): Promise<{ status: string; payment: Payment }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/payments`, payment);
    return data;
  },

  async confirmPayment(id: number): Promise<{ status: string; payment: Payment }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/payments/${id}/confirm`);
    return data;
  },

  // Ventas
  async getSales(params?: Record<string, string | number>): Promise<{ status: string; sales: Sale[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/sales`, { params });
    return data;
  },

  async createSale(sale: Omit<Partial<Sale>, 'lines'> & { lines: Omit<SaleLine, 'subtotal'>[] }): Promise<{ status: string; sale: Sale }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/sales`, sale);
    return data;
  },

  async paySale(id: number, payload: { payment_method: string; amount?: number }): Promise<{ status: string; sale: Sale; payment: Payment }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/sales/${id}/pay`, payload);
    return data;
  },

  async refundSale(id: number, payload: { amount?: number; reason?: string }): Promise<{ status: string; sale: Sale; result: { refund_amount: number; points_reversed: number; new_state: string; new_amount_paid: number } }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/sales/${id}/refund`, payload);
    return data;
  },

  // Cortes de caja
  async getCashClosings(date?: string): Promise<{ status: string; cash_closings: CashClosing[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/cash_closings`, { params: date ? { date } : {} });
    return data;
  },

  async createCashClosing(payload: { date?: string; opening_cash: number; notes?: string }): Promise<{ status: string; cash_closing: CashClosing }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/cash_closings`, payload);
    return data;
  },

  async closeCashClosing(id: number, closing_cash: number): Promise<{ status: string; cash_closing: CashClosing }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/cash_closings/${id}/close`, { closing_cash });
    return data;
  },

  // Reportes
  async getSalesReport(start?: string, end?: string): Promise<{ status: string; total_sales: number; total_paid: number; total_due: number; count: number; by_day?: { date: string; total: number }[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/sales`, { params: { start, end } });
    return data;
  },

  async getDailyReport(date?: string, by?: 'medico' | 'recepcion'): Promise<{ status: string } & DailyReport & { por_medico?: DailyPorMedico[]; por_recepcion?: DailyPorRecepcion[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/daily`, {
      params: { ...(date ? { date } : {}), ...(by ? { by } : {}) },
    });
    return data;
  },

  async getComisiones(start?: string, end?: string): Promise<{ status: string; start: string; end: string; comisiones: ComisionRow[]; total_vendido: number; total_comision: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/comisiones`, { params: { start, end } });
    return data;
  },

  async getPagosServicios(start?: string, end?: string): Promise<{ status: string; total_cobrado: number; total_pagos: number; by_method: Record<string, number>; servicios: PagoServicioRow[]; total_pagado_completo: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/pagos-servicios`, { params: { start, end } });
    return data;
  },

  async getPagosClientes(start?: string, end?: string): Promise<{ status: string; clientes: PagoClienteRow[]; total_cobrado: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/pagos-clientes`, { params: { start, end } });
    return data;
  },

  async getDevoluciones(start?: string, end?: string): Promise<{ status: string; devoluciones: DevolucionRow[]; total_devuelto: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/devoluciones`, { params: { start, end } });
    return data;
  },

  async getTopClientes(start?: string, end?: string, limit = 20): Promise<{ status: string; clientes: TopClienteRow[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/top-clientes`, { params: { start, end, limit } });
    return data;
  },

  async getMovimientos(params?: Record<string, string | number>): Promise<{ status: string; movimientos: MovimientoRow[]; total?: number; page?: number; page_size?: number; total_pages?: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventario/movimientos`, { params });
    return data;
  },

  async createCompra(payload: { item_id: number; qty: number; cost?: number; reference?: string; notes?: string }): Promise<{ status: string; move: InventoryMove; item: InventoryItem }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/inventario/compras`, payload);
    return data;
  },

  async createBaja(payload: { item_id: number; qty: number; reference?: string; notes?: string }): Promise<{ status: string; move: InventoryMove; item: InventoryItem }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/inventario/bajas`, payload);
    return data;
  },

  async getInventarioAlertas(): Promise<{ status: string; caducidades: CaducidadRow[]; sugerencia_compra: SugerenciaRow[]; sugerencia_total: { items: number; costo_total: number } }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventario/alertas`);
    return data;
  },

  async getHorasAgenda(start?: string, end?: string): Promise<{ status: string; horas: HoraAgendaRow[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/horas-agenda`, { params: { start, end } });
    return data;
  },

  async getPaquetes(): Promise<{ status: string; paquetes: PaqueteRow[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/paquetes`);
    return data;
  },

  async getVendedores(start?: string, end?: string): Promise<{ status: string; vendedores: VendedorRow[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/vendedores`, { params: { start, end } });
    return data;
  },

  async getConcentrado(start?: string, end?: string): Promise<{ status: string } & ConcentradoReport> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/concentrado`, { params: { start, end } });
    return data;
  },

  async getRecomendaciones(): Promise<{ status: string; recomendaciones: RecomendacionRow[]; total: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/recomendaciones`);
    return data;
  },

  async getMonederoPuntos(start?: string, end?: string): Promise<{ status: string } & MonederoPuntosReport> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/monedero-puntos`, { params: { start, end } });
    return data;
  },

  async getKpis(start?: string, end?: string): Promise<{ status: string } & KpisReport> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/kpis`, { params: { start, end } });
    return data;
  },

  async getNotifications(): Promise<{ status: string; notifications: AppNotification[]; total: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/notifications`);
    return data;
  },

  // POS: venta + pago en una sola operación
  async posCheckout(payload: PosCheckoutPayload): Promise<PosCheckoutResult> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/pos/checkout`, payload);
    return data;
  },

  async getCashReportRange(start: string, end: string): Promise<{ status: string; total: number; by_method: Record<string, number> }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/cash`, { params: { start, end } });
    return data;
  },

  async getInventoryReport(): Promise<{ status: string; summary: InventoryReportSummary; items: InventoryItem[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/inventory`);
    return data;
  },

  async getAppointmentsReport(start?: string, end?: string): Promise<{ status: string; total: number; by_state: Record<string, number> }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/appointments`, { params: { start, end } });
    return data;
  },

  async getTopServices(start?: string, end?: string, limit = 8): Promise<{ status: string; start: string; end: string; services: { service_id: number; service: string; qty: number; revenue: number }[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/top_services`, { params: { start, end, limit } });
    return data;
  },

  async getCashReport(date?: string): Promise<{ status: string; total: number; by_method: Record<string, number> }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/cash`, { params: { date } });
    return data;
  },

  // Tipo de cambio
  async getExchangeRate(): Promise<{ status: string; current: { rate: number; date: string; source: string } | null; history: { id: number; date: string; rate: number; source: string }[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/exchange_rate`);
    return data;
  },

  async setExchangeRate(rate: number, source = 'manual'): Promise<{ status: string; exchange_rate: { id: number; date: string; rate: number; source: string } }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/exchange_rate`, { rate, source });
    return data;
  },

  // Meta de ventas mensual
  async getSalesGoal(): Promise<{ status: string; goal: number; current: number; pct: number; start: string; end: string; count: number }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/sales_goal`);
    return data;
  },

  async setSalesGoal(goal: number): Promise<{ status: string; goal: number }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/sales_goal`, { goal });
    return data;
  },

  // Cumpleañeros
  async getBirthdays(period: 'today' | 'week' | 'month' = 'month'): Promise<{ status: string; period: string; start: string; end: string; total: number; birthdays: Birthday[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/birthdays`, { params: { period } });
    return data;
  },

  // Inventario / Consumibles
  async getInventory(params?: { kind?: InventoryKind; level?: InventoryLevel; search?: string }): Promise<{ status: string; items: InventoryItem[]; summary: InventorySummary }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventory/items`, { params });
    return data;
  },

  async createInventoryItem(item: Partial<InventoryItem>): Promise<{ status: string; item: InventoryItem }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/inventory/items`, item);
    return data;
  },

  async updateInventoryItem(id: number, item: Partial<InventoryItem>): Promise<{ status: string; item: InventoryItem }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/inventory/items/${id}`, item);
    return data;
  },

  async getInventoryMoves(id: number): Promise<{ status: string; moves: InventoryMove[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventory/items/${id}/moves`);
    return data;
  },

  async createInventoryMove(id: number, payload: { type: InventoryMoveType; qty: number; reference?: string; notes?: string }): Promise<{ status: string; move: InventoryMove; item: InventoryItem }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/inventory/items/${id}/moves`, payload);
    return data;
  },

  // ============================================================
  // WACRM Proxy
  // ============================================================
  async syncWacrm(): Promise<{ status: string; result: Record<string, number | string | null> }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/wacrm/sync`);
    return data;
  },

  async getWacrmMembers(): Promise<{ status: string; members: { id: string; profile_id?: string; name: string; email?: string; avatar_url?: string; role: string }[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wacrm/members`);
    return data;
  },

  async assignWacrmConversation(external_id: string, assigned_agent_id: string | null): Promise<{ status: string; assigned_agent_id?: string }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/wacrm/conversations/${external_id}/assign`, {
      assigned_agent_id,
    });
    return data;
  },

  async getWacrmConversations(search?: string): Promise<{ status: string; conversations: WacrmConversation[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wacrm/conversations`, { params: search ? { search } : {} });
    return data;
  },

  async sendWacrmMessage(payload: { conversation_id: string; text: string; assigned_agent_id: string }): Promise<{ status: string; message: string }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/wacrm/messages`, payload);
    return data;
  },

  async getWacrmMessages(search?: string, conversation_id?: string): Promise<{ status: string; messages: WacrmMessage[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wacrm/messages`, {
      params: { ...(search ? { search } : {}), ...(conversation_id ? { conversation_id } : {}) },
    });
    return data;
  },

  async getWacrmPipelines(): Promise<{ status: string; pipelines: WacrmPipeline[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wacrm/pipelines`);
    return data;
  },

  async getWacrmLeads(search?: string, status?: string, pipeline_id?: string): Promise<{ status: string; leads: WacrmLead[] }> {
    const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wacrm/leads`, {
      params: { ...(search ? { search } : {}), ...(status ? { status } : {}), ...(pipeline_id ? { pipeline_id } : {}) },
    });
    return data;
  },

  async updateWacrmLeadStatus(id: number, payload: { status?: 'open' | 'won' | 'lost'; stage_id?: string; assigned_to?: string | null }): Promise<{ status: string; lead: WacrmLead }> {
    const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/wacrm/leads/${id}/status`, payload);
    return data;
  },

  async convertWacrmLead(id: number): Promise<{ status: string; lead: WacrmLead; patient_id: number; created: boolean; message?: string }> {
    const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/wacrm/leads/${id}/convert`);
    return data;
  },
};
