package de.htwsaar.webshop.controller;

import de.htwsaar.webshop.repository.entities.Account;
import de.htwsaar.webshop.service.AccountService;
import de.htwsaar.webshop.service.SessionService;
import de.htwsaar.webshop.service.ValidatorService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

import static de.htwsaar.webshop.config.ControllerPathConfig.*;
import static de.htwsaar.webshop.config.ParameterConfig.*;
import static de.htwsaar.webshop.util.LoggerUtil.logRequest;

@RestController
@Slf4j
public class AccountController {

    private final AccountService accountService;
    private final ValidatorService validatorService;
    private final SessionService sessionService;

    @Autowired
    public AccountController(AccountService accountService, ValidatorService validatorService, SessionService sessionService) {
        this.accountService = accountService;
        this.validatorService = validatorService;
        this.sessionService = sessionService;
    }

    @RequestMapping(path = EMAIL_BASE, method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<Boolean> isEmailUsed(HttpServletRequest request,
                                               @RequestParam(PARAM_EMAIL) String email) {
        logRequest(request);
        return accountService.existsWithEmail(email) ?
                ResponseEntity.ok(true) :
                ResponseEntity.notFound().build();
    }

    @RequestMapping(path = ACCOUNT_BASE_ALL, method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<List<Account>> getAllAccounts(HttpServletRequest request,
                                                        @RequestParam(PARAM_EMAIL) String email,
                                                        @RequestParam(PARAM_SESSION) UUID token) {
        logRequest(request);
        if (!sessionService.isAdmin(token, email)) {
            log.warn("[{}] Account isnt allowed to make request {}", request.getRequestURI(), email);
            return ResponseEntity.badRequest().build();
        }

        return ResponseEntity.ok(accountService.findAll());
    }

    @RequestMapping(path = ACCOUNT_BASE, method = RequestMethod.POST, produces = "application/json")
    public ResponseEntity<Void> createAccount(HttpServletRequest request,
                                              @RequestBody Account account) {
        logRequest(request);
        if (validatorService.isInvalid(account)) {
            log.warn("[{}] failed Validation, sending bad request", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        if (accountService.existsWithEmail(account.getEmail())) {
            log.warn("[{}] Account cant be created, Email is already in use", request.getRequestURI());
            return ResponseEntity.unprocessableEntity().build();
        }
        account.setId(null);
        if (accountService.saveNew(account).getId() == null) {
            return ResponseEntity.internalServerError().build();
        }
        return ResponseEntity.ok().build();
    }

    @RequestMapping(path = ACCOUNT_BASE, method = RequestMethod.DELETE, produces = "application/json")
    public ResponseEntity<Void> deleteAccount(HttpServletRequest request,
                                              @RequestParam(PARAM_EMAIL) String email,
                                              @RequestParam(PARAM_PASSWORD) String password) {
        logRequest(request);
        if (!accountService.existsWithEmail(email)) {
            log.warn("[{}] Account doesn't exist", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        Account acc = accountService.isValidLogin(email, password);
        if (acc == null) {
            log.warn("[{}] Invalid Credentials", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        if (!accountService.deleteIfExists(acc)) {
            return ResponseEntity.badRequest().build();
        }
        return ResponseEntity.ok().build();
    }

    @RequestMapping(path = ACCOUNT_BASE, method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<Account> getAccount(HttpServletRequest request,
                                              @RequestParam(PARAM_EMAIL) String email,
                                              @RequestParam(PARAM_PASSWORD) String password) {
        logRequest(request);
        if (!accountService.existsWithEmail(email)) {
            log.warn("[{}] Account doesn't exist", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        Account acc = accountService.isValidLogin(email, password);
        if (acc == null) {
            log.warn("[{}] Invalid Credentials", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        return ResponseEntity.ok(acc);
    }

    @RequestMapping(path = ACCOUNT_BASE, method = RequestMethod.PUT, produces = "application/json")
    public ResponseEntity<Account> updateAccount(HttpServletRequest request,
                                                 @RequestParam(PARAM_EMAIL) String email,
                                                 @RequestParam(PARAM_PASSWORD) String password,
                                                 @RequestBody Account account) {
        logRequest(request);
        if (validatorService.isInvalid(account)) {
            log.warn("[{}] failed Validation, sending bad request", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        if (!accountService.existsWithEmail(email)) {
            log.warn("[{}] Account doesn't exist", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        Account loggedIn = accountService.isValidLogin(email, password);
        if (loggedIn == null) {
            log.warn("[{}] Invalid Credentials", request.getRequestURI());
            return ResponseEntity.badRequest().build();
        }
        account.setId(loggedIn.getId());
        Account saved = accountService.save(account);
        if (saved == null) {
            return ResponseEntity.internalServerError().build();
        }
        return ResponseEntity.ok(saved);
    }

}
