<?php
class SettingController extends Controller
{
    public function index(): void
    {
        Auth::requirePermission('settings.view');

        $settings = Database::fetchAll('SELECT setting_key,setting_value FROM settings ORDER BY id');
        $s = array_column($settings, 'setting_value', 'setting_key');

        // Activity log stats — safe fallback if table missing
        try {
            $logStats = Database::fetchOne(
                "SELECT COUNT(*) AS total,
                        COUNT(CASE WHEN created_at >= DATE_SUB(NOW(),INTERVAL 24 HOUR) THEN 1 END) AS today,
                        COUNT(CASE WHEN action LIKE '%login%' AND created_at >= DATE_SUB(NOW(),INTERVAL 24 HOUR) THEN 1 END) AS logins_today,
                        COUNT(CASE WHEN action LIKE '%fail%'  AND created_at >= DATE_SUB(NOW(),INTERVAL 24 HOUR) THEN 1 END) AS failed_today,
                        MAX(created_at) AS last_entry
                 FROM activity_logs"
            );
        } catch (Exception $e) {
            $logStats = ['total'=>0,'today'=>0,'logins_today'=>0,'failed_today'=>0,'last_entry'=>null];
        }

        // Current online users — safe fallback if last_active column missing
        try {
            $onlineNow = Database::fetchAll(
                "SELECT u.name, r.role_name,
                        COALESCE(b.name,'Main Branch') AS branch_name,
                        TIMESTAMPDIFF(SECOND,u.last_active,NOW()) AS sec_ago,
                        CASE WHEN u.last_active>=DATE_SUB(NOW(),INTERVAL 2 MINUTE)  THEN 'online'
                             WHEN u.last_active>=DATE_SUB(NOW(),INTERVAL 15 MINUTE) THEN 'away'
                             ELSE 'offline' END AS status
                 FROM users u JOIN roles r ON r.id=u.role_id
                 LEFT JOIN branches b ON b.id=u.branch_id
                 WHERE u.last_active>=DATE_SUB(NOW(),INTERVAL 15 MINUTE)
                   AND u.status='active'
                 ORDER BY u.last_active DESC"
            );
        } catch (Exception $e) {
            $onlineNow = [];
        }

        $pageTitle = 'Settings';
        ob_start();
        require APP_PATH . '/views/settings/index.php';
        $content = ob_get_clean();
        require APP_PATH . '/views/layouts/main.php';
    }
    public function update(): void
    {
        Auth::requirePermission('settings.edit');
        Auth::requireCsrf();

        $keys = [
            'shop_name','shop_tagline','shop_address','shop_phone','shop_email',
            'currency_symbol','currency_code',
            'tax_percent','tax_name','invoice_prefix','purchase_prefix',
            'return_prefix','receipt_footer',
            'print_auto_enabled','print_auto_close','print_paper_width','print_copies',
            'pmt_account_cash','pmt_account_card','pmt_account_bank_transfer','pmt_account_mobile',
            'card_fee_percent','daily_sales_target','daily_target_enabled',
            'sms_enabled','sms_user_id','sms_api_key','sms_sender_id','sms_api_url','sms_template',
            'admin_reset_phone','admin_report_phone',
            'low_stock_alert','expiry_alert_days','allow_negative_stock',
            'receipt_show_tax','receipt_show_logo','timezone',
            'activity_log_enabled','activity_log_retention_days',
            'log_sales','log_purchases','log_expenses','log_auth','log_settings','log_stock',
            'online_timeout_online','online_timeout_away','online_poll_interval','show_online_users',
        ];

        $pdo = Database::getInstance();
        try {
            $pdo->beginTransaction();

            $sql = 'INSERT INTO settings (setting_key, setting_value) VALUES (?, ?)
                    ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)';
            foreach ($keys as $key) {
                if (!array_key_exists($key, $_POST)) {
                    continue;
                }
                $value = is_array($_POST[$key]) ? '' : trim((string) $_POST[$key]);
                Database::execute($sql, [$key, $value]);
            }

            $pdo->commit();

            $this->saveUploadedImage('shop_logo', 'shop_logo', 'logo', ALLOWED_IMG_TYPES);
            $this->saveUploadedImage('site_icon', 'site_icon', 'site-icon', [
                'image/png','image/jpeg','image/x-icon','image/vnd.microsoft.icon',
                'image/svg+xml','image/webp','image/gif',
            ]);
            $this->saveUploadedImage('login_bg', 'login_bg_image', 'login-bg', ALLOWED_IMG_TYPES);

            if ($this->post('remove_site_icon') === '1') {
                $this->removeSettingFile('site_icon');
            }
            if ($this->post('remove_login_bg') === '1') {
                $this->removeSettingFile('login_bg_image');
            }

            $rows = Database::fetchAll('SELECT setting_key,setting_value FROM settings');
            $_SESSION['settings'] = array_column($rows, 'setting_value', 'setting_key');

            Auth::logAudit(Auth::id(), 'settings_update', 'settings', 'Settings updated');
            redirectWith(APP_URL . '/settings', 'success', 'Settings saved successfully.');
        } catch (\Throwable $e) {
            if ($pdo->inTransaction()) {
                $pdo->rollBack();
            }
            error_log('Settings update failed: ' . $e->getMessage());
            redirectWith(APP_URL . '/settings', 'error', 'Settings could not be saved. Please check the server error log.');
        }
    }

    private function saveSetting(string $key, string $value): void
    {
        Database::execute(
            'INSERT INTO settings (setting_key, setting_value) VALUES (?, ?)
             ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)',
            [$key, $value]
        );
    }

    private function saveUploadedImage(string $field, string $settingKey, string $baseName, array $allowedTypes): void
    {
        if (empty($_FILES[$field]['tmp_name']) || !is_uploaded_file($_FILES[$field]['tmp_name'])) {
            return;
        }

        $tmp = $_FILES[$field]['tmp_name'];
        $type = mime_content_type($tmp) ?: '';
        if (!in_array($type, $allowedTypes, true)) {
            throw new RuntimeException('Invalid image type for ' . $field);
        }

        $extensions = [
            'image/jpeg'=>'jpg', 'image/png'=>'png', 'image/gif'=>'gif',
            'image/webp'=>'webp', 'image/svg+xml'=>'svg',
            'image/x-icon'=>'ico', 'image/vnd.microsoft.icon'=>'ico',
        ];
        $ext = $extensions[$type] ?? strtolower(pathinfo($_FILES[$field]['name'] ?? '', PATHINFO_EXTENSION));
        if ($ext === '') {
            $ext = 'png';
        }

        if (!is_dir(UPLOAD_PATH) && !mkdir(UPLOAD_PATH, 0755, true) && !is_dir(UPLOAD_PATH)) {
            throw new RuntimeException('Upload directory could not be created');
        }

        $file = $baseName . '.' . $ext;
        $dest = UPLOAD_PATH . '/' . $file;
        if (!move_uploaded_file($tmp, $dest)) {
            throw new RuntimeException('Failed to upload ' . $field);
        }

        $old = setting($settingKey, '');
        if ($old && $old !== $file && is_file(UPLOAD_PATH . '/' . $old)) {
            @unlink(UPLOAD_PATH . '/' . $old);
        }
        $this->saveSetting($settingKey, $file);
    }

    private function removeSettingFile(string $settingKey): void
    {
        $current = setting($settingKey, '');
        if ($current && is_file(UPLOAD_PATH . '/' . $current)) {
            @unlink(UPLOAD_PATH . '/' . $current);
        }
        Database::execute('DELETE FROM settings WHERE setting_key = ?', [$settingKey]);
    }

    /** AJAX: GET /settings/sms-status */
    public function smsStatus(): void
    {
        Auth::requirePermission('settings.view');
        header('Content-Type: application/json');
        try {
            if (!function_exists('curl_init')) {
                echo json_encode(['success'=>false,'message'=>'cURL not available on server']);
                exit;
            }
            $uid = setting('sms_user_id','');
            $key = setting('sms_api_key','');
            if (!$uid || !$key) {
                echo json_encode(['success'=>false,'message'=>'SMS not configured']);
                exit;
            }
            $url = rtrim(setting('sms_api_url','https://smslenz.lk/api'),'/') .
                   '/account-status?user_id='.urlencode($uid).'&api_key='.urlencode($key);
            $ch = curl_init();
            curl_setopt_array($ch,[CURLOPT_URL=>$url,CURLOPT_RETURNTRANSFER=>true,
                CURLOPT_TIMEOUT=>10,CURLOPT_CONNECTTIMEOUT=>6,CURLOPT_SSL_VERIFYPEER=>false]);
            $raw = curl_exec($ch);
            $err = curl_errno($ch); curl_close($ch);
            if ($err) { echo json_encode(['success'=>false,'message'=>'cURL error: '.curl_strerror($err)]); exit; }
            $resp = $raw ? json_decode($raw,true) : null;
            echo json_encode($resp ?: ['success'=>false,'message'=>'Invalid response']);
        } catch (\Throwable $e) {
            echo json_encode(['success'=>false,'message'=>$e->getMessage()]);
        }
        exit;
    }

    /** AJAX: GET /settings/sms-test?phone=xxx */
    public function smsTest(): void
    {
        Auth::requirePermission('settings.view');
        header('Content-Type: application/json');
        try {
            $phone = trim($this->get('phone',''));
            if (!$phone) { echo json_encode(['success'=>false,'message'=>'Phone required']); exit; }
            if (!function_exists('curl_init')) { echo json_encode(['success'=>false,'message'=>'cURL not available']); exit; }

            // Format phone
            $p = preg_replace('/[\s\-\(\)]/','',$phone);
            if (preg_match('/^0[0-9]{9}$/',$p))     $p = '+94'.substr($p,1);
            elseif (preg_match('/^94\d{9}$/',$p))   $p = '+'.$p;
            elseif (preg_match('/^7[0-9]{8}$/',$p)) $p = '+94'.$p;

            $tpl = setting('sms_template','Hi {customer}, Invoice {invoice_no} | Total: Rs.{total} | Paid: Rs.{paid} | Thank you! - {shop_name}');
            $msg = str_replace(
                ['{invoice_no}','{total}','{paid}','{change}','{balance}','{customer}','{shop_name}','{date}'],
                ['TEST-'.date('YmdHis'),'1,000.00','1,000.00','0.00','0.00','Test Customer',setting('shop_name','MJPOS'),date('d M Y')],
                $tpl
            );

            $ch = curl_init();
            curl_setopt_array($ch,[
                CURLOPT_URL            => rtrim(setting('sms_api_url','https://smslenz.lk/api'),'/').'/send-sms',
                CURLOPT_POST           => true,
                CURLOPT_POSTFIELDS     => http_build_query([
                    'user_id'   => setting('sms_user_id',''),
                    'api_key'   => setting('sms_api_key',''),
                    'sender_id' => setting('sms_sender_id','SMSlenzDEMO'),
                    'contact'   => $p, 'message' => $msg,
                ]),
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT        => 10,
                CURLOPT_SSL_VERIFYPEER => false,
            ]);
            $raw = curl_exec($ch); $errno = curl_errno($ch); $cerr = curl_error($ch); curl_close($ch);
            if ($errno) { echo json_encode(['success'=>false,'message'=>"cURL ({$errno}): {$cerr}"]); exit; }
            $resp = $raw ? json_decode($raw,true) : null;
            if ($resp && ($resp['success']??false)) {
                echo json_encode(['success'=>true,'message'=>'SMS sent to '.$p,
                    'balance'=>$resp['data']['sms_credit_balance']??null]);
            } else {
                echo json_encode(['success'=>false,'message'=>$resp['message']??'Failed — check credentials: '.substr($raw??'',0,100)]);
            }
        } catch (\Throwable $e) {
            echo json_encode(['success'=>false,'message'=>'Error: '.$e->getMessage()]);
        }
        exit;
    }

    // ── Test Print Page ──────────────────────────────────
    public function testPrint(): void
    {
        Auth::requirePermission('settings.view');
        $shopName    = setting('shop_name',    'MJPOS');
        $shopAddress = setting('shop_address', '');
        $shopPhone   = setting('shop_phone',   '');
        $paperWidth  = setting('print_paper_width', '80mm');
        $autoClose   = setting('print_auto_close', '1');
        require APP_PATH . '/views/settings/test_print.php';
        exit;
    }

    // ── Download Windows Kiosk BAT ───────────────────────
    public function downloadKioskBat(): void
    {
        Auth::requirePermission('settings.view');
        $url = APP_URL . '/pos';
        $bat = "@echo off\r\n"
             . "REM MJPOS Silent Print Launcher\r\n"
             . "REM Double-click this file to open POS with silent printing (no print dialog)\r\n"
             . "\r\n"
             . "set URL={$url}\r\n"
             . "\r\n"
             . "REM Try Chrome first\r\n"
             . "set CHROME=\"%PROGRAMFILES%\\Google\\Chrome\\Application\\chrome.exe\"\r\n"
             . "if not exist %CHROME% set CHROME=\"%PROGRAMFILES(X86)%\\Google\\Chrome\\Application\\chrome.exe\"\r\n"
             . "if not exist %CHROME% set CHROME=\"%LOCALAPPDATA%\\Google\\Chrome\\Application\\chrome.exe\"\r\n"
             . "\r\n"
             . "if exist %CHROME% (\r\n"
             . "    start \"\" %CHROME% --kiosk-printing --app=%URL%\r\n"
             . "    goto end\r\n"
             . ")\r\n"
             . "\r\n"
             . "REM Fallback to Edge\r\n"
             . "set EDGE=\"%PROGRAMFILES(X86)%\\Microsoft\\Edge\\Application\\msedge.exe\"\r\n"
             . "if not exist %EDGE% set EDGE=\"%PROGRAMFILES%\\Microsoft\\Edge\\Application\\msedge.exe\"\r\n"
             . "if exist %EDGE% (\r\n"
             . "    start \"\" %EDGE% --kiosk-printing --app=%URL%\r\n"
             . "    goto end\r\n"
             . ")\r\n"
             . "\r\n"
             . "echo Browser not found. Please install Chrome or Edge.\r\n"
             . "pause\r\n"
             . ":end\r\n";

        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="MJPOS_Silent_Print.bat"');
        header('Content-Length: ' . strlen($bat));
        echo $bat;
        exit;
    }
}