/**
 * Serviço de Agendamentos
 */

import { apiClient } from "../api/client";
import type {
  Appointment,
  CreateAppointmentInput,
  UpdateAppointmentInput,
  AppointmentFilters,
  GetAvailableSlotsInput,
  GetAvailableSlotsResponse,
} from "./types";

class AppointmentService {
  private readonly basePath = "/appointments";

  /**
   * Busca horários disponíveis de um médico
   * POST /functions/v1/get-available-slots
   */
  async getAvailableSlots(
    data: GetAvailableSlotsInput
  ): Promise<GetAvailableSlotsResponse> {
    try {
      console.log("[AppointmentService] Chamando get-available-slots:", data);

      // Usa callFunction para chamar a Edge Function
      const response = await apiClient.callFunction<GetAvailableSlotsResponse>(
        "get-available-slots",
        data
      );

      console.log(
        "[AppointmentService] Resposta get-available-slots:",
        response.data
      );

      return response.data;
    } catch (error: any) {
      console.error("[AppointmentService] ❌ Erro ao buscar slots:");
      console.error("[AppointmentService] Status:", error?.response?.status);
      console.error(
        "[AppointmentService] Response Data:",
        JSON.stringify(error?.response?.data, null, 2)
      );
      console.error("[AppointmentService] Message:", error?.message);
      console.error(
        "[AppointmentService] Input enviado:",
        JSON.stringify(data, null, 2)
      );

      throw new Error(
        error?.response?.data?.message ||
          error?.message ||
          "Erro ao buscar horários disponíveis"
      );
    }
  }

  /**
   * Lista agendamentos com filtros opcionais
   */
  async list(filters?: AppointmentFilters): Promise<Appointment[]> {
    const params: Record<string, string> = {};

    if (filters?.doctor_id) {
      params["doctor_id"] = `eq.${filters.doctor_id}`;
    }

    if (filters?.patient_id) {
      params["patient_id"] = `eq.${filters.patient_id}`;
    }

    if (filters?.status) {
      params["status"] = `eq.${filters.status}`;
    }

    if (filters?.scheduled_at) {
      params["scheduled_at"] = filters.scheduled_at;
    }

    if (filters?.limit) {
      params["limit"] = filters.limit.toString();
    }

    if (filters?.offset) {
      params["offset"] = filters.offset.toString();
    }

    if (filters?.order) {
      params["order"] = filters.order;
    }

    const response = await apiClient.get<Appointment[]>(this.basePath, {
      params,
    });
    return response.data;
  }

  /**
   * Busca agendamento por ID
   */
  async getById(id: string): Promise<Appointment> {
    const response = await apiClient.get<Appointment[]>(
      `${this.basePath}?id=eq.${id}`
    );
    if (response.data && response.data.length > 0) {
      return response.data[0];
    }
    throw new Error("Agendamento não encontrado");
  }

  /**
   * Cria novo agendamento
   * POST /rest/v1/appointments
   * Nota: order_number é gerado automaticamente (APT-YYYY-NNNN)
   */
  async create(data: CreateAppointmentInput): Promise<Appointment> {
    try {
      console.log("[AppointmentService] 📝 Criando agendamento com dados:", data);

      // Buscar user_id do localStorage para usar como created_by
      const userStr = localStorage.getItem("mediconnect_user");
      console.log("[AppointmentService] mediconnect_user no localStorage:", userStr);
      
      let userId: string | undefined;
      
      if (userStr) {
        try {
          const user = JSON.parse(userStr);
          userId = user.id;
          console.log("[AppointmentService] ✅ User ID extraído:", userId);
        } catch (e) {
          console.warn("[AppointmentService] ⚠️ Erro ao parsear user do localStorage:", e);
        }
      } else {
        console.warn("[AppointmentService] ⚠️ mediconnect_user não encontrado no localStorage!");
      }

      // Adiciona created_by obrigatório (deve ser user_id do auth)
      const payload = {
        ...data,
        duration_minutes: data.duration_minutes || 30,
        appointment_type: data.appointment_type || "presencial",
        status: "requested",
        created_by: data.created_by || userId, // IMPORTANTE: Usa user_id do auth
      };

      console.log("[AppointmentService] 🚀 Payload final a ser enviado:", {
        ...payload,
        created_by_source: data.created_by ? "input" : userId ? "localStorage" : "undefined"
      });

      if (!payload.created_by) {
        console.error("[AppointmentService] ❌ ERRO: created_by está undefined!");
        throw new Error("created_by é obrigatório mas não foi definido");
      }

      const response = await apiClient.post<Appointment[]>(
        this.basePath,
        payload,
        {
          headers: {
            Prefer: "return=representation",
          },
        }
      );

      console.log("[AppointmentService] ✅ Resposta da API:", response.data);

      if (response.data && response.data.length > 0) {
        return response.data[0];
      }
      throw new Error("Erro ao criar agendamento");
    } catch (error: any) {
      console.error("[AppointmentService] ❌ Erro ao criar agendamento:", {
        error,
        message: error?.message,
        response: error?.response,
        data: error?.response?.data,
        status: error?.response?.status,
      });
      throw error;
    }
  }

  /**
   * Atualiza agendamento existente
   * Usa Supabase Client para respeitar RLS policies
   */
  async update(id: string, data: UpdateAppointmentInput): Promise<Appointment> {
    console.log("[AppointmentService] Atualizando agendamento via API (PostgREST):", {
      id,
      data,
    });

    try {
      // Usa o apiClient (Axios) para fazer PATCH na rota REST do Supabase.
      // O apiClient já injeta o access token nas requisições, então a chamada
      // respeitará as políticas RLS do Supabase.
      const response = await apiClient.patch<Appointment[]>(
        `${this.basePath}?id=eq.${id}`,
        data
      );

      const updated = Array.isArray(response.data) ? response.data[0] : null;

      if (!updated) {
        console.error(
          "[AppointmentService] ❌ Nenhum agendamento retornado pela API ao atualizar",
          { responseData: response.data }
        );
        throw new Error("Agendamento não encontrado");
      }

      console.log("[AppointmentService] ✅ Agendamento atualizado com sucesso:", updated);
      return updated as Appointment;
    } catch (error: any) {
      console.error("[AppointmentService] Erro ao atualizar agendamento (API):", {
        error,
        id,
        data,
      });
      // Re-lança o erro para o componente tratar
      throw error;
    }
  }

  /**
   * Deleta agendamento
   */
  async delete(id: string): Promise<void> {
    await apiClient.delete(`${this.basePath}?id=eq.${id}`);
  }
}

export const appointmentService = new AppointmentService();
