<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Http;

class ESP32CamController extends Controller
{
    /**
     * Upload foto dari ESP32-CAM
     */
    public function upload(Request $request)
    {
        try {
            // Direktori untuk menyimpan gambar
            $uploadDir = 'esp32cam/';
            
            // Pastikan direktori ada di storage/app/public
            if (!Storage::disk('public')->exists($uploadDir)) {
                Storage::disk('public')->makeDirectory($uploadDir);
            }
            
            // Buat nama file unik dengan timestamp
            $filename = 'esp32cam_' . Carbon::now()->format('Ymd_His') . '.jpg';
            $fullPath = $uploadDir . $filename;
            
            // Ambil konten gambar dari request
            $imageContent = $request->getContent();
            
            if (!empty($imageContent)) {
                // Simpan gambar menggunakan Laravel Storage
                if (Storage::disk('public')->put($fullPath, $imageContent)) {
                    // Mengatur waktu file agar sesuai dengan waktu pengambilan saat ini
                    $now = time();
                    $filePath = storage_path('app/public/' . $fullPath);
                    @touch($filePath, $now);
                    
                    // Log informasi upload menggunakan Laravel Logger
                    Log::info("ESP32-CAM image uploaded successfully", [
                        'filename' => $filename,
                        'path' => $fullPath,
                        'size' => strlen($imageContent) . ' bytes',
                        'time' => Carbon::now()->format('Y-m-d H:i:s')
                    ]);
                    
                    return response()->json([
                        'status' => 'success',
                        'message' => 'Gambar tersimpan sebagai ' . $filename,
                        'path' => $fullPath,
                        'time' => Carbon::now()->format('Y-m-d H:i:s')
                    ]);
                }
                
                throw new \Exception('Gagal menyimpan gambar');
            }
            
            throw new \Exception('Tidak ada data yang diterima');
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM upload error: " . $e->getMessage());
            
            return response()->json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Menampilkan semua foto
     */
    public function all(Request $request)
    {
        $uploadDir = 'esp32cam/';
        $files = Storage::disk('public')->files($uploadDir);
        
        // Urutkan file berdasarkan waktu modifikasi (terbaru lebih dulu)
        usort($files, function($a, $b) {
            return Storage::disk('public')->lastModified($b) - Storage::disk('public')->lastModified($a);
        });
        
        $photos = [];
        foreach ($files as $file) {
            $filePath = storage_path('app/public/' . $file);
            $fileModTime = Storage::disk('public')->lastModified($file);
            $fileName = basename($file);
            $fileSize = round(Storage::disk('public')->size($file) / 1024, 2) . ' KB';
            
            // Mendapatkan timestamp dari nama file (format nama file: esp32cam_YmdHis)
            $timestampFromFilename = null;
            if (preg_match('/esp32cam_(\d{8})_(\d{6})/', $fileName, $matches)) {
                $dateStr = $matches[1];
                $timeStr = $matches[2];
                $timestampFromFilename = strtotime(
                    substr($dateStr, 0, 4) . '-' . 
                    substr($dateStr, 4, 2) . '-' . 
                    substr($dateStr, 6, 2) . ' ' . 
                    substr($timeStr, 0, 2) . ':' . 
                    substr($timeStr, 2, 2) . ':' . 
                    substr($timeStr, 4, 2)
                );
            }
            
            // Menggunakan timestamp dari nama file jika tersedia, jika tidak gunakan waktu modifikasi
            $captureTimestamp = $timestampFromFilename ?: $fileModTime;
            $captureTime = date('Y-m-d H:i:s', $captureTimestamp);
            
            // Mendapatkan timestamp dari EXIF data jika tersedia
            if (function_exists('exif_read_data')) {
                try {
                    $exifData = @exif_read_data($filePath);
                    
                    if ($exifData && isset($exifData['DateTimeOriginal'])) {
                        // Format EXIF datetime: YYYY:MM:DD HH:MM:SS
                        $exifTime = strtotime($exifData['DateTimeOriginal']);
                        if ($exifTime) {
                            $captureTimestamp = $exifTime;
                            $captureTime = date('Y-m-d H:i:s', $exifTime);
                        }
                    }
                } catch (\Exception $e) {
                    Log::warning("Error reading EXIF data: " . $e->getMessage());
                }
            }
            
            // Format untuk tampilan
            $displayTime = date('d-m-Y H:i:s', $captureTimestamp);
            
            $photoItem = [
                'name' => $fileName,
                'path' => 'storage/' . $file,
                'time' => $displayTime,
                'size' => $fileSize
            ];
            
            $photos[] = $photoItem;
        }
        
        return view('photos', ['photos' => $photos]);
    }
    
    /**
     * Mengambil foto terbaru
     */
    public function latest()
    {
        $uploadDir = 'esp32cam/';
        $files = Storage::disk('public')->files($uploadDir);
        
        if (count($files) > 0) {
            // Urutkan file berdasarkan waktu modifikasi (terbaru lebih dulu)
            usort($files, function($a, $b) {
                return Storage::disk('public')->lastModified($b) - Storage::disk('public')->lastModified($a);
            });
            
            $latestPhoto = $files[0];
            
            // Get file path for EXIF reading
            $filePath = storage_path('app/public/' . $latestPhoto);
            $fileModTime = Storage::disk('public')->lastModified($latestPhoto);
            $fileSize = round(Storage::disk('public')->size($latestPhoto) / 1024, 2) . ' KB';
            $fileName = basename($latestPhoto);
            
            // Mendapatkan timestamp dari nama file (format nama file: esp32cam_YmdHis)
            $timestampFromFilename = null;
            if (preg_match('/esp32cam_(\d{8})_(\d{6})/', $fileName, $matches)) {
                $dateStr = $matches[1];
                $timeStr = $matches[2];
                $timestampFromFilename = strtotime(
                    substr($dateStr, 0, 4) . '-' . 
                    substr($dateStr, 4, 2) . '-' . 
                    substr($dateStr, 6, 2) . ' ' . 
                    substr($timeStr, 0, 2) . ':' . 
                    substr($timeStr, 2, 2) . ':' . 
                    substr($timeStr, 4, 2)
                );
            }
            
            // Menggunakan timestamp dari nama file jika tersedia, jika tidak gunakan waktu modifikasi
            $captureTimestamp = $timestampFromFilename ?: $fileModTime;
            $captureTime = date('Y-m-d H:i:s', $captureTimestamp);
            
            // Get timestamp from EXIF data if available
            if (function_exists('exif_read_data')) {
                try {
                    $exifData = @exif_read_data($filePath);
                    
                    if ($exifData && isset($exifData['DateTimeOriginal'])) {
                        // Format EXIF datetime: YYYY:MM:DD HH:MM:SS
                        $exifTime = strtotime($exifData['DateTimeOriginal']);
                        if ($exifTime) {
                            $captureTimestamp = $exifTime;
                            $captureTime = date('Y-m-d H:i:s', $exifTime);
                        }
                    }
                } catch (\Exception $e) {
                    Log::warning("Error reading EXIF data: " . $e->getMessage());
                }
            }
            
            // Format untuk tampilan
            $displayTime = date('d-m-Y H:i:s', $captureTimestamp);
            
            return response()->json([
                'status' => 'success',
                'photo' => [
                    'name' => $fileName,
                    'path' => 'storage/' . $latestPhoto,
                    'time' => $displayTime,
                    'timestamp' => $captureTimestamp,
                    'size' => $fileSize
                ]
            ]);
        }
        
        return response()->json([
            'status' => 'error',
            'message' => 'Tidak ada foto yang tersedia'
        ], 404);
    }
    
    /**
     * Hapus foto tertentu
     */
    public function delete(Request $request)
    {
        $filename = $request->input('filename');
        $uploadDir = 'esp32cam/';
        
        if (Storage::disk('public')->exists($uploadDir . $filename)) {
            Storage::disk('public')->delete($uploadDir . $filename);
            
            return response()->json([
                'status' => 'success',
                'message' => 'Foto berhasil dihapus'
            ]);
        }
        
        return response()->json([
            'status' => 'error',
            'message' => 'Foto tidak ditemukan'
        ], 404);
    }

    /**
     * Membersihkan foto lama
     */
    public function cleanup()
    {
        try {
            $uploadDir = 'esp32cam/';
            $files = Storage::disk('public')->files($uploadDir);
            $deletedCount = 0;
            
            // Hapus file yang lebih lama dari 7 hari, tapi simpan minimal 10 file terakhir
            if (count($files) > 10) {
                // Urutkan file berdasarkan waktu modifikasi (terlama lebih dulu)
                usort($files, function($a, $b) {
                    return Storage::disk('public')->lastModified($a) - Storage::disk('public')->lastModified($b);
                });
                
                // Ambil file lama untuk dihapus (tapi sisakan 10 file terakhir)
                $filesToDelete = array_slice($files, 0, count($files) - 10);
                
                foreach ($filesToDelete as $file) {
                    $fileTime = Storage::disk('public')->lastModified($file);
                    if (time() - $fileTime > 7 * 24 * 60 * 60) { // 7 hari dalam detik
                        Storage::disk('public')->delete($file);
                        Log::info("Deleted old ESP32-CAM image: " . $file);
                        $deletedCount++;
                    }
                }
            }
            
            return response()->json([
                'status' => 'success',
                'message' => 'Cleanup completed. Deleted ' . $deletedCount . ' old files.',
                'remaining_files' => count($files) - $deletedCount
            ]);
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM cleanup error: " . $e->getMessage());
            
            return response()->json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Fetch image from ESP32-CAM web server and save it
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function fetchFromCamera(Request $request)
    {
        try {
            // Debug untuk melihat isi request
            Log::info('ESP32CAM Debug - Request Content:', [
                'all' => $request->all(),
                'content' => $request->getContent(),
                'content_decoded' => json_decode($request->getContent(), true),
                'headers' => $request->header()
            ]);
            
            // Gunakan IP kamera dari request atau default
            $cameraIp = '192.168.1.19'; // Default IP
            
            // Coba ambil dari request JSON
            $requestData = json_decode($request->getContent(), true);
            if (isset($requestData['camera_ip']) && !empty($requestData['camera_ip'])) {
                $cameraIp = $requestData['camera_ip'];
            }
            
            Log::info('ESP32CAM Debug - Camera IP:', [
                'camera_ip' => $cameraIp,
                'is_empty' => empty($cameraIp)
            ]);
            
            if (empty($cameraIp)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'IP address ESP32-CAM diperlukan'
                ], 400);
            }
            
            // URL untuk mengambil gambar dari ESP32-CAM
            $captureUrl = "http://{$cameraIp}/capture";
            Log::info('ESP32CAM Capture URL: ' . $captureUrl);
            
            // Ambil gambar dari ESP32-CAM dengan timeout yang lebih lama
            $response = Http::timeout(30)->get($captureUrl);
            
            if ($response->successful()) {
                // Direktori untuk menyimpan gambar
                $uploadDir = 'esp32cam/';
                
                // Pastikan direktori ada di storage/app/public
                if (!Storage::disk('public')->exists($uploadDir)) {
                    Storage::disk('public')->makeDirectory($uploadDir);
                }
                
                // Buat nama file unik dengan timestamp
                $filename = 'esp32cam_' . Carbon::now()->format('Ymd_His') . '.jpg';
                $fullPath = $uploadDir . $filename;
                
                // Simpan gambar menggunakan Laravel Storage
                Storage::disk('public')->put($fullPath, $response->body());
                
                // Mengatur waktu file agar sesuai dengan waktu pengambilan saat ini
                $now = time();
                $filePath = storage_path('app/public/' . $fullPath);
                @touch($filePath, $now);
                
                // Log informasi
                Log::info("ESP32-CAM image fetched successfully", [
                    'camera_ip' => $cameraIp,
                    'filename' => $filename,
                    'path' => $fullPath,
                    'size' => strlen($response->body()) . ' bytes',
                    'time' => Carbon::now()->format('Y-m-d H:i:s')
                ]);
                
                return response()->json([
                    'status' => 'success',
                    'message' => 'Gambar berhasil diambil dari ESP32-CAM',
                    'filename' => $filename,
                    'path' => $fullPath,
                    'time' => Carbon::now()->format('Y-m-d H:i:s')
                ]);
            }
            
            Log::error('ESP32-CAM fetch error: Failed with status ' . $response->status());
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengambil gambar dari ESP32-CAM. Status: ' . $response->status(),
                'camera_ip' => $cameraIp
            ], 500);
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM fetch error: " . $e->getMessage(), [
                'camera_ip' => $cameraIp ?? '192.168.1.19',
                'exception' => $e
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengambil gambar: ' . $e->getMessage(),
                'camera_ip' => $cameraIp ?? '192.168.1.19'
            ], 500);
        }
    }

    /**
     * Proxy untuk endpoint status dari ESP32-CAM
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function proxyStatus(Request $request)
    {
        try {
            $cameraIp = $request->query('ip');
            
            if (empty($cameraIp)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'IP address ESP32-CAM diperlukan'
                ], 400);
            }
            
            // Periksa apakah URL sudah mengandung http:// atau https://
            if (!preg_match('/^https?:\/\//', $cameraIp)) {
                $statusUrl = "http://{$cameraIp}/status";
            } else {
                // Gunakan URL langsung jika sudah termasuk protokol
                $statusUrl = "{$cameraIp}/status";
            }
            
            Log::info('ESP32CAM Proxy Status URL: ' . $statusUrl);
            
            $response = Http::timeout(10)->get($statusUrl);
            
            if ($response->successful()) {
                return response($response->body(), 200)
                    ->header('Content-Type', 'application/json');
            }
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengakses status ESP32-CAM. Status: ' . $response->status(),
                'camera_ip' => $cameraIp
            ], 500);
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM proxy status error: " . $e->getMessage());
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengakses status: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Proxy untuk stream video dari ESP32-CAM
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     */
    public function proxyStream(Request $request)
    {
        $cameraIp = $request->query('ip');
        
        if (empty($cameraIp)) {
            return response()->json([
                'status' => 'error',
                'message' => 'IP address ESP32-CAM diperlukan'
            ], 400);
        }
        
        // Periksa apakah URL sudah mengandung http:// atau https://
        if (!preg_match('/^https?:\/\//', $cameraIp)) {
            $streamUrl = "http://{$cameraIp}/stream";
        } else {
            // Gunakan URL langsung jika sudah termasuk protokol
            $streamUrl = "{$cameraIp}/stream";
        }
        
        Log::info('ESP32CAM Proxy Stream URL: ' . $streamUrl);
        
        // Menggunakan streaming response untuk meneruskan MJPEG stream
        return response()->stream(function() use ($streamUrl) {
            $ch = curl_init($streamUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // Langsung kirim output ke browser
            curl_exec($ch);
            curl_close($ch);
        }, 200, [
            'Content-Type' => 'multipart/x-mixed-replace; boundary=frame',
            'Cache-Control' => 'no-cache, private',
            'Connection' => 'close',
            'Pragma' => 'no-cache'
        ]);
    }
    
    /**
     * Proxy untuk pengaturan kamera ESP32-CAM
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function proxySettings(Request $request)
    {
        try {
            $cameraIp = $request->query('ip');
            $resolution = $request->query('resolution');
            $quality = $request->query('quality');
            
            if (empty($cameraIp)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'IP address ESP32-CAM diperlukan'
                ], 400);
            }
            
            // Periksa apakah URL sudah mengandung http:// atau https://
            if (!preg_match('/^https?:\/\//', $cameraIp)) {
                $baseUrl = "http://{$cameraIp}";
            } else {
                // Gunakan URL langsung jika sudah termasuk protokol
                $baseUrl = $cameraIp;
            }
            
            // Bangun URL dengan parameter yang diperlukan
            $settingsUrl = "{$baseUrl}/camera-settings";
            $params = [];
            
            if (!empty($resolution)) {
                $params['resolution'] = $resolution;
            }
            
            if (!empty($quality)) {
                $params['quality'] = $quality;
            }
            
            if (!empty($params)) {
                $settingsUrl .= '?' . http_build_query($params);
            }
            
            Log::info('ESP32CAM Proxy Settings URL: ' . $settingsUrl);
            
            $response = Http::timeout(10)->get($settingsUrl);
            
            if ($response->successful()) {
                return response($response->body(), 200)
                    ->header('Content-Type', 'application/json');
            }
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengubah pengaturan ESP32-CAM. Status: ' . $response->status(),
                'camera_ip' => $cameraIp
            ], 500);
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM proxy settings error: " . $e->getMessage());
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengubah pengaturan: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Proxy untuk endpoint capture dari ESP32-CAM
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function proxyCapture(Request $request)
    {
        try {
            $cameraIp = $request->query('ip');
            
            if (empty($cameraIp)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'IP address ESP32-CAM diperlukan'
                ], 400);
            }
            
            // Periksa apakah URL sudah mengandung http:// atau https://
            if (!preg_match('/^https?:\/\//', $cameraIp)) {
                $captureUrl = "http://{$cameraIp}/capture";
            } else {
                // Gunakan URL langsung jika sudah termasuk protokol
                $captureUrl = "{$cameraIp}/capture";
            }
            
            Log::info('ESP32CAM Proxy Capture URL: ' . $captureUrl);
            
            $response = Http::timeout(15)->get($captureUrl);
            
            if ($response->successful()) {
                // Jika hanya ingin menampilkan gambar tanpa menyimpan
                if ($request->query('display_only') === 'true') {
                    return response($response->body(), 200)
                        ->header('Content-Type', 'image/jpeg');
                }
                
                // Jika ingin menyimpan gambar
                $uploadDir = 'esp32cam/';
                
                // Pastikan direktori ada di storage/app/public
                if (!Storage::disk('public')->exists($uploadDir)) {
                    Storage::disk('public')->makeDirectory($uploadDir);
                }
                
                // Buat nama file unik dengan timestamp
                $filename = 'esp32cam_' . Carbon::now()->format('Ymd_His') . '.jpg';
                $fullPath = $uploadDir . $filename;
                
                // Simpan gambar menggunakan Laravel Storage
                Storage::disk('public')->put($fullPath, $response->body());
                
                // Mengatur waktu file agar sesuai dengan waktu pengambilan saat ini
                $now = time();
                $filePath = storage_path('app/public/' . $fullPath);
                @touch($filePath, $now);
                
                return response()->json([
                    'status' => 'success',
                    'message' => 'Gambar berhasil diambil dan disimpan',
                    'filename' => $filename,
                    'path' => $fullPath,
                    'time' => Carbon::now()->format('Y-m-d H:i:s')
                ]);
            }
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengambil gambar dari ESP32-CAM. Status: ' . $response->status(),
                'camera_ip' => $cameraIp
            ], 500);
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM proxy capture error: " . $e->getMessage());
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal mengambil gambar: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Proxy untuk menghentikan streaming dari ESP32-CAM
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function proxyStopStream(Request $request)
    {
        try {
            $cameraIp = $request->query('ip');
            
            if (empty($cameraIp)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'IP address ESP32-CAM diperlukan'
                ], 400);
            }
            
            // Periksa apakah URL sudah mengandung http:// atau https://
            if (!preg_match('/^https?:\/\//', $cameraIp)) {
                $stopStreamUrl = "http://{$cameraIp}/stopstream";
            } else {
                // Gunakan URL langsung jika sudah termasuk protokol
                $stopStreamUrl = "{$cameraIp}/stopstream";
            }
            
            Log::info('ESP32CAM Proxy Stop Stream URL: ' . $stopStreamUrl);
            
            $response = Http::timeout(5)->get($stopStreamUrl);
            
            if ($response->successful()) {
                return response()->json([
                    'status' => 'success',
                    'message' => 'Streaming dihentikan'
                ]);
            }
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal menghentikan streaming. Status: ' . $response->status(),
                'camera_ip' => $cameraIp
            ], 500);
            
        } catch (\Exception $e) {
            Log::error("ESP32-CAM proxy stop stream error: " . $e->getMessage());
            
            return response()->json([
                'status' => 'error',
                'message' => 'Gagal menghentikan streaming: ' . $e->getMessage()
            ], 500);
        }
    }
}
