<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;

class PasswordResetOtp extends BaseModel
{
    use HasFactory;
    
    protected $fillable = [
        'email', 
        'otp', 
        'expires_at',
        'used',
        'token'
    ];
    
    protected $casts = [
        'expires_at' => 'datetime',
        'used' => 'boolean',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];
    
    /**
     * Override setAttribute to handle expires_at properly during storage
     */
    public function setAttribute($key, $value)
    {
        // Handle expires_at specially to prevent BaseModel interference
        if ($key === 'expires_at' && $value !== null) {
            // Ensure it's stored as a proper datetime
            if (!($value instanceof Carbon)) {
                $value = Carbon::parse($value);
            }
            // Store directly in attributes array, bypassing BaseModel formatting
            $this->attributes[$key] = $value;
            return $this;
        }
        
        return parent::setAttribute($key, $value);
    }
    
    /**
     * Override getAttribute to handle expires_at properly
     */
    public function getAttribute($key)
    {
        // Handle expires_at specially to always return Carbon instance
        if ($key === 'expires_at') {
            $value = $this->getAttributeFromArray($key);
            if ($value !== null) {
                // Convert to Carbon if it's not already
                if (!($value instanceof Carbon)) {
                    return Carbon::parse($value);
                }
                return $value;
            }
            return null;
        }
        
        return parent::getAttribute($key);
    }
    
    /**
     * Override the BaseModel's field classification to exclude expires_at from date formatting
     */
    public function isFieldExcludedFromFormatting($fieldName)
    {
        // Exclude expires_at from BaseModel's date formatting since we handle it manually
        if ($fieldName === 'expires_at') {
            return true;
        }
        
        return parent::isFieldExcludedFromFormatting($fieldName);
    }
    
    /**
     * Generate a new OTP for the given email
     * 
     * @param string $email
     * @return string
     */
    public static function generateOtp(string $email): string
    {
        // Invalidate any existing OTPs for this email
        self::where('email', $email)->update(['used' => true]);
        
        // Generate a 6-digit OTP
        $otp = str_pad(rand(100000, 999999), 6, '0', STR_PAD_LEFT);
        
        // Set expiry to 5 minutes from now
        $expiresAt = Carbon::now()->addMinutes(5);
        
        // Create the OTP record
        $record = self::create([
            'email' => $email,
            'otp' => (string)$otp,
            'expires_at' => $expiresAt,
            'used' => false
        ]);
        
        // Debug log - use safe access to expires_at
        Log::info('OTP Created', [
            'email' => $email,
            'otp' => $otp,
            'expires_at_carbon' => $expiresAt,
            'expires_at_stored' => $record->getAttributeFromArray('expires_at'), // Raw value
            'expires_at_retrieved' => $record->expires_at, // Retrieved value
            'current_time' => Carbon::now(),
            'record_id' => $record->id
        ]);
        
        return (string)$otp;
    }
    
    /**
     * Verify if the given OTP is valid for the email
     * 
     * @param string $email
     * @param string $otp
     * @return bool
     */
    public static function verifyOtp(string $email, string $otp): bool
    {
        $currentTime = Carbon::now();
        
        // Debug: Check all records for this email
        $allRecords = self::where('email', $email)->get();
        Log::info('OTP Verification Debug', [
            'email' => $email,
            'otp_input' => $otp,
            'current_time' => $currentTime,
            'all_records' => $allRecords->map(function($rec) use ($currentTime) {
                $expiresAt = $rec->expires_at; // This will now use our custom getAttribute
                $isExpired = $expiresAt->lt($currentTime);
                
                return [
                    'id' => $rec->id,
                    'otp' => $rec->otp,
                    'used' => $rec->used,
                    'expires_at' => $expiresAt,
                    'expires_at_raw' => $rec->getAttributeFromArray('expires_at'),
                    'is_expired' => $isExpired,
                    'created_at' => $rec->created_at
                ];
            })->toArray()
        ]);
        
        $record = self::where('email', $email)
            ->where('otp', (string)$otp)
            ->where('used', false)
            ->where('expires_at', '>', $currentTime)
            ->first();
            
        if ($record) {
            Log::info('OTP Verification Success', [
                'email' => $email,
                'otp' => $otp,
                'record_id' => $record->id,
                'expires_at' => $record->expires_at,
                'current_time' => $currentTime
            ]);
            
            // Mark as used
            $record->update(['used' => true]);
            return true;
        }
        
        Log::warning('OTP Verification Failed', [
            'email' => $email,
            'otp_input' => $otp,
            'current_time' => $currentTime,
            'reason' => 'No valid record found'
        ]);
        
        return false;
    }
    
    /**
     * Check if the OTP has expired
     * 
     * @return bool
     */
    public function isExpired(): bool
    {
        return $this->expires_at->lt(Carbon::now());
    }
}
