<?php

namespace App\Modules\Vm\Dummyvm;

use App\Core\Vm\AbstractVm;
use App\Jobs\SendEmailJob;
use App\Models\Client;
use App\Models\Setting;
use Illuminate\Support\Facades\Log;

/**
 * Dummyvm — VM provider modüllerinin yazılışını gösteren örnek/skeleton.
 *
 * Yaşam döngüsü: ProductInterface metodları (`createAccount`,
 * `terminateAccount`, `suspendAccount`, `unsuspendAccount`). VM-spesifik
 * ekstra operasyonlar (reboot, status) `getAdminButtons()` ile deklare
 * edilir + `adminCustomAction()` ile dispatch olur — bu sayede
 * MODULE_ACTIONS_SYSTEM'in standart pattern'ine uyar.
 *
 * `paramSchema()` mapping pipeline için ürünün hangi config option'larını
 * provider params'a eşleyebileceğini bildirir; admin product edit'te
 * dinamik dropdown'lar bu şemadan üretilir.
 */
class Dummyvm extends AbstractVm
{
    public function createAccount(array $params)
    {
        $result = $this->ok('Dummy VM created', [
            'vm_id' => 'dummy-' . uniqid(),
            'ip_address' => '203.0.113.1',
            'hostname' => $params['hostname'] ?? 'dummy.example',
        ]);
        $this->notifyAdmin('Create Account', $params, $result);

        return $result;
    }

    public function terminateAccount(array $params)
    {
        $result = $this->ok('Dummy VM destroyed');
        $this->notifyAdmin('Terminate Account', $params, $result);

        return $result;
    }

    public function suspendAccount(array $params)
    {
        $result = $this->ok('Dummy VM suspended');
        $this->notifyAdmin('Suspend Account', $params, $result);

        return $result;
    }

    public function unsuspendAccount(array $params)
    {
        $result = $this->ok('Dummy VM resumed');
        $this->notifyAdmin('Unsuspend Account', $params, $result);

        return $result;
    }

    public function changeAccountPassword(array $params)
    {
        $result = $this->ok('Dummy VM password changed');
        $this->notifyAdmin('Change Password', $params, $result);

        return $result;
    }

    public function paramSchema(): array
    {
        return [
            ['key' => 'plan', 'label' => 'Plan', 'required' => false],
            ['key' => 'region', 'label' => 'Region', 'required' => false],
        ];
    }

    /**
     * Admin butonları — render/dispatch katmanı (product-detail.blade +
     * ClientController) her butonu `$button['action']` üzerinden route eder;
     * bu yüzden liste-halinde, her girişte `action` key'i ZORUNLU. Yalnızca
     * `adminCustomAction()`'da GERÇEKTEN handle edilen aksiyonlar deklare
     * edilir (reboot + status) — desteklenmeyen buton reklam edilmez.
     */
    public function getAdminButtons(): array
    {
        return [
            [
                'action' => 'reboot',
                'label' => 'Reboot VM',
                'icon' => 'fas fa-redo',
                'class' => 'btn-outline-warning',
            ],
            [
                'action' => 'status',
                'label' => 'Refresh Status',
                'icon' => 'fas fa-sync',
                'class' => 'btn-outline-info',
            ],
        ];
    }

    public function adminCustomAction(string $action, array $params): array
    {
        $result = match ($action) {
            'reboot' => $this->ok('Dummy VM rebooted'),
            'status' => $this->ok('Status fetched', [
                'power_state' => 'running',
                'cpu_usage' => 5,
                'memory_used_mb' => 512,
                'memory_total_mb' => 2048,
            ]),
            default => $this->fail("Unknown action '{$action}'"),
        };
        $this->notifyAdmin("Admin Action: {$action}", $params, $result);

        return $result;
    }

    public function testConnection(array $params)
    {
        return $this->ok('Dummy provider always reachable');
    }

    public function adminFields()
    {
        return [
            'api_endpoint' => [
                'type' => 'text',
                'label' => 'API Endpoint',
                'description' => 'Provider API URL — Dummyvm için kullanılmaz, sadece field örnek.',
                'default' => 'https://api.example.com',
            ],
            'api_token' => [
                'type' => 'password',
                'label' => 'API Token',
            ],
        ];
    }

    /**
     * Admin'e param-dump bildirimi (PRC-445 QA fixture) — Dummyproduct paterni.
     * $params caller tarafından ModuleParamsBuilder ile zenginleştirilmiş gelir;
     * modül enrichment yapmaz, sadece dump eder. Param-completeness kontratının
     * (modül yalnızca array key okur) e-posta üzerinden çapraz-doğrulama yüzeyi.
     *
     * Not: ayrı bir VM template'i seed etmemek için seeded 'Dummy Product Admin
     * Notification' template'i yeniden kullanılır (hostname → USERNAME).
     */
    protected function notifyAdmin(string $action, array $params = [], array $result = []): void
    {
        try {
            $adminEmail = Setting::getValue('company_email');
            if (! $adminEmail) {
                return;
            }

            $username = $params['hostname']
                ?? ($params['username'] ?? ($params['client_email'] ?? 'N/A'));

            $entityType = 'client_product';
            $entityId = $params['client_product_id'] ?? $params['service_id'] ?? null;

            if (! $entityId) {
                $entityType = 'client';
                $entityId = $params['client_id'] ?? Client::query()->value('id');
            }

            if (! $entityId) {
                return;
            }

            SendEmailJob::dispatch(
                'Dummy Product Admin Notification',
                $entityType,
                (int) $entityId,
                [
                    'ACTION' => '[VM] ' . $action,
                    'USERNAME' => $username,
                    'ACTIONDATE' => now()->format('d/m/Y H:i:s'),
                    'DETAILS' => $this->formatActionDetails($params, $result),
                ],
                null,
                $adminEmail
            );
        } catch (\Exception $e) {
            Log::warning('Dummyvm: Admin notification failed', [
                'action' => $action,
                'error' => $e->getMessage(),
            ]);
        }
    }

    /**
     * 2 JSON <pre> bloğu: Input Parameters (caller'ın gönderdiği zenginleştirilmiş
     * $params) + Return Value. Sensitive key (password) maskelenir.
     */
    private function formatActionDetails(array $params, array $result): string
    {
        $flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;

        $masked = $params;
        foreach (['password', 'root_password', 'api_token'] as $k) {
            if (isset($masked[$k]) && $masked[$k] !== '') {
                $masked[$k] = '***masked***';
            }
        }
        if (isset($masked['server']['password'])) {
            $masked['server']['password'] = '***masked***';
        }

        $preStyle = 'background:#f5f5f5;border:1px solid #ddd;padding:12px;border-radius:4px;'
            .'font-family:Menlo,Monaco,Consolas,monospace;font-size:12px;white-space:pre-wrap;'
            .'word-wrap:break-word;overflow-x:auto;color:#333;';

        $block = function (string $label, string $json) use ($preStyle) {
            return '<p style="margin:16px 0 4px 0;"><strong>'.$label.':</strong></p>'
                .'<pre style="'.$preStyle.'">'.htmlspecialchars($json, ENT_QUOTES, 'UTF-8').'</pre>';
        };

        return '<div style="margin-top:10px;">'
            .$block('Input Parameters', json_encode($masked, $flags) ?: '[]')
            .$block('Return Value', json_encode($result, $flags) ?: '[]')
            .'</div>';
    }
}
