package com.tutego.ch_09.mappers;

import com.tutego.ch_07.ProfileRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.temporal.ChronoUnit;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Stream;

@RestController // shorthand for @Controller + @ResponseBody
@RequestMapping("/api") // can also be used at class level (confusing)
public class AppRestController {

    private final ProfileRepository profileRepository;

    public AppRestController(ProfileRepository profileRepository) {
        this.profileRepository = profileRepository;
    }

    @GetMapping("/total") // == @RequestMapping(path = "/api/stat/total", method = RequestMethod.GET)
    public String totalNumberOfRegisteredUnicorns() {
        return String.valueOf(profileRepository.count());
    }

    @GetMapping("/last-seen")
    public ResponseEntity<LastSeenStatistics> lastSeenStatistics() {
        var start = YearMonth.now().minusYears(2);
        var end = YearMonth.now();
        var rnd = ThreadLocalRandom.current();
        var data = Stream.iterate(start, o -> o.plusMonths(1))
                .limit(start.until(end, ChronoUnit.MONTHS) + 1)
                .map(yearMonth -> new LastSeenStatistics.Data(yearMonth, rnd.nextInt(1000, 10000)))
                .toList();

        return ResponseEntity.ok(new LastSeenStatistics(data));
    }

    @RequestMapping("/test")
    public void handleRequest(HttpServletRequest in, HttpServletResponse out) {
        var requestUri = in.getRequestURI();
        var requestUrl = in.getRequestURL();
        var servletPath = in.getServletPath();
    }

    @GetMapping("/profile/search" /* ?q=fillmore */)
    public String requestParams(
            @RequestParam("q") String query,
            @RequestParam("page" /* can also specify a default value or mark the field as not required */) Optional<String> page,
            @RequestParam MultiValueMap<String, String> params // MultiValueMap<?, ?> is needed for q=fillmore&q=bold
    ) {
        return query;
    }

    @GetMapping("/profiles/{id}/photos/{index}")
    public String pathVariables(
            @PathVariable("id") long profileId,
            @PathVariable("index") int index
    ) {
        return String.valueOf(profileId);
    }

    @GetMapping("headers")
    public String handlerMethod(
            @RequestHeader("Accept-Language") String acceptLanguage,
            @RequestHeader(value = "User-Agent", defaultValue = "Bro") String userAgent,
            @RequestHeader("Keep-Alive") long keepAlive,
            @RequestHeader HttpHeaders allHttpHeaders
    ) {
        return acceptLanguage;
    }

    @GetMapping("/{name:[-\\w]+}.{suffix:\\w+}") // URI template pattern with regular expressions
    public void custom(
            @DateTimeFormat(pattern = "MM-dd-yyy") LocalDate date, // ConversionService only works with ISO-8601
            @ModelAttribute YearMonthRange range, // built by WebDataBinder, binds only request params
            BindingResult bindingResult, // binding the results avoids the handler throwing an exception (??)
            @RequestParam YearMonthRange anotherRange, // ?range=2024-01~2024-12 built through the Formatter<YearMonthRange>
            @PathVariable String name,
            @PathVariable String suffix
    ) {}
}