<?php
/**
 * Kontroler urządzeń
 */

require_once __DIR__ . '/BaseController.php';

class DeviceController extends BaseController
{
    private Device $deviceModel;
    private User $userModel;
    private AuditLog $auditLog;

    public function __construct()
    {
        parent::__construct();
        $this->deviceModel = new Device();
        $this->userModel = new User();
        $this->auditLog = new AuditLog();
    }

    /**
     * Lista urządzeń
     */
    public function index(): void
    {
        $search = get('search');
        $page = max(1, (int)get('page', 1));
        $filterUserId = get('user_id'); // może być 'all' lub ID
        
        // Określ filtr użytkownika w zależności od roli
        $userId = null;
        
        if ($this->auth->isAdmin()) {
            if ($filterUserId === 'all') {
                // Wszystkie urządzenia
                $userId = null;
            } elseif ($filterUserId && is_numeric($filterUserId)) {
                // Filtrowanie po konkretnym użytkowniku
                $userId = (int)$filterUserId;
            } else {
                // Domyślnie: tylko własne
                $userId = $this->currentUser['id'];
            }
            
            // Pobierz urządzenia
            $total = $this->deviceModel->count($search, $userId);
            $pagination = paginate($total, ITEMS_PER_PAGE, $page);
            $devices = $this->deviceModel->getAll(ITEMS_PER_PAGE, $pagination['offset'], $search, $userId);
            
            // Lista użytkowników
            $users = $this->userModel->getAll(1000);
            
        } elseif ($this->auth->isReseller()) {
            $visibleUserIds = $this->userModel->getVisibleUserIds($this->currentUser);
            
            if ($filterUserId === 'all') {
                // Wszystkie widoczne
                $total = $this->deviceModel->countByUserIds($visibleUserIds, $search);
                $pagination = paginate($total, ITEMS_PER_PAGE, $page);
                $devices = $this->deviceModel->getByUserIds($visibleUserIds, ITEMS_PER_PAGE, $pagination['offset'], $search);
            } elseif ($filterUserId && is_numeric($filterUserId) && in_array((int)$filterUserId, $visibleUserIds)) {
                // Filtrowanie po konkretnym użytkowniku
                $userId = (int)$filterUserId;
                $total = $this->deviceModel->count($search, $userId);
                $pagination = paginate($total, ITEMS_PER_PAGE, $page);
                $devices = $this->deviceModel->getAll(ITEMS_PER_PAGE, $pagination['offset'], $search, $userId);
            } else {
                // Domyślnie: tylko własne
                $userId = $this->currentUser['id'];
                $total = $this->deviceModel->count($search, $userId);
                $pagination = paginate($total, ITEMS_PER_PAGE, $page);
                $devices = $this->deviceModel->getAll(ITEMS_PER_PAGE, $pagination['offset'], $search, $userId);
            }
            
            // Lista użytkowników
            $users = $this->userModel->getByParentId($this->currentUser['id'], 1000);
            
        } else {
            // Zwykły użytkownik widzi tylko swoje
            $userId = $this->currentUser['id'];
            $total = $this->deviceModel->count($search, $userId);
            $pagination = paginate($total, ITEMS_PER_PAGE, $page);
            $devices = $this->deviceModel->getAll(ITEMS_PER_PAGE, $pagination['offset'], $search, $userId);
            $users = [];
        }

        // Oblicz limity do wyświetlenia
        if ($this->auth->isReseller()) {
            $resellerUsage = $this->userModel->getResellerUsage($this->currentUser['id']);
            $deviceLimit = $resellerUsage['devices']['max'];
            $currentDevicesCount = $resellerUsage['devices']['used'];
        } else {
            $deviceLimit = $this->currentUser['device_limit'];
            $currentDevicesCount = $this->deviceModel->countByUserId($this->currentUser['id']);
        }

        $this->render('devices/list.tpl', [
            'pageTitle' => 'Urządzenia',
            'devices' => $devices,
            'pagination' => $pagination,
            'search' => $search,
            'filterUserId' => $filterUserId,
            'users' => $users,
            'deviceLimit' => $deviceLimit,
            'currentDevicesCount' => $currentDevicesCount
        ]);
    }

    /**
     * Dodaj urządzenie
     */
    public function add(): void
    {
        // Dla admina - można wybrać użytkownika, dla zwykłego - własny
        $userId = $this->auth->isAdmin() ? (int)get('user_id', $this->currentUser['id']) : $this->currentUser['id'];

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!$this->verifyCsrf()) {
                return;
            }

            $targetUserId = $this->auth->isAdmin() ? (int)post('user_id', $this->currentUser['id']) : $this->currentUser['id'];

            $data = [
                'user_id' => $targetUserId,
                'mac' => post('mac'),
                'code' => post('code'),
                'name' => post('name'),
                'logged_user_id' => $this->currentUser['id']
            ];

            $result = $this->deviceModel->create($data);

            // Audit log
            if ($result['success'] && isset($result['id'])) {
                $this->auditLog->log(
                    AuditLog::ENTITY_DEVICE,
                    $result['id'],
                    AuditLog::ACTION_CREATE,
                    null,
                    ['mac' => $data['mac'], 'name' => $data['name']]
                );
                
                // Dodaj notatkę jeśli podano
                $initialNote = trim(post('initial_note', ''));
                if ($initialNote) {
                    $notesModel = new EntityNotes();
                    $notesModel->add('device', $result['id'], $this->currentUser['id'], [
                        'title' => 'Uwagi przy tworzeniu',
                        'content' => $initialNote,
                        'color' => 'green'
                    ]);
                }
            }

            if (isAjax()) {
                $this->json($result);
            } else {
                if ($result['success']) {
                    $this->redirect('devices', 'success', 'Urządzenie zostało dodane.');
                } else {
                    $users = $this->auth->isAdmin() ? $this->userModel->getAll(100) : [];
                    $this->render('devices/form.tpl', [
                        'pageTitle' => 'Dodaj urządzenie',
                        'error' => $result['error'],
                        'data' => $data,
                        'isEdit' => false,
                        'users' => $users
                    ]);
                }
            }
            return;
        }

        $users = $this->auth->isAdmin() ? $this->userModel->getAll(100) : [];

        $this->render('devices/form.tpl', [
            'pageTitle' => 'Dodaj urządzenie',
            'isEdit' => false,
            'data' => ['user_id' => $userId],
            'users' => $users
        ]);
    }

    /**
     * Edytuj urządzenie
     */
    public function edit(): void
    {
        $id = (int)get('id');
        $device = $this->deviceModel->getById($id);

        if (!$device) {
            $this->redirect('devices', 'danger', 'Urządzenie nie istnieje.');
            return;
        }

        // Sprawdź uprawnienia
        if (!$this->canAccess($device['owner_id'])) {
            $this->redirect('devices', 'danger', 'Brak dostępu do tego urządzenia.');
            return;
        }

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!$this->verifyCsrf()) {
                return;
            }

            $data = [
                'mac' => post('mac'),
                'code' => post('code'),
                'name' => post('name')
            ];

            $result = $this->deviceModel->update($id, $data, $this->currentUser['id']);

            // Audit log
            if ($result['success']) {
                $this->auditLog->log(
                    AuditLog::ENTITY_DEVICE,
                    $id,
                    AuditLog::ACTION_UPDATE,
                    $device,
                    array_merge($device, $data)
                );
            }

            if (isAjax()) {
                $this->json($result);
            } else {
                if ($result['success']) {
                    $this->redirect('devices', 'success', 'Urządzenie zostało zaktualizowane.');
                } else {
                    $users = $this->auth->isAdmin() ? $this->userModel->getAll(100) : [];
                    $this->render('devices/form.tpl', [
                        'pageTitle' => 'Edytuj urządzenie',
                        'error' => $result['error'],
                        'data' => array_merge($device, $data),
                        'isEdit' => true,
                        'users' => $users
                    ]);
                }
            }
            return;
        }

        $users = $this->auth->isAdmin() ? $this->userModel->getAll(100) : [];

        $this->render('devices/form.tpl', [
            'pageTitle' => 'Edytuj urządzenie',
            'isEdit' => true,
            'data' => $device,
            'users' => $users
        ]);
    }

    /**
     * Usuń urządzenie
     */
    public function delete(): void
    {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            $this->redirect('devices');
            return;
        }

        if (!$this->verifyCsrf()) {
            return;
        }

        $id = (int)post('id');
        $device = $this->deviceModel->getById($id);

        if (!$device) {
            if (isAjax()) {
                $this->json(['success' => false, 'error' => 'Urządzenie nie istnieje.']);
            } else {
                $this->redirect('devices', 'danger', 'Urządzenie nie istnieje.');
            }
            return;
        }

        // Sprawdź uprawnienia
        if (!$this->canAccess($device['owner_id'])) {
            if (isAjax()) {
                $this->json(['success' => false, 'error' => 'Brak dostępu.']);
            } else {
                $this->redirect('devices', 'danger', 'Brak dostępu.');
            }
            return;
        }

        $result = $this->deviceModel->delete($id, $this->currentUser['id']);

        // Audit log
        if ($result['success']) {
            $this->auditLog->log(
                AuditLog::ENTITY_DEVICE,
                $id,
                AuditLog::ACTION_DELETE,
                ['mac' => $device['mac'], 'name' => $device['name']],
                null
            );
        }

        if (isAjax()) {
            $this->json($result);
        } else {
            if ($result['success']) {
                $this->redirect('devices', 'success', 'Urządzenie zostało usunięte.');
            } else {
                $this->redirect('devices', 'danger', $result['error']);
            }
        }
    }

    /**
     * Przełącz blokadę urządzenia (tylko admin)
     */
    public function toggleBlock(): void
    {
        if (!$this->auth->isAdmin()) {
            if (isAjax()) {
                $this->json(['success' => false, 'error' => 'Brak uprawnień.']);
            } else {
                $this->redirect('devices', 'danger', 'Brak uprawnień.');
            }
            return;
        }

        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            $this->redirect('devices');
            return;
        }

        if (!$this->verifyCsrf()) {
            return;
        }

        $id = (int)post('id');
        $device = $this->deviceModel->getById($id);
        $result = $this->deviceModel->toggleBlock($id, $this->currentUser['id']);

        // Audit log
        if ($result['success'] && $device) {
            $this->auditLog->log(
                AuditLog::ENTITY_DEVICE,
                $id,
                $result['is_blocked'] ? AuditLog::ACTION_BLOCK : AuditLog::ACTION_UNBLOCK,
                ['is_blocked' => !$result['is_blocked']],
                ['is_blocked' => $result['is_blocked'], 'mac' => $device['mac']]
            );
        }

        if (isAjax()) {
            $this->json($result);
        } else {
            if ($result['success']) {
                $status = $result['is_blocked'] ? 'zablokowane' : 'odblokowane';
                $this->redirect('devices', 'success', "Urządzenie zostało {$status}.");
            } else {
                $this->redirect('devices', 'danger', $result['error']);
            }
        }
    }

    /**
     * Sklonuj urządzenie
     */
    public function clone(): void
    {
        $sourceId = (int)get('id');
        $sourceDevice = $this->deviceModel->getById($sourceId);

        if (!$sourceDevice) {
            $this->redirect('devices', 'danger', 'Urządzenie źródłowe nie istnieje.');
            return;
        }

        // Sprawdź uprawnienia do urządzenia źródłowego
        if (!$this->canAccess($sourceDevice['owner_id'])) {
            $this->redirect('devices', 'danger', 'Brak dostępu do tego urządzenia.');
            return;
        }

        // Pobierz playlisty urządzenia źródłowego
        $playlistModel = new Playlist();
        $sourcePlaylists = $playlistModel->getByDeviceId($sourceId);

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!$this->verifyCsrf()) {
                return;
            }

            // Określ użytkownika docelowego
            $targetUserId = $this->auth->isAdmin() 
                ? (int)post('user_id', $this->currentUser['id']) 
                : $this->currentUser['id'];

            // Sprawdź limit urządzeń
            $targetUser = $this->userModel->getById($targetUserId);
            if (!$targetUser) {
                $this->renderCloneForm($sourceDevice, $sourcePlaylists, 'Użytkownik docelowy nie istnieje.');
                return;
            }

            $currentCount = $this->deviceModel->countByUserId($targetUserId);
            if ($currentCount >= $targetUser['device_limit']) {
                $this->renderCloneForm($sourceDevice, $sourcePlaylists, 
                    "Użytkownik osiągnął limit urządzeń ({$targetUser['device_limit']}).");
                return;
            }

            // Walidacja danych nowego urządzenia
            $mac = post('mac');
            $code = post('code');
            $name = post('name', $sourceDevice['name'] . ' (kopia)');

            $deviceData = [
                'user_id' => $targetUserId,
                'mac' => $mac,
                'code' => $code,
                'name' => $name,
                'logged_user_id' => $this->currentUser['id']
            ];

            // Utwórz nowe urządzenie
            $result = $this->deviceModel->create($deviceData);

            if (!$result['success']) {
                $this->renderCloneForm($sourceDevice, $sourcePlaylists, $result['error'], [
                    'mac' => $mac,
                    'code' => $code,
                    'name' => $name,
                    'user_id' => $targetUserId
                ]);
                return;
            }

            $newDeviceId = $result['id'];
            $clonedCount = 0;

            // Sklonuj playlisty
            foreach ($sourcePlaylists as $playlist) {
                $config = json_decode($playlist['config_json'], true);
                
                $playlistData = [
                    'device_id' => $newDeviceId,
                    'type' => $playlist['type'],
                    'name' => $playlist['name'],
                    'sort_order' => $playlist['sort_order'],
                    'is_active' => $playlist['is_active'],
                    'update_date' => time()
                ];

                // Dodaj pola konfiguracji w zależności od typu
                // Uwaga: Stalker ma pole 'device_id' w config - trzeba je przemapować
                if ($playlist['type'] === 'stalker' && isset($config['device_id'])) {
                    $playlistData['stalker_device_id'] = $config['device_id'];
                    unset($config['device_id']);
                }
                
                $playlistData = array_merge($playlistData, $config);

                $playlistResult = $playlistModel->create($playlistData, $this->currentUser['id']);
                if ($playlistResult['success']) {
                    $clonedCount++;
                }
            }

            // Loguj klonowanie
            $this->logger->log(
                'device_cloned',
                "Sklonowano urządzenie {$sourceDevice['mac']} -> {$mac} ({$clonedCount} playlist)",
                $this->currentUser['id']
            );

            // Audit log
            $this->auditLog->log(
                AuditLog::ENTITY_DEVICE,
                $newDeviceId,
                AuditLog::ACTION_CLONE,
                ['source_id' => $sourceId, 'source_mac' => $sourceDevice['mac']],
                ['mac' => $mac, 'name' => $name, 'playlists_cloned' => $clonedCount]
            );

            $this->redirect('devices', 'success', 
                "Urządzenie zostało sklonowane. Skopiowano {$clonedCount} playlist.");
            return;
        }

        $this->renderCloneForm($sourceDevice, $sourcePlaylists);
    }

    /**
     * Renderuj formularz klonowania
     */
    private function renderCloneForm(array $sourceDevice, array $sourcePlaylists, ?string $error = null, array $formData = []): void
    {
        $users = $this->auth->isAdmin() ? $this->userModel->getAll(100) : [];

        $this->render('devices/clone.tpl', [
            'pageTitle' => 'Sklonuj urządzenie',
            'sourceDevice' => $sourceDevice,
            'sourcePlaylists' => $sourcePlaylists,
            'users' => $users,
            'error' => $error,
            'data' => $formData
        ]);
    }
}
