<?php

require_once __DIR__ . '/BaseModel.php';

class OtpModel extends BaseModel
{

    protected $table = 'otp_codes';

    /**
     * Generate and save OTP
     */
    public function generateOtp($phone, $purpose = 'verification', $length = 6)
    {
        // Generate OTP
        $otp = str_pad(rand(0, pow(10, $length) - 1), $length, '0', STR_PAD_LEFT);

        // Set expiry time (5 minutes from now)
        $expiresAt = date('Y-m-d H:i:s', strtotime('+5 minutes'));

        // Clean up old/expired OTPs for this phone and purpose
        $this->cleanupOtps($phone, $purpose);

        // Save new OTP
        $data = [
            'phone' => $phone,
            'otp' => $otp,
            'purpose' => $purpose,
            'expires_at' => $expiresAt,
            'used' => 0,
            'created_at' => date('Y-m-d H:i:s')
        ];

        $otpId = $this->create($data);

        if ($otpId) {
            return [
                'id' => $otpId,
                'otp' => $otp,
                'expires_at' => $expiresAt
            ];
        }

        return false;
    }

    /**
     * Verify OTP
     */
    public function verifyOtp($phone, $otp, $purpose = 'verification')
    {
        $stmt = $this->db->prepare("
            SELECT id, otp, expires_at, used, created_at
            FROM {$this->table} 
            WHERE phone = ? 
            AND purpose = ? 
            AND used = 0 
            AND expires_at > NOW()
            ORDER BY created_at DESC 
            LIMIT 1
        ");

        if (!$stmt) {
            throw new Exception("Database prepare error: " . $this->db->error);
        }

        $stmt->bind_param("ss", $phone, $purpose);
        $stmt->execute();
        $result = $stmt->get_result();
        $otpRecord = $result->fetch_assoc();
        $stmt->close();

        if (!$otpRecord) {
            return ['success' => false, 'message' => 'OTP not found or expired'];
        }

        if ($otpRecord['otp'] !== $otp) {
            return ['success' => false, 'message' => 'Invalid OTP'];
        }

        // Mark OTP as used
        $this->markAsUsed($otpRecord['id']);

        // Cleanup used OTPs
        $this->cleanupOtps($phone, $purpose);

        return ['success' => true, 'message' => 'OTP verified successfully'];
    }

    /**
     * Mark OTP as used
     */
    public function markAsUsed($otpId)
    {
        $stmt = $this->db->prepare("UPDATE {$this->table} SET used = 1 WHERE id = ?");
        if (!$stmt) {
            throw new Exception("Database prepare error: " . $this->db->error);
        }

        $stmt->bind_param("i", $otpId);
        $result = $stmt->execute();
        $stmt->close();

        return $result;
    }

    /**
     * Clean up expired or used OTPs
     */
    public function cleanupOtps($phone, $purpose)
    {
        $stmt = $this->db->prepare("
            DELETE FROM {$this->table} 
            WHERE phone = ? 
            AND purpose = ? 
            AND (expires_at < NOW() OR used = 1)
        ");

        if (!$stmt) {
            throw new Exception("Database prepare error: " . $this->db->error);
        }

        $stmt->bind_param("ss", $phone, $purpose);
        $result = $stmt->execute();
        $stmt->close();

        return $result;
    }

    /**
     * Check if phone has valid OTP
     */
    public function hasValidOtp($phone, $purpose = 'verification')
    {
        $stmt = $this->db->prepare("
            SELECT COUNT(*) as count
            FROM {$this->table} 
            WHERE phone = ? 
            AND purpose = ? 
            AND used = 0 
            AND expires_at > NOW()
        ");

        if (!$stmt) {
            throw new Exception("Database prepare error: " . $this->db->error);
        }

        $stmt->bind_param("ss", $phone, $purpose);
        $stmt->execute();
        $result = $stmt->get_result();
        $row = $result->fetch_assoc();
        $stmt->close();

        return (int) $row['count'] > 0;
    }

    /**
     * Get latest OTP for phone and purpose
     */
    public function getLatestOtp($phone, $purpose = 'verification')
    {
        $stmt = $this->db->prepare("
            SELECT id, otp, expires_at, used, created_at
            FROM {$this->table} 
            WHERE phone = ? 
            AND purpose = ? 
            ORDER BY created_at DESC 
            LIMIT 1
        ");

        if (!$stmt) {
            throw new Exception("Database prepare error: " . $this->db->error);
        }

        $stmt->bind_param("ss", $phone, $purpose);
        $stmt->execute();
        $result = $stmt->get_result();
        $otp = $result->fetch_assoc();
        $stmt->close();

        return $otp;
    }
}
