package com.saas.tenant.controller;

import com.saas.tenant.entity.InboundCallRequest;
import com.saas.tenant.entity.Doctor; // Assuming Doctor entity is needed for DoctorRepository
import com.saas.tenant.repository.DoctorRepository;
import com.saas.tenant.service.CalendarAuthService;
import com.saas.tenant.service.CalendarSyncService;
import com.saas.tenant.service.InboundCallService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView;

import java.io.IOException;
import java.util.Map;

@RestController
@RequestMapping("/api/calendar")
@RequiredArgsConstructor
@Slf4j
public class CalendarController {

    private final CalendarAuthService authService;
    private final InboundCallService inboundCallService;
    private final CalendarSyncService calendarSyncService;
    private final DoctorRepository doctorRepository;

    @Value("${app.frontend.url:http://localhost:4200}")
    private String frontendUrl;

    @GetMapping("/auth/google")
    public ResponseEntity<Map<String, String>> getGoogleAuthUrl() {
        // Get current tenant from context
        String tenantId = com.saas.shared.core.TenantContext.getTenantId();
        log.info("🔐 [CalendarController] Initiating Google OAuth for tenant: {}", tenantId);

        // Construct the Backend Callback URL with tenant ID as state parameter
        String callbackUrl = "http://localhost:8000/api/calendar/callback/google";
        String authUrl = authService.getAuthorizationUrl(callbackUrl, tenantId);
        return ResponseEntity.ok(Map.of("url", authUrl));
    }

    /**
     * Google OAuth Callback Handler
     * Google redirects here after user grants permission
     * The tenant ID is passed back in the 'state' parameter
     */
    @GetMapping("/callback/google")
    public RedirectView handleGoogleCallbackWithCode(
            @RequestParam("code") String code,
            @RequestParam(value = "state", required = false) String tenantId,
            @RequestParam(value = "error", required = false) String error) {

        if (error != null) {
            log.error("❌ Google OAuth error: {}", error);
            return new RedirectView(frontendUrl + "/tenant/settings?calendar_error=" + error);
        }

        if (tenantId == null || tenantId.isEmpty()) {
            log.error("❌ No tenant ID in OAuth callback state parameter");
            return new RedirectView(frontendUrl + "/tenant/settings?calendar_error=missing_tenant");
        }

        try {
            // Set tenant context for this request
            com.saas.shared.core.TenantContext.setTenantId(tenantId);
            log.info("🔑 [CalendarController] Set tenant context to: {}", tenantId);

            // Exchange code for token
            String callbackUrl = "http://localhost:8000/api/calendar/callback/google";
            authService.exchangeCodeForToken(code, callbackUrl);
            log.info("✅ Google Calendar successfully connected for tenant: {}", tenantId);

            return new RedirectView(frontendUrl + "/tenant/settings?calendar_success=true");
        } catch (IOException e) {
            log.error("❌ Error exchanging code for token", e);
            return new RedirectView(frontendUrl + "/tenant/settings?calendar_error=connection_failed");
        } finally {
            // Clear tenant context
            com.saas.shared.core.TenantContext.clear();
        }
    }

    @GetMapping("/status")
    public ResponseEntity<Map<String, Boolean>> getStatus() {
        return ResponseEntity.ok(Map.of("connected", authService.isConnected()));
    }

    @GetMapping("/connection-status")
    public ResponseEntity<Map<String, Boolean>> getConnectionStatus() {
        String tenantId = com.saas.shared.core.TenantContext.getTenantId();
        log.info("🔍 [CalendarController] Checking connection status for tenant: {}", tenantId);

        boolean googleConnected = authService.isConnected("GOOGLE");
        boolean outlookConnected = authService.isConnected("OUTLOOK");

        return ResponseEntity.ok(Map.of(
                "googleConnected", googleConnected,
                "outlookConnected", outlookConnected));
    }

    @PostMapping("/disconnect")
    public ResponseEntity<Void> disconnect() {
        authService.disconnect();
        return ResponseEntity.ok().build();
    }

    @GetMapping("/events")
    public ResponseEntity<java.util.List<InboundCallRequest>> getEvents() {
        return ResponseEntity.ok(inboundCallService.getAppointments());
    }

    /**
     * Manual Sync Endpoint
     * Synchronizes all existing confirmed appointments for the authenticated doctor
     * from inbound_call_request to their Google Calendar
     * 
     * Usage: POST /api/calendar/sync-all
     * 
     * This endpoint should be called after connecting a Google Calendar account
     * to sync all historical appointments that were created before the integration
     * was set up.
     */
    @PostMapping("/sync-all")
    public ResponseEntity<Map<String, Object>> syncAllAppointments(Authentication authentication) {
        String tenantId = com.saas.shared.core.TenantContext.getTenantId();
        String userEmail = authentication.getName();
        log.info("🔄 [CalendarController] Manual sync requested by user: {} (tenant: {})", userEmail, tenantId);

        try {
            // Get doctor ID from authenticated user's email
            Long doctorId = getDoctorIdFromEmail(userEmail);
            if (doctorId == null) {
                log.warn("⚠️ [CalendarController] User {} is not associated with a doctor", userEmail);
                return ResponseEntity.badRequest()
                        .body(Map.of(
                                "success", false,
                                "message", "You must be a doctor to sync appointments to your calendar.",
                                "syncedCount", 0));
            }

            // Check if this doctor has Google Calendar connected
            if (!authService.isConnectedForDoctor(doctorId, "GOOGLE")) {
                log.warn("⚠️ [CalendarController] Doctor {} does not have Google Calendar connected", doctorId);
                return ResponseEntity.badRequest()
                        .body(Map.of(
                                "success", false,
                                "message", "Google Calendar is not connected. Please connect your account first.",
                                "syncedCount", 0));
            }

            int syncedCount = calendarSyncService.syncAllAppointmentsForDoctor(doctorId);

            log.info("✅ [CalendarController] Manual sync completed for doctor {} - Synced {} appointments",
                    doctorId, syncedCount);

            return ResponseEntity.ok(Map.of(
                    "success", true,
                    "message",
                    String.format("Successfully synced %d appointments to your Google Calendar", syncedCount),
                    "syncedCount", syncedCount));

        } catch (Exception e) {
            log.error("❌ [CalendarController] Manual sync failed for user: {}", userEmail, e);
            return ResponseEntity.status(500)
                    .body(Map.of(
                            "success", false,
                            "message", "Failed to sync appointments: " + e.getMessage(),
                            "syncedCount", 0));
        }
    }

    /**
     * Helper method to get doctor ID from user email
     */
    private Long getDoctorIdFromEmail(String email) {
        return doctorRepository.findByEmail(email)
                .map(Doctor::getId)
                .orElse(null);
    }
}
