package research.loghunter.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import research.loghunter.entity.ScanHistory;
import research.loghunter.service.ScanService;
import research.loghunter.service.SftpService;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/api/scan")
@RequiredArgsConstructor
public class ScanController {

    private final ScanService scanService;
    private final SftpService sftpService;
    private final ExecutorService executor = Executors.newCachedThreadPool();

    /**
     * 연결 테스트
     */
    @PostMapping("/test-connection/{serverId}")
    public ResponseEntity<SftpService.ConnectionTestResult> testConnection(@PathVariable Long serverId) {
        return ResponseEntity.ok(sftpService.testConnection(serverId));
    }

    /**
     * 단일 서버 스캔 (SSE로 진행상황 전송)
     */
    @GetMapping(value = "/start/{serverId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter startScan(@PathVariable Long serverId) {
        SseEmitter emitter = new SseEmitter(300000L);  // 5분 타임아웃

        executor.execute(() -> {
            try {
                ScanService.ScanResult result = scanService.scanServer(serverId, progress -> {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("progress")
                                .data(progress));
                    } catch (IOException e) {
                        emitter.completeWithError(e);
                    }
                });

                emitter.send(SseEmitter.event()
                        .name("complete")
                        .data(result));
                emitter.complete();

            } catch (Exception e) {
                try {
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data(e.getMessage()));
                } catch (IOException ignored) {}
                emitter.completeWithError(e);
            }
        });

        return emitter;
    }

    /**
     * 모든 서버 스캔 (SSE로 진행상황 전송)
     */
    @GetMapping(value = "/start-all", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter startAllScan() {
        SseEmitter emitter = new SseEmitter(600000L);  // 10분 타임아웃

        executor.execute(() -> {
            try {
                List<ScanService.ScanResult> results = scanService.scanAllServers(progress -> {
                    try {
                        emitter.send(SseEmitter.event()
                                .name("progress")
                                .data(progress));
                    } catch (IOException e) {
                        emitter.completeWithError(e);
                    }
                });

                emitter.send(SseEmitter.event()
                        .name("complete")
                        .data(results));
                emitter.complete();

            } catch (Exception e) {
                try {
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data(e.getMessage()));
                } catch (IOException ignored) {}
                emitter.completeWithError(e);
            }
        });

        return emitter;
    }

    /**
     * 단일 서버 스캔 (동기 방식)
     */
    @PostMapping("/execute/{serverId}")
    public ResponseEntity<ScanService.ScanResult> executeScan(@PathVariable Long serverId) {
        ScanService.ScanResult result = scanService.scanServer(serverId, null);
        return ResponseEntity.ok(result);
    }

    /**
     * 현재 진행 상황 조회
     */
    @GetMapping("/progress/{serverId}")
    public ResponseEntity<ScanService.ScanProgress> getProgress(@PathVariable Long serverId) {
        ScanService.ScanProgress progress = scanService.getProgress(serverId);
        if (progress == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(progress);
    }

    /**
     * 스캔 이력 조회
     */
    @GetMapping("/history/{serverId}")
    public ResponseEntity<List<ScanHistory>> getHistory(@PathVariable Long serverId) {
        return ResponseEntity.ok(scanService.getHistory(serverId));
    }

    /**
     * 분석 결과 초기화 (서버별)
     */
    @DeleteMapping("/reset/{serverId}")
    public ResponseEntity<Map<String, Object>> resetScanData(@PathVariable Long serverId) {
        ScanService.ResetResult result = scanService.resetScanData(serverId);
        return ResponseEntity.ok(Map.of(
                "success", true,
                "deletedErrors", result.deletedErrors(),
                "deletedFiles", result.deletedFiles(),
                "deletedHistories", result.deletedHistories()
        ));
    }

    /**
     * 전체 분석 결과 초기화
     */
    @DeleteMapping("/reset-all")
    public ResponseEntity<Map<String, Object>> resetAllScanData() {
        ScanService.ResetResult result = scanService.resetAllScanData();
        return ResponseEntity.ok(Map.of(
                "success", true,
                "deletedErrors", result.deletedErrors(),
                "deletedFiles", result.deletedFiles(),
                "deletedHistories", result.deletedHistories()
        ));
    }

    /**
     * 파일별 에러 통계 조회
     */
    @GetMapping("/stats/by-file")
    public ResponseEntity<List<ScanService.FileErrorStats>> getErrorStatsByFile(
            @RequestParam(required = false) Long serverId) {
        return ResponseEntity.ok(scanService.getErrorStatsByFile(serverId));
    }

    /**
     * 서버별 에러 통계 조회
     */
    @GetMapping("/stats/by-server")
    public ResponseEntity<List<ScanService.ServerErrorStats>> getErrorStatsByServer() {
        return ResponseEntity.ok(scanService.getErrorStatsByServer());
    }

    /**
     * 패턴별 에러 통계 조회
     */
    @GetMapping("/stats/by-pattern")
    public ResponseEntity<List<ScanService.PatternErrorStats>> getErrorStatsByPattern(
            @RequestParam(required = false) Long serverId) {
        return ResponseEntity.ok(scanService.getErrorStatsByPattern(serverId));
    }

    /**
     * 대시보드용: 서버별 최근 N일 일별 통계
     */
    @GetMapping("/stats/daily-by-server")
    public ResponseEntity<List<ScanService.ServerDailyStats>> getDailyStatsByServer(
            @RequestParam(defaultValue = "30") int days) {
        return ResponseEntity.ok(scanService.getDailyStatsByServer(days));
    }

    /**
     * 월별현황용: 서버별 해당 월 일별 통계
     */
    @GetMapping("/stats/monthly-by-server")
    public ResponseEntity<List<ScanService.ServerDailyStats>> getMonthlyStatsByServer(
            @RequestParam int year,
            @RequestParam int month) {
        return ResponseEntity.ok(scanService.getMonthlyStatsByServer(year, month));
    }

    /**
     * 일별현황용: 서버별 해당 날짜 5분 단위 통계
     */
    @GetMapping("/stats/time-by-server")
    public ResponseEntity<List<ScanService.ServerTimeStats>> getTimeStatsByServer(
            @RequestParam String date,
            @RequestParam(defaultValue = "5") int intervalMinutes) {
        java.time.LocalDate localDate = java.time.LocalDate.parse(date);
        return ResponseEntity.ok(scanService.getTimeStatsByServer(localDate, intervalMinutes));
    }
}
