package gc.mda.kcg.admin;

import gc.mda.kcg.audit.AccessLogRepository;
import gc.mda.kcg.audit.AuditLogRepository;
import gc.mda.kcg.auth.LoginHistoryRepository;
import gc.mda.kcg.permission.annotation.RequirePermission;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 시스템 관리 대시보드 메트릭 API.
 *
 * - 감사 로그 / 접근 로그 / 로그인 이력 통계
 * - 24시간 / 7일 추세
 * - 액션별 / 상태별 분포
 *
 * 권한: admin:audit-logs, admin:access-logs, admin:login-history (READ)
 */
@RestController
@RequestMapping("/api/admin/stats")
@RequiredArgsConstructor
public class AdminStatsController {

    private final AuditLogRepository auditLogRepository;
    private final AccessLogRepository accessLogRepository;
    private final LoginHistoryRepository loginHistoryRepository;
    private final JdbcTemplate jdbc;

    /**
     * 감사 로그 통계.
     * - total: 전체 건수
     * - last24h: 24시간 내 건수
     * - failed24h: 24시간 내 FAILED 건수
     * - byAction: 액션별 카운트 (top 10)
     * - hourly24: 시간별 24시간 추세
     */
    @GetMapping("/audit")
    @RequirePermission(resource = "admin:audit-logs", operation = "READ")
    public Map<String, Object> auditStats() {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("total", auditLogRepository.count());
        result.put("last24h", jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_audit_log WHERE created_at > now() - interval '24 hours'", Long.class));
        result.put("failed24h", jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_audit_log WHERE created_at > now() - interval '24 hours' AND result = 'FAILED'", Long.class));

        List<Map<String, Object>> byAction = jdbc.queryForList(
                "SELECT action_cd AS action, COUNT(*) AS count FROM kcg.auth_audit_log " +
                "WHERE created_at > now() - interval '7 days' " +
                "GROUP BY action_cd ORDER BY count DESC LIMIT 10");
        result.put("byAction", byAction);

        List<Map<String, Object>> hourly = jdbc.queryForList(
                "SELECT date_trunc('hour', created_at) AS hour, COUNT(*) AS count " +
                "FROM kcg.auth_audit_log " +
                "WHERE created_at > now() - interval '24 hours' " +
                "GROUP BY hour ORDER BY hour");
        result.put("hourly24", hourly);

        return result;
    }

    /**
     * 접근 로그 통계.
     * - total: 전체 건수
     * - last24h: 24시간 내
     * - error4xx, error5xx: 24시간 내 에러
     * - avgDurationMs: 24시간 내 평균 응답 시간
     * - topPaths: 24시간 내 호출 많은 경로
     */
    @GetMapping("/access")
    @RequirePermission(resource = "admin:access-logs", operation = "READ")
    public Map<String, Object> accessStats() {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("total", accessLogRepository.count());
        result.put("last24h", jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_access_log WHERE created_at > now() - interval '24 hours'", Long.class));
        result.put("error4xx", jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_access_log WHERE created_at > now() - interval '24 hours' AND status_code >= 400 AND status_code < 500", Long.class));
        result.put("error5xx", jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_access_log WHERE created_at > now() - interval '24 hours' AND status_code >= 500", Long.class));

        Double avg = jdbc.queryForObject(
                "SELECT AVG(duration_ms)::float FROM kcg.auth_access_log WHERE created_at > now() - interval '24 hours'",
                Double.class);
        result.put("avgDurationMs", avg != null ? Math.round(avg * 10) / 10.0 : 0);

        List<Map<String, Object>> topPaths = jdbc.queryForList(
                "SELECT request_path AS path, COUNT(*) AS count, AVG(duration_ms)::int AS avg_ms " +
                "FROM kcg.auth_access_log " +
                "WHERE created_at > now() - interval '24 hours' AND request_path NOT LIKE '/actuator%' " +
                "GROUP BY request_path ORDER BY count DESC LIMIT 10");
        result.put("topPaths", topPaths);

        return result;
    }

    /**
     * 로그인 통계.
     * - total: 전체 건수
     * - success24h: 24시간 내 성공
     * - failed24h: 24시간 내 실패
     * - locked24h: 24시간 내 잠금
     * - successRate: 성공률 (24시간 내, %)
     * - byUser: 사용자별 성공 카운트 (top 10)
     * - daily7d: 7일 일별 추세
     */
    @GetMapping("/login")
    @RequirePermission(resource = "admin:login-history", operation = "READ")
    public Map<String, Object> loginStats() {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("total", loginHistoryRepository.count());

        Long success24h = jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_login_hist WHERE login_dtm > now() - interval '24 hours' AND result = 'SUCCESS'", Long.class);
        Long failed24h = jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_login_hist WHERE login_dtm > now() - interval '24 hours' AND result = 'FAILED'", Long.class);
        Long locked24h = jdbc.queryForObject(
                "SELECT COUNT(*) FROM kcg.auth_login_hist WHERE login_dtm > now() - interval '24 hours' AND result = 'LOCKED'", Long.class);

        result.put("success24h", success24h);
        result.put("failed24h", failed24h);
        result.put("locked24h", locked24h);

        long total24h = (success24h == null ? 0 : success24h) + (failed24h == null ? 0 : failed24h) + (locked24h == null ? 0 : locked24h);
        double rate = total24h == 0 ? 0 : (success24h == null ? 0 : success24h) * 100.0 / total24h;
        result.put("successRate", Math.round(rate * 10) / 10.0);

        List<Map<String, Object>> byUser = jdbc.queryForList(
                "SELECT user_acnt, COUNT(*) AS count FROM kcg.auth_login_hist " +
                "WHERE login_dtm > now() - interval '7 days' AND result = 'SUCCESS' " +
                "GROUP BY user_acnt ORDER BY count DESC LIMIT 10");
        result.put("byUser", byUser);

        List<Map<String, Object>> daily = jdbc.queryForList(
                "SELECT date_trunc('day', login_dtm) AS day, " +
                "COUNT(*) FILTER (WHERE result='SUCCESS') AS success, " +
                "COUNT(*) FILTER (WHERE result='FAILED') AS failed, " +
                "COUNT(*) FILTER (WHERE result='LOCKED') AS locked " +
                "FROM kcg.auth_login_hist " +
                "WHERE login_dtm > now() - interval '7 days' " +
                "GROUP BY day ORDER BY day");
        result.put("daily7d", daily);

        return result;
    }
}
