package ru.kayashov.bar.controller;

import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.kayashov.bar.controller.dto.AuthRequestDto;
import ru.kayashov.bar.controller.dto.AuthResponseDto;
import ru.kayashov.bar.model.entity.Visitor;
import ru.kayashov.bar.repository.VisitorsRepository;
import ru.kayashov.bar.security.JwtTokenProvider;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {

    private final JwtTokenProvider jwtTokenProvider;
    private final VisitorsRepository visitorsRepository;
    private final PasswordEncoder passwordEncoder;

    @PostMapping("/login")
    public AuthResponseDto checkTelegramChat(@RequestBody AuthRequestDto dto) {
        if (dto.getByLogin()) {
            return checkLogin(dto.getLogin(), dto.getPassword());
        } else {
            return parseCode(dto.getCode());
        }
    }

    private AuthResponseDto parseCode(String code) {
        String decode = new String(Base64.getDecoder().decode(code), StandardCharsets.UTF_8);
        String[] decodeArr = decode.split(":");
        Visitor visitor = visitorsRepository.findById(Long.valueOf(decodeArr[0]))
                .orElseThrow();

        Integer visitorCode = visitor.getCode();
        if (visitorCode == null) {
            return new AuthResponseDto(null, "Повторите запрос кода из бота");
        }
        if (Integer.valueOf(decodeArr[1]).equals(visitor.getCode())) {
            visitor.setCode(null);
            visitor = visitorsRepository.save(visitor);
            return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null);
        }
        return new AuthResponseDto(null, "Неверный код подтверждения");
    }

    private AuthResponseDto checkLogin(String login, String password) {
        if (login == null || login.isEmpty() || password == null || password.isEmpty()) {
            return new AuthResponseDto(null, "Поля не могут быть пустые");
        }

        Optional<Visitor> visitorOpt = visitorsRepository.findByLogin(login);
        if (visitorOpt.isEmpty()) {
            return new AuthResponseDto(null, "Не найдет пользователь " + login);
        }
        Visitor visitor = visitorOpt.get();
        if (passwordEncoder.matches(password, visitor.getPassword())) {
            return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null);
        } else {
            return new AuthResponseDto(null, "Неверный логин или пароль");
        }
    }

    @PostMapping("refresh")
    public AuthResponseDto refreshToken(@RequestHeader("Authorization") String token) {
        Claims claims = jwtTokenProvider.extractAllClaims(token);
        Long visitorId = claims.get("id", Long.class);
        Visitor visitor = visitorsRepository.findById(visitorId).orElseThrow();
        return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null);
    }

}
