<?php

namespace App\Core;

use PDO;

/**
 * نظام مصادقة الأطباء - تسجيل دخول منفصل للوحة تحكم الطبيب
 * يدعم 2FA (TOTP)
 */
class DoctorAuth
{
    private PDO $db;

    public function __construct(PDO $db)
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        $this->db = $db;
    }

    /**
     * محاولة تسجيل الدخول
     * @return bool|string true على النجاح، '2fa_required' عند الحاجة للتحقق الثنائي، false عند الفشل
     */
    public function attempt(string $username, string $password)
    {
        try {
            $this->db->query('SELECT id FROM doctor_accounts LIMIT 1');
        } catch (\Throwable $e) {
            return false;
        }

        $account = null;
        try {
            $stmt = $this->db->prepare(
                'SELECT da.*, d.full_name, d.specialty, d.clinic_name, t.name AS tenant_name, t.slug AS tenant_slug
                 FROM doctor_accounts da
                 JOIN doctors d ON d.id = da.doctor_id AND d.tenant_id = da.tenant_id
                 JOIN tenants t ON t.id = da.tenant_id
                 WHERE da.username = ? AND da.is_active = 1 AND t.status IN ("active","trial")'
            );
            $stmt->execute([$username]);
            $account = $stmt->fetch();
        } catch (\Throwable $e) {
            try {
                $stmt = $this->db->prepare(
                    'SELECT da.*, d.full_name, d.specialty, d.clinic_name, t.name AS tenant_name, t.slug AS tenant_slug
                     FROM doctor_accounts da
                     JOIN doctors d ON d.id = da.doctor_id
                     JOIN tenants t ON t.id = da.tenant_id
                     WHERE da.username = ? AND da.is_active = 1 AND t.status IN ("active","trial")'
                );
                $stmt->execute([$username]);
                $account = $stmt->fetch();
            } catch (\Throwable $e2) {}
        }

        if (!$account || !password_verify($password, $account['password_hash'])) {
            return false;
        }

        $twoFactorEnabled = false;
        try {
            $this->db->query('SELECT two_factor_enabled, two_factor_secret FROM doctor_accounts LIMIT 1');
            $enabled = !empty($account['two_factor_enabled']);
            $hasSecret = !empty(trim((string)($account['two_factor_secret'] ?? '')));
            $twoFactorEnabled = $enabled && $hasSecret;
        } catch (\Throwable $e) {}

        if ($twoFactorEnabled) {
            $_SESSION['doctor_2fa_pending'] = $account;
            return '2fa_required';
        }

        $this->completeLogin($account);
        return true;
    }

    public function verify2FA(string $code): bool
    {
        $account = $_SESSION['doctor_2fa_pending'] ?? null;
        if (!$account) return false;

        try {
            $this->db->query('SELECT two_factor_secret FROM doctor_accounts LIMIT 1');
        } catch (\Throwable $e) {
            unset($_SESSION['doctor_2fa_pending']);
            return false;
        }

        $secret = trim((string)($account['two_factor_secret'] ?? ''));
        if ($secret === '' || !\App\Core\TOTP::verify($secret, $code)) {
            return false;
        }

        unset($_SESSION['doctor_2fa_pending']);
        $this->completeLogin($account);
        return true;
    }

    private function completeLogin(array $account): void
    {
        $_SESSION['doctor_account_id'] = (int)$account['id'];
        $_SESSION['doctor_id'] = (int)$account['doctor_id'];
        $_SESSION['doctor_tenant_id'] = (int)$account['tenant_id'];
        $_SESSION['doctor_name'] = $account['full_name'];
        $_SESSION['doctor_specialty'] = $account['specialty'] ?? '';
        $_SESSION['doctor_clinic'] = $account['clinic_name'] ?? '';
        $_SESSION['doctor_tenant_name'] = $account['tenant_name'] ?? '';
        $_SESSION['doctor_tenant_slug'] = $account['tenant_slug'] ?? '';
        $_SESSION['doctor_last_activity'] = time();

        $this->db->prepare('UPDATE doctor_accounts SET last_login_at = NOW() WHERE id = ?')
            ->execute([$account['id']]);
    }

    public function hasPending2FA(): bool
    {
        return !empty($_SESSION['doctor_2fa_pending']);
    }

    /**
     * إلغاء التحقق الثنائي والدخول مباشرة - للمستخدمين الذين لم يفعّلوا 2FA فعلياً
     */
    public function disable2FAAndCompleteLogin(): bool
    {
        $account = $_SESSION['doctor_2fa_pending'] ?? null;
        if (!$account) return false;

        try {
            $this->db->prepare('UPDATE doctor_accounts SET two_factor_enabled = 0, two_factor_secret = NULL, two_factor_verified_at = NULL WHERE id = ?')
                ->execute([$account['id']]);
        } catch (\Throwable $e) {
            return false;
        }

        unset($_SESSION['doctor_2fa_pending']);
        $this->completeLogin($account);
        return true;
    }

    public function check(): bool
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        if (!isset($_SESSION['doctor_account_id'])) {
            return false;
        }
        $timeout = 30 * 60; // 30 دقيقة
        if (isset($_SESSION['doctor_last_activity']) && (time() - (int)$_SESSION['doctor_last_activity']) > $timeout) {
            $this->logout();
            return false;
        }
        $_SESSION['doctor_last_activity'] = time();
        return true;
    }

    public function logout(): void
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        $keys = ['doctor_account_id', 'doctor_id', 'doctor_tenant_id', 'doctor_name', 'doctor_specialty', 'doctor_clinic', 'doctor_tenant_name', 'doctor_tenant_slug', 'doctor_last_activity'];
        foreach ($keys as $k) {
            unset($_SESSION[$k]);
        }
    }

    public function doctorId(): ?int
    {
        return $this->check() ? (int)($_SESSION['doctor_id'] ?? 0) : null;
    }

    public function tenantId(): ?int
    {
        return $this->check() ? (int)($_SESSION['doctor_tenant_id'] ?? 0) : null;
    }

    public function accountId(): ?int
    {
        return $this->check() ? (int)($_SESSION['doctor_account_id'] ?? 0) : null;
    }
}
