package com.saas.tenant.service;

import com.google.api.client.auth.oauth2.Credential;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.EventDateTime;
import com.saas.tenant.entity.CalendarIntegration;
import com.saas.tenant.entity.InboundCallRequest;
import com.saas.tenant.repository.CalendarIntegrationRepository;
import com.saas.tenant.repository.InboundCallRequestRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class CalendarSyncService {

    private final CalendarIntegrationRepository repository;
    private final InboundCallRequestRepository requestRepository;

    @Value("${google.client.id}")
    private String clientId;

    @Value("${google.client.secret}")
    private String clientSecret;

    private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
    private static final String APPLICATION_NAME = "SaaSForge/1.0";

    /**
     * Sync appointment to doctor's calendar
     * Only syncs if appointment has a doctor assigned and that doctor has calendar
     * connected
     */
    public void syncAppointment(InboundCallRequest request) {
        if (!Boolean.TRUE.equals(request.getAppointmentConfirmed()) || request.getAppointmentDateTime() == null) {
            return;
        }

        // Only sync if appointment has a doctor assigned
        if (request.getDoctorId() == null) {
            log.warn("⚠️ Appointment {} has no doctor assigned, skipping calendar sync", request.getCallSid());
            return;
        }

        // Find doctor's Google Calendar integration
        repository.findByDoctorIdAndProvider(request.getDoctorId(), CalendarIntegration.Provider.GOOGLE)
                .filter(CalendarIntegration::getIsActive)
                .ifPresentOrElse(
                        integration -> createGoogleEvent(integration, request),
                        () -> log.debug("No active Google Calendar integration for doctor {}", request.getDoctorId()));
    }

    /**
     * Sync all appointments for a specific doctor to their Google Calendar
     * 
     * @param doctorId ID of the doctor whose appointments to sync
     * @return Number of appointments successfully synced
     */
    public int syncAllAppointmentsForDoctor(Long doctorId) {
        log.info("🔄 [CalendarSyncService] Starting manual sync for doctor {}", doctorId);

        // Get all confirmed appointments for this doctor
        List<InboundCallRequest> appointments = requestRepository
                .findByDoctorIdAndAppointmentConfirmedTrueAndAppointmentDateTimeNotNull(doctorId);

        log.info("📅 [CalendarSyncService] Found {} confirmed appointments for doctor {}",
                appointments.size(), doctorId);

        int syncedCount = 0;
        int failedCount = 0;

        for (InboundCallRequest appointment : appointments) {
            try {
                syncAppointment(appointment);
                syncedCount++;
                log.debug("✅ Synced appointment: {}", appointment.getCallSid());
            } catch (Exception e) {
                failedCount++;
                log.warn("⚠️ Failed to sync appointment {}: {}", appointment.getCallSid(), e.getMessage());
            }
        }

        log.info("✅ [CalendarSyncService] Manual sync completed for doctor {} - Synced: {}, Failed: {}",
                doctorId, syncedCount, failedCount);
        return syncedCount;
    }

    private void createGoogleEvent(CalendarIntegration integration, InboundCallRequest request) {
        try {
            final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

            GoogleCredentials credentials = GoogleCredentials.create(
                new AccessToken(integration.getAccessToken(), null)
            );

            Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, 
                new com.google.auth.http.HttpCredentialsAdapter(credentials))
                .setApplicationName(APPLICATION_NAME)
                .build();

            Event event = new Event()
                    .setSummary("RDV Patient: " + request.getNom())
                    .setDescription(
                            "Visite pour: " + request.getMotifVisite() + "\nContact: " + request.getTelephone());

            // Convert LocalDateTime to ZonedDateTime for Google API (Assuming system zone
            // or UTC, better to configure tenant timezone)
            ZonedDateTime startZoned = request.getAppointmentDateTime().atZone(ZoneId.systemDefault());
            DateTime start = new DateTime(Date.from(startZoned.toInstant()));
            EventDateTime startEventDateTime = new EventDateTime().setDateTime(start);

            // Assume 30 min duration
            DateTime end = new DateTime(Date.from(startZoned.plusMinutes(30).toInstant()));
            EventDateTime endEventDateTime = new EventDateTime().setDateTime(end);

            event.setStart(startEventDateTime);
            event.setEnd(endEventDateTime);

            String calendarId = integration.getCalendarId() != null ? integration.getCalendarId() : "primary";
            event = service.events().insert(calendarId, event).execute();

            log.info("✅ Event created in Google Calendar: {}", event.getHtmlLink());

        } catch (IOException | GeneralSecurityException e) {
            log.error("Failed to sync with Google Calendar", e);
        }
    }
}
