package com.cameleer.server.app.controller;

import com.cameleer.server.app.dto.AuditLogPageResponse;
import com.cameleer.server.core.admin.AuditCategory;
import com.cameleer.server.core.admin.AuditRepository;
import com.cameleer.server.core.admin.AuditRepository.AuditPage;
import com.cameleer.server.core.admin.AuditRepository.AuditQuery;
import com.cameleer.server.core.admin.AuditResult;
import com.cameleer.server.core.admin.AuditService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;

@RestController
@RequestMapping("/api/v1/admin/audit")
@PreAuthorize("hasRole('ADMIN')")
@Tag(name = "Audit Log", description = "Audit log viewer (ADMIN only)")
public class AuditLogController {

    private final AuditRepository auditRepository;
    private final AuditService auditService;

    public AuditLogController(AuditRepository auditRepository, AuditService auditService) {
        this.auditRepository = auditRepository;
        this.auditService = auditService;
    }

    @GetMapping
    @Operation(summary = "Search audit log entries with pagination")
    public ResponseEntity<AuditLogPageResponse> getAuditLog(
            HttpServletRequest httpRequest,
            @RequestParam(required = false) String username,
            @RequestParam(required = false) String category,
            @RequestParam(required = false) String search,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant from,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant to,
            @RequestParam(defaultValue = "timestamp") String sort,
            @RequestParam(defaultValue = "desc") String order,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "25") int size) {

        size = Math.min(size, 100);

        Instant fromInstant = from != null ? from : Instant.now().minus(java.time.Duration.ofDays(7));
        Instant toInstant = to != null ? to : Instant.now();

        AuditCategory cat = null;
        if (category != null && !category.isEmpty()) {
            try {
                cat = AuditCategory.valueOf(category.toUpperCase());
            } catch (IllegalArgumentException ignored) {
                // invalid category is treated as no filter
            }
        }

        auditService.log("view_audit_log", AuditCategory.AUTH, null, null, AuditResult.SUCCESS, httpRequest);

        AuditQuery query = new AuditQuery(username, cat, search, fromInstant, toInstant, sort, order, page, size);
        AuditPage result = auditRepository.find(query);

        int totalPages = Math.max(1, (int) Math.ceil((double) result.totalCount() / size));
        return ResponseEntity.ok(new AuditLogPageResponse(
                result.items(), result.totalCount(), page, size, totalPages));
    }
}
