package com.alttd.altitudeweb.controllers.forms;

import com.alttd.altitudeweb.api.MailApi;
import com.alttd.altitudeweb.controllers.data_from_auth.AuthenticatedUuid;
import com.alttd.altitudeweb.database.web_db.mail.EmailVerification;
import com.alttd.altitudeweb.model.MailResponseDto;
import com.alttd.altitudeweb.model.SubmitEmailDto;
import com.alttd.altitudeweb.model.VerifyCodeDto;
import com.alttd.altitudeweb.model.EmailEntryDto;
import com.alttd.altitudeweb.services.limits.RateLimit;
import com.alttd.altitudeweb.services.mail.MailVerificationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.http.HttpStatus;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequiredArgsConstructor
@RateLimit(limit = 60, timeValue = 1, timeUnit = TimeUnit.HOURS)
public class MailController implements MailApi {

    private final MailVerificationService mailVerificationService;
    private final AuthenticatedUuid authenticatedUuid;

    @Override
    @RateLimit(limit = 5, timeValue = 1, timeUnit = TimeUnit.HOURS, key = "mailSubmit")
    public ResponseEntity<MailResponseDto> submitEmailForVerification(SubmitEmailDto submitEmailDto) {
        UUID uuid = authenticatedUuid.getAuthenticatedUserUuid();
        boolean emailAlreadyVerified = mailVerificationService.listAll(uuid).stream()
                                           .filter(EmailVerification::verified)
                                           .map(EmailVerification::email)
                                           .anyMatch(mail -> mail.equalsIgnoreCase(submitEmailDto.getEmail()));
        if (emailAlreadyVerified) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Email already verified for user");
        }

        EmailVerification saved = mailVerificationService.submitEmail(uuid, submitEmailDto.getEmail());
        MailResponseDto response = new MailResponseDto()
                .email(saved.email())
                .message("Verification email sent")
                .verified(false);
        return ResponseEntity.status(HttpStatus.CREATED).body(response);
    }

    @Override
    @RateLimit(limit = 20, timeValue = 1, timeUnit = TimeUnit.HOURS, key = "mailVerify")
    public ResponseEntity<MailResponseDto> verifyEmailCode(VerifyCodeDto verifyCodeDto) {
        UUID uuid = authenticatedUuid.getAuthenticatedUserUuid();
        Optional<EmailVerification> optionalEmailVerification = mailVerificationService.verifyCode(uuid, verifyCodeDto.getCode());
        if (optionalEmailVerification.isEmpty()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid verification code");
        }
        EmailVerification emailVerification = optionalEmailVerification.get();
        MailResponseDto response = new MailResponseDto()
                .email(emailVerification.email())
                .message("Email verified successfully")
                .verified(true);
        return ResponseEntity.ok(response);
    }

    @Override
    @RateLimit(limit = 5, timeValue = 1, timeUnit = TimeUnit.HOURS, key = "mailResend")
    public ResponseEntity<MailResponseDto> resendVerificationEmail(SubmitEmailDto submitEmailDto) {
        UUID uuid = authenticatedUuid.getAuthenticatedUserUuid();
        EmailVerification updated = mailVerificationService.resend(uuid, submitEmailDto.getEmail());
        if (updated == null) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Email not found for user");
        }
        MailResponseDto response = new MailResponseDto()
                .email(updated.email())
                .message("Verification email resent")
                .verified(false);
        return ResponseEntity.ok(response);
    }

    @Override
    @RateLimit(limit = 10, timeValue = 1, timeUnit = TimeUnit.HOURS, key = "mailDelete")
    public ResponseEntity<Void> deleteEmail(SubmitEmailDto submitEmailDto) {
        UUID uuid = authenticatedUuid.getAuthenticatedUserUuid();
        boolean deleted = mailVerificationService.delete(uuid, submitEmailDto.getEmail());
        if (!deleted) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Email not found for user");
        }
        return ResponseEntity.noContent().build();
    }

    @Override
    public ResponseEntity<List<EmailEntryDto>> getUserEmails() {
        UUID uuid = authenticatedUuid.getAuthenticatedUserUuid();
        List<EmailVerification> emails = mailVerificationService.listAll(uuid);
        List<EmailEntryDto> result = emails.stream()
                .map(ev -> new EmailEntryDto().email(ev.email()).verified(ev.verified()))
                .toList();
        return ResponseEntity.ok(result);
    }
}
