<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ShortlinkController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'nullable|string|max:255',
            'url' => 'required|url|max:2000',
            'alias' => 'nullable|string|max:100|alpha_dash|unique:shortlinks,custom_alias',
            'description' => 'nullable|string|max:500',
            'og_image' => 'nullable|url|max:2000',
        ]);

        // Always fetch meta data for description and image
        $metaData = $this->fetchMetaData($validated['url']);

        // Generate unique short code
        $shortCode = $this->generateShortCode();
        
        // Determine final title: User input (if not empty) > Meta Title > Default
        // Use trim to check if title is actually filled with content
        $userTitle = isset($validated['title']) ? trim($validated['title']) : '';
        $finalTitle = !empty($userTitle) ? $userTitle : ($metaData['title'] ?? 'Shortlink');

        // Smart fallback for description: Manual input > Auto-fetch > null
        $userDescription = isset($validated['description']) ? trim($validated['description']) : '';
        $finalDescription = !empty($userDescription) ? $userDescription : ($metaData['description'] ?? null);

        // Smart fallback for image: Manual input > Auto-fetch > null
        $userImage = isset($validated['og_image']) ? trim($validated['og_image']) : '';
        $finalImage = !empty($userImage) ? $userImage : ($metaData['image'] ?? null);

        // Create shortlink
        $shortlink = auth()->user()->shortlinks()->create([
            'title' => $finalTitle,
            'description' => $finalDescription,
            'og_image' => $finalImage,
            'original_url' => $validated['url'],
            'short_code' => $shortCode,
            'custom_alias' => $validated['alias'] ?? null,
            'type' => 'url',
            'is_active' => true,
        ]);

        // Send Notification
        auth()->user()->notify(new \App\Notifications\LinkCreatedNotification($shortlink));

        return response()->json([
            'success' => true,
            'message' => 'Shortlink berhasil dibuat!',
            'data' => [
                'id' => $shortlink->id,
                'title' => $shortlink->title,
                'description' => $shortlink->description,
                'og_image' => $shortlink->og_image,
                'short_url' => $shortlink->getShortUrl(),
                'short_code' => $shortlink->custom_alias ?: $shortlink->short_code,
                'original_url' => $shortlink->original_url,
                'created_at' => $shortlink->created_at->format('d M Y'),
            ]
        ]);
    }

    public function update(Request $request, $id)
    {
        $shortlink = auth()->user()->shortlinks()->findOrFail($id);

        $validated = $request->validate([
            'title' => 'nullable|string|max:255',
            'original_url' => 'required|url|max:2000',
            'is_active' => 'boolean',
        ]);

        $shortlink->update([
            'title' => $validated['title'],
            'original_url' => $validated['original_url'],
            'is_active' => $validated['is_active'] ?? $shortlink->is_active,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Shortlink berhasil diperbarui!',
            'data' => [
                'id' => $shortlink->id,
                'title' => $shortlink->title ?: '-',
                'original_url' => $shortlink->original_url,
            ]
        ]);
    }

    /**
     * Fetch meta data from URL (API endpoint for manual fetch)
     */
    public function fetchMeta(Request $request)
    {
        $request->validate([
            'url' => 'required|url',
        ]);

        $metaData = $this->fetchMetaData($request->url);

        return response()->json([
            'success' => true,
            'data' => $metaData,
        ]);
    }

    /**
     * Refresh metadata for an existing shortlink
     */
    public function refreshMeta($id)
    {
        $shortlink = auth()->user()->shortlinks()->findOrFail($id);
        
        // Fetch fresh metadata from the original URL
        $metaData = $this->fetchMetaData($shortlink->original_url);
        
        // Update shortlink with new metadata
        $shortlink->update([
            'description' => $metaData['description'] ?? $shortlink->description,
            'og_image' => $metaData['image'] ?? $shortlink->og_image,
        ]);
        
        return response()->json([
            'success' => true,
            'message' => 'Metadata berhasil diperbarui!',
            'data' => [
                'title' => $shortlink->title,
                'description' => $shortlink->description,
                'og_image' => $shortlink->og_image,
            ]
        ]);
    }

    public function stats($id)
    {
        $link = auth()->user()->shortlinks()->findOrFail($id);

        // Calculate Top Referrers
        $rawReferrers = $link->clicks()
            ->select('referer_url', \DB::raw('count(*) as total'))
            ->whereNotNull('referer_url')
            ->groupBy('referer_url')
            ->orderByDesc('total')
            ->limit(100)
            ->get();

        $referrerStats = $rawReferrers->groupBy(function($item) {
                return parse_url($item->referer_url, PHP_URL_HOST) ?: 'Direct/Other';
            })
            ->map(function($group, $domain) {
                return [
                    'source' => $domain, 
                    'count' => $group->sum('total')
                ];
            })
            ->sortByDesc('count')
            ->values()
            ->take(5);

        // Helper for top stats
        $getTop = function($col) use ($link) {
            return $link->clicks()->selectRaw("$col, COUNT(*) as count")->groupBy($col)->orderByDesc('count')->first();
        };

        $topDevice = $getTop('device_type');
        $topOS = $getTop('os');
        $topCountry = $getTop('country');
        $topCity = $getTop('city');
        
        $latestClick = $link->clicks()->latest('clicked_at')->first();
        $latestRef = ($latestClick && $latestClick->referer_url) ? parse_url($latestClick->referer_url, PHP_URL_HOST) : 'Direct/None';

        return response()->json([
            'referrer_summary' => $referrerStats,
            'latest_referrer' => $latestRef,
            'top_device' => $topDevice ? $topDevice->device_type : '-',
            'top_device_count' => $topDevice ? $topDevice->count : 0,
            'top_os' => $topOS ? $topOS->os : '-',
            'top_os_count' => $topOS ? $topOS->count : 0,
            'top_country' => $topCountry ? $topCountry->country : '-',
            'top_country_count' => $topCountry ? $topCountry->count : 0,
            'top_city' => $topCity ? $topCity->city : '-',
            'top_city_count' => $topCity ? $topCity->count : 0,
        ]);
    }

    public function index(Request $request)
    {
        $query = auth()->user()->shortlinks()
            ->where('type', 'url');

        if ($request->has('search') && $request->search != '') {
            $search = $request->search;
            $query->where(function($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                  ->orWhere('short_code', 'like', "%{$search}%")
                  ->orWhere('custom_alias', 'like', "%{$search}%")
                  ->orWhere('original_url', 'like', "%{$search}%");
            });
        }

        // Filter Status
        if ($request->has('status') && in_array($request->status, ['active', 'inactive'])) {
            $query->where('is_active', $request->status === 'active');
        }

        // Lightweight Stats (Only Counts)
        $shortlinks = $query->withCount([
            'clicks as clicks_today_count' => function ($query) {
                $query->whereDate('clicked_at', \Carbon\Carbon::today());
            },
            'clicks as clicks_1_hour_count' => function ($query) {
                $query->where('clicked_at', '>=', \Carbon\Carbon::now()->subHour());
            },
            'clicks as clicks_7_days_count' => function ($query) {
                $query->where('clicked_at', '>=', \Carbon\Carbon::now()->subDays(7));
            },
            'clicks as clicks_30_days_count' => function ($query) {
                $query->where('clicked_at', '>=', \Carbon\Carbon::now()->subDays(30));
            },
            'clicks as unique_clicks_count' => function ($query) {
                $query->select(\DB::raw('count(distinct ip_address)'));
            }
        ])
        ->with(['clicks' => function($q) {
            $q->latest('clicked_at')->limit(1)->select('shortlink_id', 'clicked_at');
        }]);

        // Sorting
        $sort = $request->get('sort', 'latest');
        switch ($sort) {
            case 'oldest':
                $query->oldest();
                break;
            case 'most_clicks':
                $query->orderBy('total_clicks', 'desc');
                break;
            case 'latest':
            default:
                $query->latest();
                break;
        }

        $shortlinks = $query->paginate(10);
        
        // Append query params to pagination
        $shortlinks->appends($request->only(['search', 'status', 'sort']));

        return view('dashboard.shortlinks.index', compact('shortlinks'));
    }

    public function destroy($id)
    {
        $shortlink = auth()->user()->shortlinks()->findOrFail($id);
        $shortlink->delete();

        return response()->json([
            'success' => true,
            'message' => 'Shortlink berhasil dihapus!'
        ]);
    }

    private function generateShortCode($length = 6)
    {
        $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        
        do {
            $code = '';
            for ($i = 0; $i < $length; $i++) {
                $code .= $characters[rand(0, strlen($characters) - 1)];
            }
        } while (\App\Models\Shortlink::where('short_code', $code)->exists());

        return $code;
    }

    /**
     * Fetch meta data (title, description, image) from URL
     */
    private function fetchMetaData($url)
    {
        $metaData = [
            'title' => null,
            'description' => null,
            'image' => null,
        ];

        try {
            // Use cURL with increased timeout to avoid hanging
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
            curl_setopt($ch, CURLOPT_TIMEOUT, 15);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            
            // Masquerade as a real Chrome browser
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36');
            
            // Add comprehensive headers to mimic browser
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                'Accept-Language: id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
                'Cache-Control: no-cache',
                'Pragma: no-cache',
                'Upgrade-Insecure-Requests: 1',
                'Sec-Fetch-Dest: document',
                'Sec-Fetch-Mode: navigate',
                'Sec-Fetch-Site: none',
                'Sec-Fetch-User: ?1',
                'Connection: keep-alive'
            ]);
            
            // Add fake referer to look organic
            curl_setopt($ch, CURLOPT_REFERER, 'https://www.google.com/');
            
            curl_setopt($ch, CURLOPT_ENCODING, ''); // Accept all encodings (gzip, etc)
            
            $html = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $curlError = curl_error($ch);
            curl_close($ch);

            if ($curlError) {
                \Log::warning("cURL error for {$url}: {$curlError}");
                return $metaData;
            }

            if ($httpCode !== 200 || !$html) {
                \Log::warning("HTTP {$httpCode} for {$url}");
                return $metaData;
            }

            // Extract Title with multiple fallbacks
            // 1. Try og:title (property attribute)
            if (preg_match('/<meta\s+property=["\']og:title["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['title'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }
            // 2. Try og:title (name attribute - some sites use this)
            elseif (preg_match('/<meta\s+name=["\']og:title["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['title'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }
            // 3. Try twitter:title
            elseif (preg_match('/<meta\s+(?:name|property)=["\']twitter:title["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['title'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }
            // 4. Fallback to regular title tag
            elseif (preg_match('/<title[^>]*>(.*?)<\/title>/is', $html, $matches)) {
                $metaData['title'] = html_entity_decode(trim($matches[1]), ENT_QUOTES, 'UTF-8');
            }

            // Extract Description with multiple fallbacks
            // 1. Try og:description (property attribute)
            if (preg_match('/<meta\s+property=["\']og:description["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['description'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }
            // 2. Try og:description (name attribute)
            elseif (preg_match('/<meta\s+name=["\']og:description["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['description'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }
            // 3. Try twitter:description
            elseif (preg_match('/<meta\s+(?:name|property)=["\']twitter:description["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['description'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }
            // 4. Fallback to meta description
            elseif (preg_match('/<meta\s+name=["\']description["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $metaData['description'] = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8');
            }

            // Extract Image with multiple fallbacks
            // 1. Try og:image (property attribute)
            if (preg_match('/<meta\s+property=["\']og:image["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $imageUrl = $matches[1];
            }
            // 2. Try og:image (name attribute)
            elseif (preg_match('/<meta\s+name=["\']og:image["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $imageUrl = $matches[1];
            }
            // 3. Try twitter:image
            elseif (preg_match('/<meta\s+(?:name|property)=["\']twitter:image["\']\s+content=["\'](.*?)["\']/i', $html, $matches)) {
                $imageUrl = $matches[1];
            }

            // Process image URL if found
            if (isset($imageUrl) && !empty($imageUrl)) {
                // Make relative URLs absolute
                if (!filter_var($imageUrl, FILTER_VALIDATE_URL)) {
                    $parsedUrl = parse_url($url);
                    $baseUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'];
                    
                    // Handle different relative URL formats
                    if (strpos($imageUrl, '//') === 0) {
                        // Protocol-relative URL
                        $imageUrl = $parsedUrl['scheme'] . ':' . $imageUrl;
                    } elseif (strpos($imageUrl, '/') === 0) {
                        // Absolute path
                        $imageUrl = $baseUrl . $imageUrl;
                    } else {
                        // Relative path
                        $imageUrl = $baseUrl . '/' . $imageUrl;
                    }
                }
                $metaData['image'] = $imageUrl;
            }

            // If no title found, use domain name
            if (empty($metaData['title'])) {
                $parsedUrl = parse_url($url);
                $metaData['title'] = $parsedUrl['host'] ?? 'Shortlink';
            }

            // Trim and limit length
            $metaData['title'] = substr(trim($metaData['title']), 0, 255);
            if ($metaData['description']) {
                $metaData['description'] = substr(trim($metaData['description']), 0, 500);
            }

            // Log successful fetch for debugging
            \Log::info("Meta data fetched for {$url}", [
                'has_title' => !empty($metaData['title']),
                'has_description' => !empty($metaData['description']),
                'has_image' => !empty($metaData['image']),
            ]);

        } catch (\Exception $e) {
            // If fetch fails, return empty meta data
            \Log::error('Failed to fetch meta data from URL: ' . $url . ' - Error: ' . $e->getMessage());
        }

        return $metaData;
    }
}
