<?php

namespace App\Models;

use CodeIgniter\Model;
use App\Libraries\FieldEncryption;

/**
 * ProfileModel — manages the `profiles` table.
 * Full utf8mb4 Unicode support; no input translation.
 *
 * Sensitive fields (email, mobile, address) are transparently
 * encrypted at rest using AES-256-CBC via FieldEncryption.
 */
class ProfileModel extends Model
{
    protected $table          = 'profiles';
    protected $primaryKey     = 'id';
    protected $useSoftDeletes = true;
    protected $useTimestamps  = true;
    protected $createdField   = 'created_at';
    protected $updatedField   = 'updated_at';
    protected $deletedField   = 'deleted_at';
    protected $returnType     = 'array';

    protected $allowedFields = [
        'name', 'company_name', 'designation',
        'email', 'mobile', 'mobile_country_code', 'about_us', 'address',
        'latitude', 'longitude', 'profile_photo', 'company_logo',
        'linkedin', 'instagram', 'facebook', 'twitter', 'youtube', 'website',
        'theme', 'slug', 'is_active', 'created_by',
    ];

    // Validation — accept all Unicode characters
    // Note: email max_length validation is on plaintext (before encryption)
    protected $validationRules = [
        'name'   => 'required|max_length[255]',
        'email'  => 'permit_empty|valid_email|max_length[191]',
        'mobile' => 'permit_empty|max_length[20]',
        'slug'   => 'permit_empty|alpha_dash|max_length[255]|is_unique[profiles.slug,id,{id}]',
    ];

    protected $validationMessages = [
        'name'  => ['required' => 'Name is required.'],
        'email' => ['valid_email' => 'Please enter a valid email address.'],
    ];

    // ── Encrypted fields ──────────────────────────────────────────────
    /** Fields encrypted at rest. */
    private array $encryptedFields = ['email', 'mobile', 'address'];

    // ── Model callbacks ───────────────────────────────────────────────
    protected $beforeInsert = ['encryptSensitiveFields'];
    protected $beforeUpdate = ['encryptSensitiveFields'];
    protected $afterFind    = ['decryptSensitiveFields'];

    /**
     * Encrypt sensitive fields before INSERT / UPDATE.
     */
    protected function encryptSensitiveFields(array $data): array
    {
        foreach ($this->encryptedFields as $field) {
            if (array_key_exists($field, $data['data'])
                && $data['data'][$field] !== null
                && $data['data'][$field] !== ''
            ) {
                $data['data'][$field] = FieldEncryption::encrypt($data['data'][$field]);
            }
        }
        return $data;
    }

    /**
     * Decrypt sensitive fields after any SELECT.
     */
    protected function decryptSensitiveFields(array $data): array
    {
        if (empty($data['data'])) {
            return $data;
        }

        if ($data['singleton']) {
            // Single row returned by find($id)
            foreach ($this->encryptedFields as $field) {
                if (array_key_exists($field, $data['data'])) {
                    $data['data'][$field] = FieldEncryption::decrypt($data['data'][$field]);
                }
            }
        } else {
            // Array of rows returned by findAll() / paginate()
            foreach ($data['data'] as &$row) {
                foreach ($this->encryptedFields as $field) {
                    if (array_key_exists($field, $row)) {
                        $row[$field] = FieldEncryption::decrypt($row[$field]);
                    }
                }
            }
            unset($row);
        }

        return $data;
    }

    // ----------------------------------------------------------------
    // Helpers
    // ----------------------------------------------------------------

    /**
     * Return paginated + filtered profile list.
     */
    public function getList(array $filters = [], int $perPage = 15): array
    {
        $builder = $this->select('profiles.*, admin_users.name AS created_by_name')
                        ->join('admin_users', 'admin_users.id = profiles.created_by', 'left');

        if (! empty($filters['search'])) {
            $search = $filters['search'];
            // email / mobile / address are encrypted — only search plaintext columns
            $builder->groupStart()
                    ->like('profiles.name',         $search)
                    ->orLike('profiles.company_name',$search)
                    ->orLike('profiles.designation', $search)
                    ->groupEnd();
        }

        if (isset($filters['is_active']) && $filters['is_active'] !== '') {
            $builder->where('profiles.is_active', (int)$filters['is_active']);
        }

        $builder->orderBy('profiles.created_at', 'DESC');

        return [
            'data'   => $builder->paginate($perPage, 'default'),
            'pager'  => $this->pager,
            'total'  => $builder->countAllResults(false),
        ];
    }

    /**
     * Generate a URL-safe slug from a name.
     */
    public function generateSlug(string $name, ?int $excludeId = null): string
    {
        // Transliterate to ASCII where possible, else keep original
        $slug = mb_strtolower(trim($name));
        $slug = preg_replace('/[\s\-]+/', '-', $slug);
        $slug = preg_replace('/[^\p{L}\p{N}\-]/u', '', $slug);
        $slug = trim($slug, '-');

        if (empty($slug)) {
            $slug = 'profile-' . time();
        }

        // Ensure uniqueness
        $base  = $slug;
        $i     = 1;
        $query = $this->where('slug', $slug);
        if ($excludeId) {
            $query->where('id !=', $excludeId);
        }
        while ($query->countAllResults() > 0) {
            $slug  = $base . '-' . $i++;
            $query = $this->where('slug', $slug);
            if ($excludeId) {
                $query->where('id !=', $excludeId);
            }
        }

        return $slug;
    }

    /**
     * Dashboard stats.
     */
    public function getTotalCount(): int
    {
        return $this->countAll();
    }

    public function getActiveCount(): int
    {
        return $this->where('is_active', 1)->countAllResults();
    }

    public function getRecentProfiles(int $limit = 5): array
    {
        return $this->select('id, name, company_name, designation, profile_photo, is_active, created_at')
                    ->orderBy('created_at', 'DESC')
                    ->limit($limit)
                    ->findAll();
    }
}
