<?php

namespace App\Models;

use CodeIgniter\Model;

/**
 * MemberOtpModel — manages the `member_otps` table.
 *
 * One active OTP per profile at a time.
 * When a new OTP is generated, previous OTPs are marked inactive
 * (is_active = 0) — they are never deleted so a full audit trail
 * is preserved.
 */
class MemberOtpModel extends Model
{
    protected $table      = 'member_otps';
    protected $primaryKey = 'id';
    protected $returnType = 'array';

    protected $useTimestamps  = false; // we handle created_at manually
    protected $useSoftDeletes = false;

    protected $allowedFields = [
        'profile_id',
        'otp_code',
        'expires_at',
        'attempts',
        'is_used',
        'is_active',
        'created_at',
    ];

    // ----------------------------------------------------------------
    // Public helpers
    // ----------------------------------------------------------------

    /**
     * Generate and store a fresh 6-digit OTP for the given profile.
     * All previous OTPs for the same profile are marked inactive
     * (is_active = 0) so the audit trail is preserved.
     *
     * @param  int $profileId
     * @param  int $ttlSeconds  Time-to-live in seconds (default 300 = 5 min)
     * @return string           The plain-text OTP code
     */
    public function createOtp(int $profileId, int $ttlSeconds = 300): string
    {
        // Deactivate all previous OTPs for this profile (keep rows for audit)
        $this->where('profile_id', $profileId)
             ->where('is_active', 1)
             ->set('is_active', 0)
             ->update();

        // Generate a cryptographically random 6-digit code
        $code = str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
		$code='123456';
        $this->insert([
            'profile_id' => $profileId,
            'otp_code'   => $code,
            'expires_at' => date('Y-m-d H:i:s', time() + $ttlSeconds),
            'attempts'   => 0,
            'is_used'    => 0,
            'is_active'  => 1,
            'created_at' => date('Y-m-d H:i:s'),
        ]);

        return $code;
    }

    /**
     * Fetch the latest active (unused, not expired, not superseded) OTP row
     * for a profile.
     *
     * @param  int        $profileId
     * @return array|null
     */
    public function getActiveOtp(int $profileId): ?array
    {
        return $this
            ->where('profile_id', $profileId)
            ->where('is_used', 0)
            ->where('is_active', 1)
            ->where('expires_at >', date('Y-m-d H:i:s'))
            ->orderBy('id', 'DESC')
            ->first();
    }

    /**
     * Increment failed attempt counter for an OTP row.
     *
     * @param int $otpId
     */
    public function incrementAttempts(int $otpId): void
    {
        $this->set('attempts', 'attempts + 1', false)
             ->where('id', $otpId)
             ->update();
    }

    /**
     * Mark an OTP row as used (consumed after successful verification).
     *
     * @param int $otpId
     */
    public function markUsed(int $otpId): void
    {
        $this->update($otpId, ['is_used' => 1]);
    }

    /**
     * Deactivate all OTP rows for a profile (on logout / too-many-attempts).
     * Rows are kept in the table for audit purposes; only is_active is cleared.
     *
     * @param int $profileId
     */
    public function clearForProfile(int $profileId): void
    {
        $this->where('profile_id', $profileId)
             ->where('is_active', 1)
             ->set('is_active', 0)
             ->update();
    }
}
