<?php
require_once 'db.php';
session_start();

header('Content-Type: application/json');
header('X-Content-Type-Options: nosniff');

class SecureAuth {
    private $db;
    private $maxAttempts = 3;
    private $lockoutTime = 300;
    
    public function __construct() {
        $this->db = getDB1Connection();
    }
    
    public function generateSecurePassword() {
        $length = 12;
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= $chars[random_int(0, strlen($chars) - 1)];
        }
        return $password;
    }
    
    public function createPassword($plainPassword, $userId) {
        if (!$this->isCEO($userId)) {
            return ['success' => false, 'message' => 'Unauthorized'];
        }
        
        if (strlen($plainPassword) !== 12) {
            return ['success' => false, 'message' => 'Password must be exactly 12 characters'];
        }
        
        $salt = bin2hex(random_bytes(32));
        $hash = hash('sha256', $plainPassword . $salt);
        
        $stmt = $this->db->prepare("INSERT INTO secure_passwords (password_hash, salt, created_by) VALUES (?, ?, ?)");
        $result = $stmt->execute([$hash, $salt, $userId]);
        
        if ($result) {
            return ['success' => true, 'message' => 'Password created successfully'];
        } else {
            return ['success' => false, 'message' => 'Failed to create password'];
        }
    }
    
    public function generateAndCreatePasswords($userId) {
        if (!$this->isCEO($userId)) {
            return ['success' => false, 'message' => 'Unauthorized'];
        }
        
        $this->db->exec("DELETE FROM secure_passwords");
        
        $passwords = [];
        for ($i = 0; i < 20; $i++) {
            $password = $this->generateSecurePassword();
            $result = $this->createPassword($password, $userId);
            if ($result['success']) {
                $passwords[] = $password;
            }
        }
        
        return ['success' => true, 'passwords' => $passwords];
    }
    
    public function verifyPassword($password, $tabName, $userId) {
        if (!in_array($tabName, ['identity', 'users', 'email'])) {
            return ['success' => false, 'message' => 'Invalid tab'];
        }
        
        $ipAddress = $_SERVER['REMOTE_ADDR'];
        
        if ($this->isLockedOut($userId, $ipAddress)) {
            return ['success' => false, 'message' => 'Too many failed attempts', 'lockout' => true];
        }
        
        $stmt = $this->db->prepare("SELECT password_hash, salt, id FROM secure_passwords WHERE is_active = 1");
        $stmt->execute();
        $validPasswords = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        $isValid = false;
        $passwordId = null;
        
        foreach ($validPasswords as $row) {
            $hash = hash('sha256', $password . $row['salt']);
            if (hash_equals($row['password_hash'], $hash)) {
                $isValid = true;
                $passwordId = $row['id'];
                break;
            }
        }
        
        $this->logAttempt($userId, $ipAddress, $tabName, $isValid);
        
        if ($isValid) {
            $this->updatePasswordUsage($passwordId);
            $sessionToken = $this->createUnlockSession($userId, $tabName);
            return ['success' => true, 'sessionToken' => $sessionToken];
        } else {
            $remaining = $this->getRemainingAttempts($userId, $ipAddress);
            return ['success' => false, 'message' => "Invalid password. $remaining attempts remaining", 'remainingAttempts' => $remaining];
        }
    }
    
    public function verifySession($sessionToken, $tabName, $userId) {
        $stmt = $this->db->prepare("SELECT id FROM unlock_sessions WHERE user_id = ? AND session_token = ? AND tab_name = ? AND expires_at > NOW()");
        $stmt->execute([$userId, $sessionToken, $tabName]);
        return $stmt->fetch() !== false;
    }
    
    public function getPasswordList($userId) {
        if (!$this->isCEO($userId)) {
            return ['success' => false, 'message' => 'Unauthorized'];
        }
        
        $stmt = $this->db->prepare("SELECT id, is_active, created_at, last_used, usage_count FROM secure_passwords ORDER BY id ASC");
        $stmt->execute();
        $passwords = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        return ['success' => true, 'passwords' => $passwords];
    }
    
    public function togglePassword($passwordId, $userId) {
        if (!$this->isCEO($userId)) {
            return ['success' => false, 'message' => 'Unauthorized'];
        }
        
        $stmt = $this->db->prepare("UPDATE secure_passwords SET is_active = NOT is_active WHERE id = ?");
        $result = $stmt->execute([$passwordId]);
        
        return ['success' => $result, 'message' => $result ? 'Password status updated' : 'Failed to update password'];
    }
    
    public function deletePassword($passwordId, $userId) {
        if (!$this->isCEO($userId)) {
            return ['success' => false, 'message' => 'Unauthorized'];
        }
        
        $stmt = $this->db->prepare("DELETE FROM secure_passwords WHERE id = ?");
        $result = $stmt->execute([$passwordId]);
        
        return ['success' => $result, 'message' => $result ? 'Password deleted' : 'Failed to delete password'];
    }
    
    private function isCEO($userId) {
        $stmt = $this->db->prepare("SELECT roleinimators FROM utilisateurs WHERE id = ?");
        $stmt->execute([$userId]);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
        return $user && $user['roleinimators'] === 'CEO';
    }
    
    private function isLockedOut($userId, $ipAddress) {
        $stmt = $this->db->prepare("SELECT COUNT(*) as failed_attempts FROM security_attempts WHERE (user_id = ? OR ip_address = ?) AND success = FALSE AND attempt_time > DATE_SUB(NOW(), INTERVAL ? SECOND)");
        $stmt->execute([$userId, $ipAddress, $this->lockoutTime]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return $result['failed_attempts'] >= $this->maxAttempts;
    }
    
    private function getRemainingAttempts($userId, $ipAddress) {
        $stmt = $this->db->prepare("SELECT COUNT(*) as failed_attempts FROM security_attempts WHERE (user_id = ? OR ip_address = ?) AND success = FALSE AND attempt_time > DATE_SUB(NOW(), INTERVAL ? SECOND)");
        $stmt->execute([$userId, $ipAddress, $this->lockoutTime]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return max(0, $this->maxAttempts - $result['failed_attempts']);
    }
    
    private function logAttempt($userId, $ipAddress, $tabName, $success) {
        $stmt = $this->db->prepare("INSERT INTO security_attempts (user_id, ip_address, tab_name, success, user_agent) VALUES (?, ?, ?, ?, ?)");
        $stmt->execute([$userId, $ipAddress, $tabName, $success ? 1 : 0, $_SERVER['HTTP_USER_AGENT']]);
    }
    
    private function updatePasswordUsage($passwordId) {
        $stmt = $this->db->prepare("UPDATE secure_passwords SET usage_count = usage_count + 1, last_used = NOW() WHERE id = ?");
        $stmt->execute([$passwordId]);
    }
    
    private function createUnlockSession($userId, $tabName) {
        $sessionToken = bin2hex(random_bytes(64));
        $expiresAt = date('Y-m-d H:i:s', time() + 3600);
        
        $stmt = $this->db->prepare("INSERT INTO unlock_sessions (user_id, session_token, tab_name, expires_at) VALUES (?, ?, ?, ?)");
        $stmt->execute([$userId, $sessionToken, $tabName, $expiresAt]);
        
        return $sessionToken;
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $auth = new SecureAuth();
    $input = json_decode(file_get_contents('php://input'), true);
    
    if (!isset($_SESSION['user_id'])) {
        echo json_encode(['success' => false, 'message' => 'Not authenticated']);
        exit;
    }
    
    $userId = $_SESSION['user_id'];
    $action = $input['action'] ?? '';
    
    switch ($action) {
        case 'verify_password':
            $password = $input['password'] ?? '';
            $tabName = $input['tabName'] ?? '';
            echo json_encode($auth->verifyPassword($password, $tabName, $userId));
            break;
            
        case 'verify_session':
            $sessionToken = $input['sessionToken'] ?? '';
            $tabName = $input['tabName'] ?? '';
            $isValid = $auth->verifySession($sessionToken, $tabName, $userId);
            echo json_encode(['success' => $isValid]);
            break;
            
        case 'create_password':
            $password = $input['password'] ?? '';
            echo json_encode($auth->createPassword($password, $userId));
            break;
            
        case 'generate_passwords':
            echo json_encode($auth->generateAndCreatePasswords($userId));
            break;
            
        case 'get_passwords':
            echo json_encode($auth->getPasswordList($userId));
            break;
            
        case 'toggle_password':
            $passwordId = $input['passwordId'] ?? 0;
            echo json_encode($auth->togglePassword($passwordId, $userId));
            break;
            
        case 'delete_password':
            $passwordId = $input['passwordId'] ?? 0;
            echo json_encode($auth->deletePassword($passwordId, $userId));
            break;
            
        default:
            echo json_encode(['success' => false, 'message' => 'Invalid action']);
    }
} else {
    echo json_encode(['success' => false, 'message' => 'Method not allowed']);
}
?>