<?php

declare(strict_types=1);

namespace backend\traits;

/**
 * BooleanFieldNormalizationTrait provides helpers for normalizing boolean fields.
 * 
 * This trait helps normalize boolean values from various formats (Y/N, 1/0, true/false)
 * which is common when dealing with legacy databases or external APIs.
 * 
 * Usage:
 * ```php
 * class MyModel extends ActiveRecord
 * {
 *     use BooleanFieldNormalizationTrait;
 *     
 *     public function beforeValidate()
 *     {
 *         $this->stop = $this->normalizeBoolean($this->stop);
 *         $this->web_stop = $this->normalizeBoolean($this->web_stop);
 *         return parent::beforeValidate();
 *     }
 * }
 * ```
 * 
 * @author Andrew Pickstock
 * @since 1.0
 */
trait BooleanFieldNormalizationTrait
{
    /**
     * Normalizes a boolean value from various formats to 1/0.
     * 
     * Handles: Y/N, yes/no, true/false, 1/0, t/f, on/off
     * 
     * @param mixed $value The value to normalize
     * @return int 1 for true, 0 for false
     */
    protected function normalizeBoolean(mixed $value): int
    {
        if ($value === null) {
            return 0;
        }
        
        // Already numeric
        if (is_numeric($value)) {
            return (int)(bool)$value;
        }
        
        // String values
        if (is_string($value)) {
            $normalized = strtolower(trim($value));
            
            $trueValues = ['y', 'yes', 'true', 't', 'on', '1'];
            $falseValues = ['n', 'no', 'false', 'f', 'off', '0', ''];
            
            if (in_array($normalized, $trueValues, true)) {
                return 1;
            }
            
            if (in_array($normalized, $falseValues, true)) {
                return 0;
            }
        }
        
        // Boolean values
        if (is_bool($value)) {
            return $value ? 1 : 0;
        }
        
        // Default to false for unknown values
        return 0;
    }
    
    /**
     * Normalizes multiple boolean fields at once.
     * 
     * @param array<string> $fields Field names to normalize
     * @return void
     */
    protected function normalizeBooleanFields(array $fields): void
    {
        foreach ($fields as $field) {
            if (property_exists($this, $field)) {
                $this->$field = $this->normalizeBoolean($this->$field);
            }
        }
    }
    
    /**
     * Converts a boolean value to Y/N format.
     * 
     * @param mixed $value The value to convert
     * @return string 'Y' or 'N'
     */
    protected function booleanToYN(mixed $value): string
    {
        return $this->normalizeBoolean($value) === 1 ? 'Y' : 'N';
    }
    
    /**
     * Converts a boolean value to Yes/No format.
     * 
     * @param mixed $value The value to convert
     * @return string 'Yes' or 'No'
     */
    protected function booleanToYesNo(mixed $value): string
    {
        return $this->normalizeBoolean($value) === 1 ? 'Yes' : 'No';
    }
    
    /**
     * Gets a CSS class for a boolean value.
     * 
     * @param mixed $value The boolean value
     * @param string $trueClass Class for true value (default: 'text-success')
     * @param string $falseClass Class for false value (default: 'text-danger')
     * @return string CSS class
     */
    protected function getBooleanClass(mixed $value, string $trueClass = 'text-success', string $falseClass = 'text-danger'): string
    {
        return $this->normalizeBoolean($value) === 1 ? $trueClass : $falseClass;
    }
    
    /**
     * Gets an icon for a boolean value.
     * 
     * @param mixed $value The boolean value
     * @param string $trueIcon Icon for true (default: 'fa fa-check')
     * @param string $falseIcon Icon for false (default: 'fa fa-times')
     * @return string Icon class
     */
    protected function getBooleanIcon(mixed $value, string $trueIcon = 'fa fa-check', string $falseIcon = 'fa fa-times'): string
    {
        return $this->normalizeBoolean($value) === 1 ? $trueIcon : $falseIcon;
    }
}
