package com.gnx.telemedicine.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;
import java.sql.Connection;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * Health check endpoints for monitoring and orchestration systems.
 */
@RestController
@RequestMapping("/actuator")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Health", description = "Health check endpoints for monitoring")
public class HealthController {

    private final DataSource dataSource;

    @Value("${spring.application.name:telemedicine}")
    private String applicationName;

    @Operation(
        summary = "Health check",
        description = "Basic health check endpoint. Returns 200 if the service is running."
    )
    @ApiResponse(responseCode = "200", description = "Service is healthy")
    @GetMapping("/health")
    public ResponseEntity<Map<String, Object>> health() {
        Map<String, Object> health = new HashMap<>();
        health.put("status", "UP");
        health.put("application", applicationName);
        health.put("timestamp", LocalDateTime.now());
        
        return ResponseEntity.ok(health);
    }

    @Operation(
        summary = "Readiness check",
        description = "Readiness check endpoint. Returns 200 if the service is ready to accept traffic."
    )
    @ApiResponse(responseCode = "200", description = "Service is ready")
    @GetMapping("/health/readiness")
    public ResponseEntity<Map<String, Object>> readiness() {
        Map<String, Object> readiness = new HashMap<>();
        readiness.put("status", "READY");
        readiness.put("application", applicationName);
        readiness.put("timestamp", LocalDateTime.now());
        
        return ResponseEntity.ok(readiness);
    }

    @Operation(
        summary = "Liveness check",
        description = "Liveness check endpoint. Returns 200 if the service is alive."
    )
    @ApiResponse(responseCode = "200", description = "Service is alive")
    @GetMapping("/health/liveness")
    public ResponseEntity<Map<String, Object>> liveness() {
        Map<String, Object> liveness = new HashMap<>();
        liveness.put("status", "ALIVE");
        liveness.put("application", applicationName);
        liveness.put("timestamp", LocalDateTime.now());
        
        return ResponseEntity.ok(liveness);
    }

    @Operation(
        summary = "Database health check",
        description = "Checks database connectivity. Returns 200 if database is accessible. " +
                     "Note: Use /actuator/health/db for detailed database health information."
    )
    @ApiResponse(responseCode = "200", description = "Database is accessible")
    @ApiResponse(responseCode = "503", description = "Database is not accessible")
    @GetMapping("/health/db")
    public ResponseEntity<Map<String, Object>> databaseHealth() {
        Map<String, Object> dbHealth = new HashMap<>();
        
        try (Connection connection = dataSource.getConnection()) {
            boolean isValid = connection.isValid(5); // 5 second timeout
            
            if (isValid) {
                dbHealth.put("status", "UP");
                dbHealth.put("database", "connected");
                dbHealth.put("timestamp", LocalDateTime.now());
                return ResponseEntity.ok(dbHealth);
            } else {
                dbHealth.put("status", "DOWN");
                dbHealth.put("database", "connection failed");
                dbHealth.put("timestamp", LocalDateTime.now());
                return ResponseEntity.status(503).body(dbHealth);
            }
        } catch (Exception e) {
            log.error("Database health check failed", e);
            dbHealth.put("status", "DOWN");
            dbHealth.put("database", "error: " + e.getMessage());
            dbHealth.put("timestamp", LocalDateTime.now());
            return ResponseEntity.status(503).body(dbHealth);
        }
    }
}

