<?php

namespace App\Controllers\Api;

use App\Controllers\BaseController;
use App\Models\UserModel;
use App\Models\AdminLicenseCacheModel;
use App\Models\RegisteredSystemModel;
use App\Models\LicenseKeyModel;
use App\Models\AdminSettingsModel;
use App\Libraries\SignatureService;
use App\Libraries\SystemReportService;
use CodeIgniter\API\ResponseTrait;

class DesktopAuth extends BaseController
{
    use ResponseTrait;

    protected UserModel $userModel;
    protected AdminLicenseCacheModel $licenseCacheModel;
    protected RegisteredSystemModel $systemModel;
    protected LicenseKeyModel $licenseModel;
    protected SignatureService $signatureService;
    protected SystemReportService $reportService;

    public function __construct()
    {
        $this->userModel = new UserModel();
        $this->licenseCacheModel = new AdminLicenseCacheModel();
        $this->systemModel = new RegisteredSystemModel();
        $this->licenseModel = new LicenseKeyModel();
        $this->signatureService = new SignatureService();
        $this->reportService = new SystemReportService();
    }

    private function getAdminLicense()
    {
        $licenseCode = env('admin.licenseCode');
        
        if (empty($licenseCode)) {
            $settingsModel = new AdminSettingsModel();
            $settings = $settingsModel->first();
            if ($settings) {
                $licenseCode = $settings['license_key'] ?? null;
            }
        }
        
        if (empty($licenseCode)) {
            return null;
        }
        
        return $this->licenseModel->where('license_code', $licenseCode)->first();
    }

    private function getEncryptionKey()
    {
        $key = env('encryption.key') ?: env('CI_ENCRYPTION_KEY');
        if (empty($key)) {
            $key = config('Encryption')->key ?? bin2hex(random_bytes(16));
        }
        return $key;
    }

    private function generateSessionToken($macAddress, $licenseId)
    {
        $data = [
            'mac_hash' => RegisteredSystemModel::hashMac($macAddress),
            'license_id' => $licenseId,
            'timestamp' => time(),
            'expires' => time() + 3600,
        ];
        $payload = base64_encode(json_encode($data));
        $signature = hash_hmac('sha256', $payload, $this->getEncryptionKey());
        return $payload . '.' . $signature;
    }

    private function validateSessionToken($token, $macAddress)
    {
        $parts = explode('.', $token);
        if (count($parts) !== 2) {
            return null;
        }
        
        list($payload, $signature) = $parts;
        $expectedSignature = hash_hmac('sha256', $payload, $this->getEncryptionKey());
        
        if (!hash_equals($expectedSignature, $signature)) {
            return null;
        }
        
        $data = json_decode(base64_decode($payload), true);
        if (!$data) {
            return null;
        }
        
        if ($data['expires'] < time()) {
            return null;
        }
        
        $macHash = RegisteredSystemModel::hashMac($macAddress);
        if ($data['mac_hash'] !== $macHash) {
            return null;
        }
        
        return $data;
    }

    private function errorResponse($message)
    {
        return $this->respond([
            'licence_valid' => false,
            'msg' => $message,
        ]);
    }

    public function authenticate()
    {
        $deployment = config('Deployment');
        
        $macAddress = $this->request->getVar('mac_address') ?? $this->request->getVar('mac_id');
        $ipAddress = $this->request->getVar('ip_address') ?? $this->request->getIPAddress();
        $hostname = $this->request->getVar('hostname');

        if (empty($macAddress)) {
            return $this->errorResponse('MAC address is required');
        }

        $license = $this->getAdminLicense();
        
        if (!$license) {
            return $this->errorResponse('License not configured. Please contact administrator.');
        }
        
        $licenseId = $license['id'];
        $licenseCode = $license['license_code'];
        $licenseData = null;
        $signedMaxSeats = null;

        if ($deployment->isAdmin()) {
            $cache = $this->licenseCacheModel->getByLicenseCode($licenseCode);
            
            if (!$cache) {
                return $this->errorResponse('License not synced. Please contact administrator to sync license.');
            }

            $licenseData = json_decode($cache['license_data'], true);
            
            if (!$this->signatureService->verifySignature($licenseData, $cache['signature'])) {
                return $this->errorResponse('License data integrity check failed. Please contact administrator.');
            }
            
            $signedMaxSeats = (int) $licenseData['max_seats'];
        } else {
            $licenseData = [
                'license_code' => $license['license_code'],
                'organization_name' => $license['organization_name'],
                'max_seats' => (int) $license['max_seats'],
                'valid_until' => $license['valid_until'],
                'status' => $license['status'],
                'enable_login_screen' => (bool) $license['enable_login_screen'],
                'enable_camera_detection' => (bool) $license['enable_camera_detection'],
                'enable_person_detection' => (bool) $license['enable_person_detection'],
                'lms_probe_origin' => $license['lms_probe_origin'] ?? '',
                'screenshot_needed' => (bool) ($license['screenshot_needed'] ?? false),
                'sap_web_url' => $license['sap_web_url'] ?? '',
            ];
            $signedMaxSeats = (int) $license['max_seats'];
        }

        if ($licenseData['status'] === 'expired') {
            return $this->errorResponse('License has expired. Please contact administrator to renew.');
        }
        
        if ($licenseData['status'] === 'suspended') {
            return $this->errorResponse('License has been suspended. Please contact administrator.');
        }
        
        if ($licenseData['status'] === 'inactive' || $licenseData['status'] === 'disabled') {
            return $this->errorResponse('License is inactive. Please contact administrator.');
        }
        
        if ($licenseData['status'] !== 'active') {
            return $this->errorResponse('License is not valid. Status: ' . $licenseData['status']);
        }

        if (!empty($licenseData['valid_until']) && strtotime($licenseData['valid_until']) < time()) {
            return $this->errorResponse('License has expired on ' . date('Y-m-d', strtotime($licenseData['valid_until'])) . '. Please contact administrator to renew.');
        }

        $macHash = RegisteredSystemModel::hashMac($macAddress);
        $existingSystem = $this->systemModel->findByMacHash($macHash, $licenseId);
        $activeSeats = $this->systemModel->countActiveByLicense($licenseId);

        if (!$existingSystem && $activeSeats >= $signedMaxSeats) {
            return $this->errorResponse("Seat limit reached. Maximum {$signedMaxSeats} systems allowed, {$activeSeats} currently registered. Please contact administrator.");
        }

        $systemResult = $this->systemModel->registerSystem(
            $licenseId,
            $macAddress,
            $ipAddress,
            $hostname,
            null
        );

        if ($deployment->isAdmin() && $systemResult['is_new']) {
            $this->reportService->reportToSuperAdmin([
                'license_code' => $licenseCode,
                'mac_hash' => $macHash,
                'hostname' => $hostname,
                'ip_address' => $ipAddress,
                'user_id' => null,
                'user_name' => null,
                'admin_source' => env('app.adminIdentifier', gethostname()),
            ]);
        }

        $loginApiUrl = env('admin.loginApiUrl');
        if (empty($loginApiUrl)) {
            $baseUrl = rtrim(base_url(), '/');
            $loginApiUrl = $baseUrl . '/api/desktop/login';
        }

        return $this->respond([
            'LmsProbeOrigin' => $licenseData['lms_probe_origin'] ?? '',
            'licence_valid' => true,
            'login_needed' => (bool) $licenseData['enable_login_screen'],
            'detect_camera' => (bool) $licenseData['enable_camera_detection'],
            'detect_person' => (bool) $licenseData['enable_person_detection'],
            'screenshot_needed' => (bool) ($licenseData['screenshot_needed'] ?? false),
            'default_login_api' => $loginApiUrl,
            'msg' => 'License validated successfully',
            'SapWebUrl' => $licenseData['sap_web_url'] ?? '',
        ]);
    }

    public function login()
    {
        $userId = $this->request->getVar('user_id') ?? $this->request->getVar('userid') ?? $this->request->getVar('username');
        $password = $this->request->getVar('password');

        if (empty($userId) || empty($password)) {
            return $this->fail('User ID and password are required', 400);
        }

        $license = $this->getAdminLicense();
        if (!$license) {
            return $this->fail('No license configured for this Admin deployment', 404);
        }

        $licenseId = $license['id'];

        if (!(bool) $license['enable_login_screen']) {
            return $this->fail('Login screen is not enabled for this license', 400);
        }

        $user = $this->userModel->where('user_id', $userId)
                                ->where('license_id', $licenseId)
                                ->first();

        if (!$user) {
            return $this->failNotFound('User not found');
        }

        if (!password_verify($password, $user['password'])) {
            return $this->fail('Invalid password', 401);
        }

        if ($user['status'] !== 'active') {
            return $this->fail('User account is not active', 403);
        }

        $this->userModel->update($user['id'], [
            'last_login' => date('Y-m-d H:i:s'),
        ]);

        return $this->respond([
            'success' => true,
            'message' => 'Login successful',
            'user' => [
                'id' => $user['id'],
                'user_id' => $user['user_id'],
                'full_name' => $user['full_name'],
                'email' => $user['email'],
                'department' => $user['department'],
            ],
        ]);
    }

}
