<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\DynamicDnsClient;
use App\Models\DnsZone;
use Illuminate\Http\Request;

class DynamicDnsController extends Controller
{
    /**
     * Display list of DynDNS clients
     */
    public function index(Request $request)
    {
        $user = auth()->user();

        // Adminul are acces la toate funcțiile
        if (!$user->isAdmin()) {
            $plan = $user->plan ?? $user->resellerPlan;

            // Verifică dacă planul permite DynDNS
            if (!$plan || !$plan->hasDynDns()) {
                return redirect()->route('dashboard')
                    ->with('error', 'Planul tău actual nu include funcționalitatea DynDNS. Te rugăm să upgrazi planul.');
            }
        }

        // Adminul vede toate clientele DynDNS, utilizatorii văd doar ale lor
        $clientsQuery = DynamicDnsClient::with(['dnsZone', 'user']);

        if (!$user->isAdmin()) {
            $clientsQuery->where('user_id', auth()->id());
        }

        // Calculează statistici înainte de filtrare
        $statsQuery = clone $clientsQuery;
        $stats = [
            'total' => $statsQuery->count(),
            'active' => (clone $statsQuery)->where('is_active', true)->count(),
            'inactive' => (clone $statsQuery)->where('is_active', false)->count(),
            'total_updates' => (clone $statsQuery)->sum('update_count'),
            'updated_today' => (clone $statsQuery)->whereDate('last_update', today())->count(),
            'updated_this_week' => (clone $statsQuery)->whereBetween('last_update', [now()->startOfWeek(), now()->endOfWeek()])->count(),
        ];

        // Filtrare după căutare
        if ($search = $request->input('search')) {
            $clientsQuery->where(function ($query) use ($search) {
                $query->where('hostname', 'like', "%{$search}%")
                      ->orWhere('current_ip', 'like', "%{$search}%")
                      ->orWhereHas('dnsZone', function ($q) use ($search) {
                          $q->where('domain', 'like', "%{$search}%");
                      });
            });
        }

        // Filtrare după status (doar dacă e selectat un status specific)
        if ($request->filled('status')) {
            $clientsQuery->where('is_active', $request->status === 'active');
        }

        $clients = $clientsQuery->latest()->paginate(20)->withQueryString();

        return view('admin.dynamic-dns.index', compact('clients', 'stats'));
    }

    /**
     * Show create form
     */
    public function create()
    {
        $user = auth()->user();

        // Adminul are acces la toate funcțiile
        if (!$user->isAdmin()) {
            $plan = $user->plan ?? $user->resellerPlan;

            // Verifică dacă planul permite DynDNS
            if (!$plan || !$plan->hasDynDns()) {
                return redirect()->route('dashboard')
                    ->with('error', 'Planul tău actual nu include funcționalitatea DynDNS. Te rugăm să upgrazi planul.');
            }

            // Verifică limita de clienți DynDNS
            if (!$plan->canCreateDynDnsClient($user)) {
                $limit = $plan->dyndns_max_clients;
                return redirect()->route('dyndns.index')
                    ->with('error', "Ai atins limita de {$limit} clienți DynDNS pentru planul tău actual.");
            }
        }

        $zones = auth()->user()->dnsZones()->orderBy('domain')->get();

        return view('admin.dynamic-dns.create', compact('zones'));
    }

    /**
     * Store new DynDNS client
     */
    public function store(Request $request)
    {
        $user = auth()->user();

        // Adminul are acces la toate funcțiile
        if (!$user->isAdmin()) {
            $plan = $user->plan ?? $user->resellerPlan;

            // Verifică dacă planul permite DynDNS
            if (!$plan || !$plan->hasDynDns()) {
                return back()->with('error', 'Planul tău actual nu include funcționalitatea DynDNS. Te rugăm să upgrazi planul.');
            }

            // Verifică limita de clienți DynDNS
            if (!$plan->canCreateDynDnsClient($user)) {
                $limit = $plan->dyndns_max_clients;
                return back()->with('error', "Ai atins limita de {$limit} clienți DynDNS pentru planul tău actual.");
            }
        }

        $request->validate([
            'dns_zone_id' => 'required|exists:dns_zones,id',
            'hostname' => 'required|string|max:255',
            'ttl' => 'nullable|integer|min:60|max:86400',
            'notify_on_change' => 'nullable|boolean',
        ]);

        // Check zonă ownership (adminul poate crea pentru orice zonă)
        $zone = DnsZone::findOrFail($request->dns_zone_id);
        if (!$user->isAdmin() && $zone->user_id !== auth()->id()) {
            abort(403, 'Unauthorized');
        }

        // Validează hostnume belongs to zonă
        if (!str_ends_with($request->hostname, $zone->domain)) {
            return back()->withErrors([
                'hostname' => "Hostname-ul trebuie să aparțină domeniului {$zone->domain}"
            ])->withInput();
        }

        // Verifică dacă hostnume există deja
        if (DynamicDnsClient::where('hostname', $request->hostname)->exists()) {
            return back()->withErrors([
                'hostname' => 'Un client DynDNS există deja pentru acest hostname'
            ])->withInput();
        }

        $client = DynamicDnsClient::create([
            'user_id' => auth()->id(),
            'dns_zone_id' => $request->dns_zone_id,
            'hostname' => $request->hostname,
            'token' => DynamicDnsClient::generateToken(),
            'ttl' => $request->ttl ?? 300,
            'notify_on_change' => $request->boolean('notify_on_change'),
        ]);

        return redirect()->route('dyndns.show', $client)
            ->with('success', 'Client DynDNS creat cu succes!');
    }

    /**
     * Show client details
     */
    public function show(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Adminul are acces la toate funcțiile
        if (!$user->isAdmin()) {
            $plan = $user->plan ?? $user->resellerPlan;

            // Verifică dacă planul permite DynDNS
            if (!$plan || !$plan->hasDynDns()) {
                return redirect()->route('dashboard')
                    ->with('error', 'Planul tău actual nu include funcționalitatea DynDNS. Te rugăm să upgrazi planul.');
            }
        }

        $dynamicDnsClient->load(['dnsZone', 'user']);

        // Check ownership (adminul poate vedea toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        // Obține ultimele 20 de log-uri de actualizare
        $updateLogs = $dynamicDnsClient->updateLogs()
            ->orderBy('created_at', 'desc')
            ->take(20)
            ->get();

        return view('admin.dynamic-dns.show', [
            'client' => $dynamicDnsClient,
            'updateLogs' => $updateLogs,
        ]);
    }

    /**
     * Afișează formularul de editare pentru un client DynDNS
     */
    public function edit(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Adminul are acces la toate funcțiile
        if (!$user->isAdmin()) {
            $plan = $user->plan ?? $user->resellerPlan;

            // Verifică dacă planul permite DynDNS
            if (!$plan || !$plan->hasDynDns()) {
                return redirect()->route('dashboard')
                    ->with('error', 'Planul tău actual nu include funcționalitatea DynDNS.');
            }
        }

        // Check ownership (adminul poate edita toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        return view('admin.dynamic-dns.edit', [
            'client' => $dynamicDnsClient,
        ]);
    }

    /**
     * Actualizează un client DynDNS existent
     */
    public function update(Request $request, DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Check ownership (adminul poate actualiza toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        $request->validate([
            'ttl' => 'required|integer|min:60|max:86400',
            'notify_on_change' => 'nullable|boolean',
        ]);

        $dynamicDnsClient->update([
            'ttl' => $request->ttl,
            'notify_on_change' => $request->boolean('notify_on_change'),
        ]);

        return redirect()->route('dyndns.show', $dynamicDnsClient)
            ->with('success', 'Client DynDNS actualizat cu succes!');
    }

    /**
     * Toggle client status
     */
    public function toggle(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Check ownership (adminul poate modifica toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        $dynamicDnsClient->update([
            'is_active' => !$dynamicDnsClient->is_active,
        ]);

        return response()->json([
            'success' => true,
            'message' => $dynamicDnsClient->is_active ? 'Client activat' : 'Client dezactivat',
            'is_active' => $dynamicDnsClient->is_active,
        ]);
    }

    /**
     * Forțează sincronizarea DNS record-ului cu IP-ul curent
     */
    public function forceSync(Request $request, DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Check ownership (adminul poate sincroniza toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        // Verifică dacă clientul are un IP setat
        if (!$dynamicDnsClient->current_ip) {
            return redirect()->route('dyndns.show', $dynamicDnsClient)
                ->with('error', 'Nu există un IP curent setat. Rulează scriptul de actualizare pentru a detecta IP-ul.');
        }

        // Obține serviciul DynDNS
        $dyndnsService = app(\App\Services\DynamicDnsService::class);

        // Forțează re-sincronizarea (resetează IP-ul pentru a forța update)
        $oldIp = $dynamicDnsClient->current_ip;
        $dynamicDnsClient->current_ip = null;
        $dynamicDnsClient->save();

        // Re-aplică IP-ul pentru a forța sincronizarea
        $result = $dyndnsService->updateDnsRecord(
            $dynamicDnsClient,
            $oldIp,
            $request->ip(),
            'Manual Sync from Panel'
        );

        if ($result['success']) {
            return redirect()->route('dyndns.show', $dynamicDnsClient)
                ->with('success', 'DNS sincronizat cu succes! IP: ' . $oldIp);
        }

        return redirect()->route('dyndns.show', $dynamicDnsClient)
            ->with('error', 'Eroare la sincronizare: ' . ($result['message'] ?? 'Eroare necunoscută'));
    }

    /**
     * Delete client
     */
    public function destroy(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Check ownership (adminul poate șterge toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        $dynamicDnsClient->delete();

        return redirect()->route('dyndns.index')
            ->with('success', 'Client DynDNS șters cu succes!');
    }

    /**
     * Regenerează token-ul API pentru un client DynDNS
     */
    public function regenerateToken(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Verifică ownership (adminul poate regenera pentru toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        // Generează un token nou
        $dynamicDnsClient->update([
            'token' => DynamicDnsClient::generateToken(),
        ]);

        return redirect()->route('dyndns.show', $dynamicDnsClient)
            ->with('success', 'Token-ul API a fost regenerat cu succes! Nu uita să actualizezi scripturile.');
    }

    /**
     * Download setup script
     */
    public function downloadScript(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Check ownership (adminul poate descărca toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        $script = $this->generateBashScript($dynamicDnsClient);

        return response($script)
            ->header('Content-Type', 'text/plain')
            ->header('Content-Disposition', 'attachment; filename="dyndns-update.sh"');
    }

    /**
     * Download script pentru Windows PowerShell
     */
    public function downloadWindowsScript(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Verifică ownership (adminul poate descărca toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        $script = $this->generatePowerShellScript($dynamicDnsClient);

        return response($script)
            ->header('Content-Type', 'text/plain')
            ->header('Content-Disposition', 'attachment; filename="dyndns-update.ps1"');
    }

    /**
     * Download script BAT pentru Windows
     */
    public function downloadWindowsBatch(DynamicDnsClient $dynamicDnsClient)
    {
        $user = auth()->user();

        // Verifică ownership (adminul poate descărca toate)
        if (!$user->isAdmin() && $dynamicDnsClient->user_id !== auth()->id()) {
            abort(403);
        }

        $script = $this->generateBatchScript($dynamicDnsClient);

        return response($script)
            ->header('Content-Type', 'text/plain')
            ->header('Content-Disposition', 'attachment; filename="dyndns-update.bat"');
    }

    /**
     * Generate bash script for client
     */
    protected function generateBashScript(DynamicDnsClient $client): string
    {
        $updateUrl = route('api.dyndns.update');

        return <<<BASH
#!/bin/bash

#############################################
# DynDNS Update Script
# Generated for: {$client->hostname}
# Date: {now()->format('Y-m-d H:i:s')}
#############################################

# Configuration
TOKEN="{$client->token}"
HOSTNAME="{$client->hostname}"
API_URL="{$updateUrl}"
LOG_FILE="/var/log/dyndns-update.log"

# Create log directory dacă nu există
mkdir -p "\$(dirname "\$LOG_FILE")"

# Update IP
echo "[\$(date '+%Y-%m-%d %H:%M:%S')] Updating DynDNS for \$HOSTNAME..." >> "\$LOG_FILE"

RESPONSE=\$(curl -s "\${API_URL}?token=\${TOKEN}&hostname=\${HOSTNAME}")

# Log response
echo "[\$(date '+%Y-%m-%d %H:%M:%S')] Response: \$RESPONSE" >> "\$LOG_FILE"

# Check success
if echo "\$RESPONSE" | grep -q '"success":true'; then
    if echo "\$RESPONSE" | grep -q '"updated":true'; then
        echo "[\$(date '+%Y-%m-%d %H:%M:%S')] ✓ IP actualizat cu succes" >> "\$LOG_FILE"
    else
        echo "[\$(date '+%Y-%m-%d %H:%M:%S')] ✓ IP neschimbat" >> "\$LOG_FILE"
    fi
else
    echo "[\$(date '+%Y-%m-%d %H:%M:%S')] ✗ Eroare la actualizare" >> "\$LOG_FILE"
fi

BASH;
    }

    /**
     * Generează script PowerShell pentru Windows
     */
    protected function generatePowerShellScript(DynamicDnsClient $client): string
    {
        $updateUrl = route('api.dyndns.update');

        return <<<POWERSHELL
# DynDNS Update Script pentru Windows PowerShell
# Generated for: {$client->hostname}
# Date: {now()->format('Y-m-d H:i:s')}

#############################################
# Configurație
#############################################
\$TOKEN = "{$client->token}"
\$HOSTNAME = "{$client->hostname}"
\$API_URL = "{$updateUrl}"
\$LOG_FILE = "\$env:TEMP\\dyndns-update.log"

#############################################
# Funcție pentru logging
#############################################
function Write-Log {
    param([string]\$Message)
    \$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    \$logMessage = "[\$timestamp] \$Message"
    Add-Content -Path \$LOG_FILE -Value \$logMessage
    Write-Host \$logMessage
}

#############################################
# Update IP
#############################################
Write-Log "Updating DynDNS pentru \$HOSTNAME..."

try {
    # Construiește URL-ul cu parametrii
    \$url = "\$API_URL" + "?token=\$TOKEN&hostname=\$HOSTNAME"

    # Trimite request
    \$response = Invoke-RestMethod -Uri \$url -Method Get -ErrorAction Stop

    # Verifică răspunsul
    if (\$response.success) {
        if (\$response.updated) {
            Write-Log "✓ IP actualizat cu succes la: \$(\$response.new_ip)"
        } else {
            Write-Log "✓ IP neschimbat: \$(\$response.current_ip)"
        }
    } else {
        Write-Log "✗ Eroare: \$(\$response.message)"
        exit 1
    }
} catch {
    Write-Log "✗ Excepție la actualizare: \$(\$_.Exception.Message)"
    exit 1
}

exit 0
POWERSHELL;
    }

    /**
     * Generează script BAT pentru Windows
     */
    protected function generateBatchScript(DynamicDnsClient $client): string
    {
        $updateUrl = route('api.dyndns.update');

        return <<<BATCH
@echo off
REM DynDNS Update Script pentru Windows
REM Generated for: {$client->hostname}
REM Date: {now()->format('Y-m-d H:i:s')}

REM #############################################
REM Configurație
REM #############################################
set TOKEN={$client->token}
set HOSTNAME={$client->hostname}
set API_URL={$updateUrl}
set LOG_FILE=%TEMP%\\dyndns-update.log

REM #############################################
REM Update IP
REM #############################################
echo [%date% %time%] Updating DynDNS pentru %HOSTNAME%... >> "%LOG_FILE%"

REM Folosește curl (disponibil în Windows 10+)
curl -s "%API_URL%?token=%TOKEN%&hostname=%HOSTNAME%" > "%TEMP%\\dyndns-response.json"

REM Afișează răspunsul
type "%TEMP%\\dyndns-response.json" >> "%LOG_FILE%"

REM Verifică dacă curl a reușit
if %ERRORLEVEL% EQU 0 (
    echo [%date% %time%] Request trimis cu succes >> "%LOG_FILE%"
) else (
    echo [%date% %time%] Eroare la trimiterea request-ului >> "%LOG_FILE%"
)

REM Cleanup
del "%TEMP%\\dyndns-response.json" 2>nul

exit /b 0
BATCH;
    }
}
