<?php

namespace Core\App\Models;

use PDO;

class TeamMemberModel
{
    protected PDO $db;

    // الأدوار المتاحة
    public const ROLES = [
        'owner'      => 'team.role_owner',
        'manager'    => 'team.role_manager',
        'confirmer'  => 'team.role_confirmer',
        'shipping'   => 'team.role_shipping',
        'accountant' => 'team.role_accountant',
    ];

    // دالة مساعدة لترجمة اسم الدور
    public static function roleLabel(string $role): string
    {
        $key = self::ROLES[$role] ?? $role;
        return __($key, $role);
    }

    // الأدوار التي تستطيع تعيين أعضاء آخرين
    public const CAN_MANAGE = ['owner', 'manager'];

    /* =====================================================
       كل الصلاحيات الممكنة في النظام
    ===================================================== */
    public const ALL_PERMISSIONS = [
        'view_orders'           => 'رؤية جميع الطلبات',
        'view_assigned_orders'  => 'رؤية الطلبات المعينة فقط',
        'view_confirmed_orders' => 'رؤية الطلبات المؤكدة فقط',
        'view_orders_readonly'  => 'رؤية الطلبات (قراءة فقط)',
        'confirm_orders'        => 'تأكيد/رفض الطلبات',
        'manage_shipping'       => 'إدارة الشحن',
        'manage_returns'        => 'إدارة المرتجعات',
        'view_products'         => 'رؤية المنتجات',
        'manage_team'           => 'إدارة الفريق',
        'view_stats'            => 'رؤية الإحصائيات',
        'view_suspicious'       => 'رؤية الطلبات المشبوهة',
    ];

    /* =====================================================
       الصلاحيات الافتراضية لكل دور (fallback إذا DB فارغ)
    ===================================================== */
    public const DEFAULT_PERMISSIONS = [
        'owner'     => ['*'],
        'manager'   => ['view_orders','confirm_orders','manage_team','view_stats','manage_shipping','view_products','view_suspicious','manage_returns'],
        'confirmer' => ['view_assigned_orders','confirm_orders'],
        'shipping'  => ['view_confirmed_orders','manage_shipping'],
        'accountant'=> ['view_stats','view_orders_readonly'],
    ];


    public function __construct()
    {
        $this->db = \db();
    }

    /* =====================================================
       جلب كل أعضاء الفريق
    ===================================================== */
    public function getAll(): array
    {
        $stmt = $this->db->query("
            SELECT id, username, email, avatar, role, is_active, last_login_at
            FROM admins
            ORDER BY role ASC, username ASC
        ");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /* =====================================================
       جلب عضو بالـ ID
    ===================================================== */
    public function getById(int $id): ?array
    {
        $stmt = $this->db->prepare("SELECT * FROM admins WHERE id = ? LIMIT 1");
        $stmt->execute([$id]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }

    /* =====================================================
       إضافة عضو جديد
    ===================================================== */
    public function create(array $data): int
    {
        $stmt = $this->db->prepare("
            INSERT INTO admins (username, password, email, role, is_active)
            VALUES (?, ?, ?, ?, 1)
        ");
        $stmt->execute([
            trim($data['username']),
            password_hash(trim($data['password']), PASSWORD_DEFAULT),
            trim($data['email'] ?? ''),
            $data['role'] ?? 'confirmer',
        ]);
        return (int)$this->db->lastInsertId();
    }

    /* =====================================================
       تحديث عضو
    ===================================================== */
    public function update(int $id, array $data): void
    {
        $sets   = ['role = ?', 'email = ?', 'is_active = ?'];
        $params = [$data['role'], trim($data['email'] ?? ''), (int)($data['is_active'] ?? 1)];

        if (!empty($data['password'])) {
            $sets[]   = 'password = ?';
            $params[] = password_hash(trim($data['password']), PASSWORD_DEFAULT);
        }

        $params[] = $id;
        $this->db->prepare("UPDATE admins SET " . implode(', ', $sets) . " WHERE id = ?")
                 ->execute($params);
    }

    /* =====================================================
       حذف عضو (لا يُحذف الـ owner)
    ===================================================== */
    public function delete(int $id): bool
    {
        $member = $this->getById($id);
        if (!$member || $member['role'] === 'owner') return false;

        $this->db->prepare("DELETE FROM admins WHERE id = ?")->execute([$id]);
        $this->db->prepare("DELETE FROM order_assignments WHERE admin_id = ?")->execute([$id]);
        return true;
    }

    /* =====================================================
       تبديل تفعيل/تعطيل عضو
    ===================================================== */
    public function toggleActive(int $id): void
    {
        $this->db->prepare("UPDATE admins SET is_active = NOT is_active WHERE id = ?")
                 ->execute([$id]);
    }

    /* =====================================================
       ROUND-ROBIN — جلب الموظف التالي لاستلام طلب
       فقط أعضاء دور confirmer + is_active
    ===================================================== */
    public function getNextConfirmer(): ?array
    {
        // الموظف الذي لديه أقل عدد طلبات معلقة
        $stmt = $this->db->query("
            SELECT a.id, a.username,
                   COUNT(oa.id) as pending_count
            FROM admins a
            LEFT JOIN order_assignments oa
                ON oa.admin_id = a.id AND oa.action = 'pending'
            WHERE a.role = 'confirmer'
              AND a.is_active = 1
            GROUP BY a.id
            ORDER BY pending_count ASC, a.id ASC
            LIMIT 1
        ");
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }

    /* =====================================================
       تعيين طلب لموظف (Round-Robin)
    ===================================================== */
    public function assignOrder(int $orderId): ?int
    {
        $confirmer = $this->getNextConfirmer();
        if (!$confirmer) return null;

        $this->db->prepare("
            INSERT INTO order_assignments (order_id, admin_id, assigned_at, action)
            VALUES (?, ?, NOW(), 'pending')
            ON DUPLICATE KEY UPDATE admin_id = VALUES(admin_id), assigned_at = NOW(), action = 'pending'
        ")->execute([$orderId, $confirmer['id']]);

        return $confirmer['id'];
    }

    /* =====================================================
       تعيين يدوي لطلب لموظف محدد
    ===================================================== */
    public function assignOrderTo(int $orderId, int $adminId): void
    {
        $this->db->prepare("
            INSERT INTO order_assignments (order_id, admin_id, assigned_at, action)
            VALUES (?, ?, NOW(), 'pending')
            ON DUPLICATE KEY UPDATE admin_id = VALUES(admin_id), assigned_at = NOW(), action = 'pending'
        ")->execute([$orderId, $adminId]);
    }

    /* =====================================================
       تسجيل أداء عضو (عند تأكيد/رفض طلب)
    ===================================================== */
    public function recordAction(int $adminId, string $action): void
    {
        if (!in_array($action, ['confirmed', 'rejected'], true)) return;

        $col = $action === 'confirmed' ? 'confirmed' : 'rejected';

        $this->db->prepare("
            INSERT INTO team_performance (admin_id, date, {$col}, total)
            VALUES (?, CURDATE(), 1, 1)
            ON DUPLICATE KEY UPDATE
                {$col} = {$col} + 1,
                total   = total + 1
        ")->execute([$adminId]);

        // تحديث حالة التعيين
        $this->db->prepare("
            UPDATE order_assignments
            SET action = ?, confirmed_at = NOW()
            WHERE admin_id = ? AND action = 'pending'
            ORDER BY assigned_at DESC
            LIMIT 1
        ")->execute([$action, $adminId]);
    }

    /* =====================================================
       جلب الطلبات المعينة لموظف
    ===================================================== */
    public function getAssignedOrders(int $adminId): array
    {
        $stmt = $this->db->prepare("
            SELECT o.*, oa.assigned_at, oa.action as assignment_action
            FROM orders o
            INNER JOIN order_assignments oa ON oa.order_id = o.id
            WHERE oa.admin_id = ?
            ORDER BY oa.assigned_at DESC
        ");
        $stmt->execute([$adminId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /* =====================================================
       إحصائيات أداء الفريق
    ===================================================== */
    public function getTeamStats(?int $adminId = null, int $days = 30): array
    {
        $where  = $adminId ? "AND tp.admin_id = ?" : '';
        $params = ["DATE_SUB(CURDATE(), INTERVAL {$days} DAY)"];
        if ($adminId) $params[] = $adminId;

        $stmt = $this->db->prepare("
            SELECT
                a.id, a.username, a.role,
                COALESCE(SUM(tp.confirmed), 0) as confirmed,
                COALESCE(SUM(tp.rejected),  0) as rejected,
                COALESCE(SUM(tp.total),     0) as total,
                ROUND(
                    CASE WHEN COALESCE(SUM(tp.total),0) > 0
                    THEN (COALESCE(SUM(tp.confirmed),0) / COALESCE(SUM(tp.total),0)) * 100
                    ELSE 0 END, 1
                ) as confirm_rate
            FROM admins a
            LEFT JOIN team_performance tp
                ON tp.admin_id = a.id AND tp.date >= ?
            WHERE a.role = 'confirmer'
            {$where}
            GROUP BY a.id
            ORDER BY confirmed DESC
        ");
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /* =====================================================
       جلب صلاحيات دور من DB
    ===================================================== */
    public function getPermissionsForRole(string $role): array
    {
        if ($role === 'owner') return ['*'];
        try {
            $stmt = $this->db->prepare(
                "SELECT permission FROM role_permissions WHERE role = ?"
            );
            $stmt->execute([$role]);
            $perms = $stmt->fetchAll(\PDO::FETCH_COLUMN);
            return $perms ?: (self::DEFAULT_PERMISSIONS[$role] ?? []);
        } catch (\Throwable $e) {
            return self::DEFAULT_PERMISSIONS[$role] ?? [];
        }
    }

    /* =====================================================
       جلب صلاحيات كل الأدوار دفعة واحدة
    ===================================================== */
    public function getAllRolePermissions(): array
    {
        $result = [];
        foreach (array_keys(self::ROLES) as $role) {
            $result[$role] = $this->getPermissionsForRole($role);
        }
        return $result;
    }

    /* =====================================================
       حفظ صلاحيات دور (يستبدل القديمة)
    ===================================================== */
    public function saveRolePermissions(string $role, array $permissions): void
    {
        if ($role === 'owner') return; // owner له كل الصلاحيات دائماً

        $this->db->prepare(
            "DELETE FROM role_permissions WHERE role = ?"
        )->execute([$role]);

        $stmt = $this->db->prepare(
            "INSERT IGNORE INTO role_permissions (role, permission) VALUES (?, ?)"
        );
        foreach ($permissions as $perm) {
            if (array_key_exists($perm, self::ALL_PERMISSIONS)) {
                $stmt->execute([$role, $perm]);
            }
        }
    }

    /* =====================================================
       فحص صلاحية عضو — يقرأ من DB
    ===================================================== */
    public static function can(string $role, string $permission): bool
    {
        if ($role === 'owner') return true;

        // نقرأ من الـ session cache أولاً لتفادي DB في كل request
        if (isset($_SESSION['role_permissions_cache'][$role])) {
            $perms = $_SESSION['role_permissions_cache'][$role];
        } else {
            try {
                $db   = \db();
                $stmt = $db->prepare("SELECT permission FROM role_permissions WHERE role = ?");
                $stmt->execute([$role]);
                $perms = $stmt->fetchAll(\PDO::FETCH_COLUMN);
                if (empty($perms)) {
                    $perms = self::DEFAULT_PERMISSIONS[$role] ?? [];
                }
            } catch (\Throwable $e) {
                $perms = self::DEFAULT_PERMISSIONS[$role] ?? [];
            }
            $_SESSION['role_permissions_cache'][$role] = $perms;
        }

        return in_array('*', $perms) || in_array($permission, $perms);
    }

    /* =====================================================
       مسح الـ cache عند تغيير الصلاحيات
    ===================================================== */
    public static function clearPermissionCache(): void
    {
        unset($_SESSION['role_permissions_cache']);
    }
}