<?php
// forgot_password.php

header("Content-Type: application/json; charset=UTF-8");

// Inklusi file keamanan, logger, rate limiting dan koneksi database
require 'security.php';
require 'logger.php';
require 'rate_limit.php';
require 'db.php';

// Jika menggunakan PHPMailer untuk pengiriman email OTP
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// Cek metode request
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['error' => 'Method Not Allowed']);
    log_activity("Method Not Allowed on forgot_password.php from IP: " . $_SERVER['REMOTE_ADDR']);
    exit;
}

// Ambil input JSON dan sanitasi
$input = json_decode(file_get_contents('php://input'), true);
$input = sanitize_input($input);

// Pastikan parameter 'email' ada
if (empty($input['email'])) {
    http_response_code(400);
    echo json_encode(['error' => 'Email is required']);
    log_activity("Email not provided in forgot_password request from IP: " . $_SERVER['REMOTE_ADDR']);
    exit;
}

$email = $input['email'];

// Validasi format email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid email format']);
    log_activity("Invalid email format '$email' in forgot_password request.");
    exit;
}

/*
   Kita buat dua alur:
   A) Jika hanya mengirimkan 'email' saja, maka proses adalah permintaan OTP.
   B) Jika mengirimkan 'email', 'otp', dan 'password', maka proses adalah reset password.
*/

// ----------
// A) Permintaan OTP untuk lupa password
// ----------
if (!isset($input['otp']) && !isset($input['password'])) {
    // Terapkan rate limiting khusus untuk permintaan OTP, misalnya 5 permintaan per menit
    $identifier = $_SERVER['REMOTE_ADDR'] . ':' . $_SERVER['REQUEST_URI'];
    rate_limit($pdo, 5, 60, $identifier);

    // Cek apakah email terdaftar
    $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch();

    if (!$user) {
        http_response_code(404);
        echo json_encode(['error' => 'Email not found']);
        log_activity("Forgot password requested for non-existent email '$email'.");
        exit;
    }
    $user_id = $user['id'];

    // Generate OTP 6 digit
    $plaintextOTP = mt_rand(100000, 999999);
    // Hash OTP menggunakan MD5 (Anda bisa menggunakan algoritma lain sesuai kebutuhan)
    $hashedOTP = md5($plaintextOTP);
    // Set masa berlaku OTP 30 menit dari sekarang
    $expiresAt = date('Y-m-d H:i:s', time() + (30 * 60));

    // Simpan OTP ke tabel otps
    try {
        $stmt = $pdo->prepare("INSERT INTO otps (user_id, otp_code, expires_at) VALUES (?, ?, ?)");
        $stmt->execute([$user_id, $hashedOTP, $expiresAt]);
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => 'Server error']);
        log_activity("Failed to insert OTP for forgot_password: " . $e->getMessage());
        exit;
    }

    // Sertakan file PHPMailer untuk pengiriman email
    require './mail/Exception.php';
    require './mail/PHPMailer.php';
    require './mail/SMTP.php';

    $mail = new PHPMailer(true);
    try {
        // Konfigurasi SMTP
        $mail->isSMTP();
        $mail->Host       = 'mail.kopmandan.com'; // Ganti sesuai SMTP Anda
        $mail->SMTPAuth   = true;
        $mail->Username   = 'admin@kopmandan.com';
        $mail->Password   = 'f2K7ToyDZrUQ';  // Password email
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port       = 587; // Atau 465 jika menggunakan SSL

        // Pengirim dan penerima
        $mail->setFrom('admin@kopmandan.com', 'Koperasi Komandan');
        $mail->addAddress($email);

        // Konten email OTP
        $mail->isHTML(true);
        $mail->Subject = 'Kode Verifikasi Lupa Password Anda';
        $validUntil = date('d F Y, H:i', strtotime($expiresAt)) . ' WIB';
        $mail->Body    = "
            <p>Salam,</p>
            <p>Berikut adalah kode OTP untuk mereset password Anda:</p>
            <h2 style='text-align:center;'>$plaintextOTP</h2>
            <p>Kode ini berlaku hingga <strong>$validUntil</strong> (30 menit).</p>
            <p>Jika Anda tidak meminta untuk mereset password, abaikan email ini.</p>
        ";

        // Kirim email
        $mail->send();

        http_response_code(200);
        echo json_encode([
            'message'        => 'OTP sent to your email',
            'info'           => 'Please check your inbox for the OTP code',
            'otp_expiration' => $expiresAt
        ]);
        log_activity("OTP for forgot password sent to '$email'.");
        exit;

    } catch (Exception $e) {
        $error = "Email error: " . $mail->ErrorInfo;
        http_response_code(500);
        echo json_encode(['error' => $error]);
        log_activity("Failed to send OTP email in forgot_password: $error");
        exit;
    }
}

// ----------
// B) Reset password menggunakan OTP
// ----------
elseif (isset($input['otp']) && isset($input['password'])) {
    // Terapkan rate limiting khusus untuk reset password, misalnya 10 permintaan per menit
    $identifier = $_SERVER['REMOTE_ADDR'] . ':' . $_SERVER['REQUEST_URI'];
    rate_limit($pdo, 10, 60, $identifier);

    $otp_input    = $input['otp'];
    $new_password = $input['password'];

    // Validasi panjang password minimal 8 karakter
    if (strlen($new_password) < 8) {
        http_response_code(400);
        echo json_encode(['error' => 'Password must be at least 8 characters']);
        log_activity("Weak password attempt during forgot_password reset for email '$email'.");
        exit;
    }

    // Cek apakah email terdaftar
    $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch();

    if (!$user) {
        http_response_code(404);
        echo json_encode(['error' => 'Email not found']);
        log_activity("Forgot password reset attempted for non-existent email '$email'.");
        exit;
    }
    $user_id = $user['id'];

    // Ambil OTP terakhir yang masih berlaku untuk user ini
    $stmt = $pdo->prepare("SELECT otp_code, expires_at FROM otps WHERE user_id = ? AND expires_at >= NOW() ORDER BY expires_at DESC LIMIT 1");
    $stmt->execute([$user_id]);
    $otp_record = $stmt->fetch();

    if (!$otp_record) {
        http_response_code(400);
        echo json_encode(['error' => 'OTP expired or invalid']);
        log_activity("No valid OTP found for forgot_password reset for email '$email'.");
        exit;
    }

    // Verifikasi OTP: bandingkan md5 dari input OTP dengan nilai yang disimpan
    if (md5($otp_input) !== $otp_record['otp_code']) {
        http_response_code(400);
        echo json_encode(['error' => 'Invalid OTP code']);
        log_activity("Invalid OTP code provided for forgot_password reset for email '$email'.");
        exit;
    }

    // Hash password baru menggunakan bcrypt
    $hashed_password = password_hash($new_password, PASSWORD_BCRYPT);

    // Perbarui password di tabel users dan hapus OTP yang telah digunakan
    try {
        $stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
        $stmt->execute([$hashed_password, $user_id]);

        // Hapus semua OTP terkait user ini untuk mencegah penggunaan ulang
        $stmt = $pdo->prepare("DELETE FROM otps WHERE user_id = ?");
        $stmt->execute([$user_id]);

        http_response_code(200);
        echo json_encode(['message' => 'Password reset successfully']);
        log_activity("Password reset successfully for email '$email'.");
        exit;
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => 'Server error']);
        log_activity("Error during password reset for email '$email': " . $e->getMessage());
        exit;
    }
}

// ----------
// Jika parameter tidak lengkap
// ----------
else {
    http_response_code(400);
    echo json_encode(['error' => 'Required fields missing']);
    log_activity("Invalid parameters provided in forgot_password request from IP: " . $_SERVER['REMOTE_ADDR']);
    exit;
}
?>
