package com.alterdekim.game.controller;

import com.alterdekim.game.component.ReferenceLoader;
import com.alterdekim.game.component.game.AvatarInventoryType;
import com.alterdekim.game.controller.result.signup.*;
import com.alterdekim.game.entity.AvatarInventory;
import com.alterdekim.game.entity.Role;
import com.alterdekim.game.entity.User;
import com.alterdekim.game.repository.UserRepository;
import com.alterdekim.game.security.AuthenticationUtil;
import com.alterdekim.game.service.AvatarInventoryService;
import com.alterdekim.game.service.GoodsService;
import com.alterdekim.game.service.IncompatibleService;
import com.alterdekim.game.service.UserService;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Base64;
import java.util.List;
import java.util.Optional;

import static com.alterdekim.game.utils.GameUtils.EmptyGoodId;

@Slf4j
@Controller
public class SignUpController {

    @Autowired
    private ReferenceLoader referenceLoader;

    @Autowired
    private AvatarInventoryService avatarInventoryService;

    @Autowired
    private IncompatibleService incompatibleService;

    @Autowired
    private UserService userService;

    @Autowired
    private GoodsService goodsService;

    @PostMapping("/ConstructorACHandler.ashx")
    public ResponseEntity<String> avatarController() {

        AvatarController controller = new AvatarController(
                "Smesharik",
                        new AvatarObject(
                                new Incompatibles(incompatibleService.getAll()),
                                List.of(
                                        new AvatarObjectSection("Shape", "Образ", avatarInventoryService.getShapeGroups()),
                                        new AvatarObjectSection("BodyParts", "Части тела", avatarInventoryService.getBodyPartGroups()),
                                        new AvatarObjectSection("Inventory", "Вещи", avatarInventoryService.getAvatarInventoryGroups())
                                )
                        )
                );
        try {
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_XML).body(
                    new XmlMapper().writeValueAsString(controller)
            );
        } catch (JsonProcessingException e) {
            log.error("AvatarConstructor controller error: {}", e.getMessage());
        }
        return ResponseEntity.noContent().build();
    }

    @PostMapping("/signup")
    public ResponseEntity<String> signup(
            @RequestParam("username") String username,
            @RequestParam("password") String password,
            @RequestParam("avatar") String avatar) {
        avatar = new String(Base64.getDecoder().decode(avatar));

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        xmlMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        SignUpAvatar av = null;
        try {
            av = xmlMapper.readValue(avatar, SignUpAvatar.class);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage());
            return ResponseEntity.badRequest().body("bad_avatar");
        }
        User existingUser = userService.findByUsername(username);

        if(existingUser != null && existingUser.getUsername() != null && !existingUser.getUsername().isEmpty() ) {
            return ResponseEntity.badRequest().body("already_exists");
        }

        if(!AuthenticationUtil.checkCredentials(username, password)) {
            return ResponseEntity.badRequest().body("bad_credentials_format");
        }

        int userId = userService.saveUser(username, password, Role.RoleType.RoleUser);

        avatarInventoryService.addPhoneToInventory(userId, 1L);
        avatarInventoryService.addBackgroundToInventory(userId, 339L);

        try {
            av.getInventory()
                    .stream()
                    .filter(i -> i.getID() != EmptyGoodId.intValue())
                    .map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.fromGoodId(goodsService, i.getID()), 0))
                    .forEach(i -> avatarInventoryService.addGoodToInventory(i));

            av.getBodyParts()
                    .stream()
                    .filter(i -> i.getID() != EmptyGoodId.intValue())
                    .map(i -> new AvatarInventory(referenceLoader.getUserReference(userId), i.getID().longValue(), true, AvatarInventoryType.BodyParts, i.getColor() == null ? 0 : i.getColor()))
                    .forEach(i -> avatarInventoryService.addGoodToInventory(i));
        } catch (Exception e) {
            userService.removeUser(userId);
            return ResponseEntity.badRequest().body("bad_avatar");
        }

        return ResponseEntity.ok("ok");
    }

    @GetMapping("/login")
    public String loginPage(Model model) {
        Optional<User> u = AuthenticationUtil.authProfile(userService);
        model.addAttribute("status", u.isPresent() ? "login_success" : "login_failed");
        return "login";
    }
}
