package com.saas.admin.controller;

import com.saas.admin.dto.response.AuditLogResponse;
import com.saas.admin.service.AuditLogService;
import com.saas.shared.dto.common.ApiResponse;
import com.saas.shared.dto.common.PageResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.Map;

/**
 * Admin Audit Log Controller
 * 
 * Provides REST endpoints for querying and analyzing audit logs across the platform.
 * All endpoints require SYSTEM_ADMIN role.
 * 
 * Audit logs are immutable records of all significant operations in the system,
 * including create, update, delete operations on critical entities.
 */
@RestController
@RequestMapping("/api/admin/audit-logs")
@PreAuthorize("hasRole('SYSTEM_ADMIN')")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Admin - Audit Logs", description = "View, filter, and analyze audit logs")
public class AdminAuditLogController {

    private final AuditLogService auditLogService;

    /**
     * Get paginated audit logs with optional filtering
     */
    @GetMapping
    @Operation(summary = "Get audit logs with filtering and pagination", 
               description = "Retrieve audit logs with optional filters for action, entity type, user, tenant, and date range")
    public ResponseEntity<ApiResponse<PageResponse<AuditLogResponse>>> getAuditLogs(
            @Parameter(description = "Page number (0-indexed)")
            @RequestParam(defaultValue = "0") int page,
            
            @Parameter(description = "Page size")
            @RequestParam(defaultValue = "20") int size,
            
            @Parameter(description = "Filter by action (e.g., CREATE, UPDATE, DELETE, LOGIN)")
            @RequestParam(required = false) String action,
            
            @Parameter(description = "Filter by entity type (e.g., User, Tenant, Role, Permission)")
            @RequestParam(required = false) String entityType,
            
            @Parameter(description = "Filter by user ID")
            @RequestParam(required = false) Long userId,
            
            @Parameter(description = "Filter by tenant ID")
            @RequestParam(required = false) String tenantId,
            
            @Parameter(description = "Filter by start date (ISO format: YYYY-MM-DD)")
            @RequestParam(required = false) 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            
            @Parameter(description = "Filter by end date (ISO format: YYYY-MM-DD)")
            @RequestParam(required = false) 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        log.info("Fetching audit logs - page: {}, size: {}, filters: action={}, entityType={}, userId={}, tenantId={}", 
                 page, size, action, entityType, userId, tenantId);

        PageResponse<AuditLogResponse> response = auditLogService.getAuditLogs(
            page, size, action, entityType, userId, tenantId, startDate, endDate
        );

        return ResponseEntity.ok(ApiResponse.success(response, "Audit logs retrieved successfully"));
    }

    /**
     * Get single audit log by ID
     */
    @GetMapping("/{id}")
    @Operation(summary = "Get audit log by ID", description = "Retrieve a specific audit log entry")
    public ResponseEntity<ApiResponse<AuditLogResponse>> getAuditLogById(
            @Parameter(description = "Audit log ID")
            @PathVariable Long id) {

        log.info("Fetching audit log detail: {}", id);
        AuditLogResponse response = auditLogService.getAuditLogById(id);
        return ResponseEntity.ok(ApiResponse.success(response));
    }

    /**
     * Get audit log statistics and summary
     */
    @GetMapping("/stats/summary")
    @Operation(summary = "Get audit logs summary statistics", 
               description = "Retrieve aggregated statistics about audit logs (counts by action, entity type, tenant)")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getAuditLogStatistics() {

        log.info("Fetching audit logs statistics");
        Map<String, Object> stats = auditLogService.getAuditLogStatistics();
        return ResponseEntity.ok(ApiResponse.success(stats, "Audit statistics retrieved successfully"));
    }

    /**
     * Get audit logs for a specific tenant
     */
    @GetMapping("/tenant/{tenantId}")
    @Operation(summary = "Get audit logs for a specific tenant", 
               description = "Retrieve all audit logs for a given tenant with pagination")
    public ResponseEntity<ApiResponse<PageResponse<AuditLogResponse>>> getTenantAuditLogs(
            @Parameter(description = "Tenant ID")
            @PathVariable String tenantId,
            
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {

        log.info("Fetching audit logs for tenant: {} - page: {}, size: {}", tenantId, page, size);
        PageResponse<AuditLogResponse> response = auditLogService.getTenantAuditLogs(tenantId, page, size);
        return ResponseEntity.ok(ApiResponse.success(response));
    }

    /**
     * Get audit logs for a specific user
     */
    @GetMapping("/user/{userId}")
    @Operation(summary = "Get audit logs for a specific user", 
               description = "Retrieve all audit logs created by a specific user")
    public ResponseEntity<ApiResponse<PageResponse<AuditLogResponse>>> getUserAuditLogs(
            @Parameter(description = "User ID")
            @PathVariable Long userId,
            
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {

        log.info("Fetching audit logs for user: {} - page: {}, size: {}", userId, page, size);
        PageResponse<AuditLogResponse> response = auditLogService.getUserAuditLogs(userId, page, size);
        return ResponseEntity.ok(ApiResponse.success(response));
    }
}
