<?php

namespace App\Http\Controllers\Api;

use Carbon\CarbonImmutable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use App\Support\ImageHelper;

class EventPublicController extends BaseController
{
    private function toPublicUrl(?string $path): ?string
    {
        if (! $path) return null;
        // Already absolute URL
        if (str_starts_with($path, 'http://') || str_starts_with($path, 'https://')) return $path;
        // Already a public storage URL
        if (str_starts_with($path, '/storage/')) return $path;
        if (str_starts_with($path, 'storage/')) return '/' . $path;

        // Common relative paths stored in DB (e.g. 'photos/...', 'thumbnails/...', 'events/...')
        if (str_starts_with($path, 'photos/') || str_starts_with($path, 'thumbnails/') || str_starts_with($path, 'events/')) {
            return Storage::url($path);
        }

        // Absolute server paths pointing into storage/app/public (Linux/Windows)
        $normalized = str_replace('\\', '/', $path);
        $needle = '/storage/app/public/';
        if (str_contains($normalized, $needle)) {
            $rel = substr($normalized, strpos($normalized, $needle) + strlen($needle));
            return '/storage/' . ltrim($rel, '/');
        }

        return $path; // fallback as-is
    }
    public function event(string $slug)
    {
        $event = DB::table('events')->where('slug', $slug)->first([
            'id', 'slug', 'name', 'default_locale', 'created_at', 'updated_at'
        ]);
        if (! $event) {
            return response()->json(['error' => ['code' => 'not_found', 'message' => 'Event not found']], 404);
        }

        return response()->json([
            'id' => $event->id,
            'slug' => $event->slug,
            'name' => $event->name,
            'default_locale' => $event->default_locale,
            'created_at' => $event->created_at,
            'updated_at' => $event->updated_at,
        ])->header('Cache-Control', 'no-store');
    }

    public function stats(string $slug)
    {
        $event = DB::table('events')->where('slug', $slug)->first(['id']);
        if (! $event) {
            return response()->json(['error' => ['code' => 'not_found', 'message' => 'Event not found']], 404);
        }

        $eventId = $event->id;

        // Approximate online guests as distinct recent uploaders in last 10 minutes.
        $tenMinutesAgo = CarbonImmutable::now()->subMinutes(10);
        $onlineGuests = DB::table('photos')
            ->where('event_id', $eventId)
            ->where('created_at', '>=', $tenMinutesAgo)
            ->distinct('guest_name')
            ->count('guest_name');

        // Tasks solved as number of photos linked to a task (proxy metric).
        $tasksSolved = DB::table('photos')->where('event_id', $eventId)->whereNotNull('task_id')->count();

        $latestPhotoAt = DB::table('photos')->where('event_id', $eventId)->max('created_at');

        $payload = [
            'online_guests' => $onlineGuests,
            'tasks_solved' => $tasksSolved,
            'latest_photo_at' => $latestPhotoAt,
        ];

        $etag = sha1(json_encode($payload));
        $reqEtag = request()->headers->get('If-None-Match');
        if ($reqEtag && $reqEtag === $etag) {
            return response('', 304);
        }

        return response()->json($payload)
            ->header('Cache-Control', 'no-store')
            ->header('ETag', $etag);
    }

    public function photos(Request $request, string $slug)
    {
        $event = DB::table('events')->where('slug', $slug)->first(['id']);
        if (! $event) {
            return response()->json(['error' => ['code' => 'not_found', 'message' => 'Event not found']], 404);
        }
        $eventId = $event->id;

        $since = $request->query('since');
        $query = DB::table('photos')
            ->select(['id', 'file_path', 'thumbnail_path', 'likes_count', 'emotion_id', 'task_id', 'created_at'])
            ->where('event_id', $eventId)
            ->orderByDesc('created_at')
            ->limit(60);

        if ($since) {
            $query->where('created_at', '>', $since);
        }

        $rows = $query->get()->map(function ($r) {
            $r->file_path = $this->toPublicUrl((string)($r->file_path ?? ''));
            $r->thumbnail_path = $this->toPublicUrl((string)($r->thumbnail_path ?? ''));
            return $r;
        });
        $latestPhotoAt = DB::table('photos')->where('event_id', $eventId)->max('created_at');
        $payload = [
            'data' => $rows,
            'latest_photo_at' => $latestPhotoAt,
        ];
        $etag = sha1(json_encode([$since, $latestPhotoAt]));
        $reqEtag = request()->headers->get('If-None-Match');
        if ($reqEtag && $reqEtag === $etag) {
            return response('', 304);
        }
        return response()->json($payload)
            ->header('Cache-Control', 'no-store')
            ->header('ETag', $etag)
            ->header('Last-Modified', (string)$latestPhotoAt);
    }

    public function photo(int $id)
    {
        $row = DB::table('photos')
            ->select(['id', 'event_id', 'file_path', 'thumbnail_path', 'likes_count', 'emotion_id', 'task_id', 'created_at'])
            ->where('id', $id)
            ->first();
        if (! $row) {
            return response()->json(['error' => ['code' => 'not_found', 'message' => 'Photo not found']], 404);
        }
        $row->file_path = $this->toPublicUrl((string)($row->file_path ?? ''));
        $row->thumbnail_path = $this->toPublicUrl((string)($row->thumbnail_path ?? ''));
        return response()->json($row)->header('Cache-Control', 'no-store');
    }

    public function like(Request $request, int $id)
    {
        $deviceId = (string) $request->header('X-Device-Id', 'anon');
        $deviceId = substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $deviceId), 0, 64);
        if ($deviceId === '') {
            $deviceId = 'anon';
        }

        $photo = DB::table('photos')->where('id', $id)->first(['id', 'event_id']);
        if (! $photo) {
            return response()->json(['error' => ['code' => 'not_found', 'message' => 'Photo not found']], 404);
        }

        // Idempotent like per device
        $exists = DB::table('photo_likes')->where('photo_id', $id)->where('guest_name', $deviceId)->exists();
        if ($exists) {
            $count = (int) DB::table('photos')->where('id', $id)->value('likes_count');
            return response()->json(['liked' => true, 'likes_count' => $count]);
        }

        DB::beginTransaction();
        try {
            DB::table('photo_likes')->insert([
                'photo_id' => $id,
                'guest_name' => $deviceId,
                'ip_address' => 'device',
                'created_at' => now(),
            ]);
            DB::table('photos')->where('id', $id)->update([
                'likes_count' => DB::raw('likes_count + 1'),
                'updated_at' => now(),
            ]);
            DB::commit();
        } catch (\Throwable $e) {
            DB::rollBack();
            Log::warning('like failed', ['error' => $e->getMessage()]);
        }

        $count = (int) DB::table('photos')->where('id', $id)->value('likes_count');

        return response()->json(['liked' => true, 'likes_count' => $count]);
    }

    public function upload(Request $request, string $slug)
    {
        $event = DB::table('events')->where('slug', $slug)->first(['id']);
        if (! $event) {
            return response()->json(['error' => ['code' => 'not_found', 'message' => 'Event not found']], 404);
        }

        $deviceId = (string) $request->header('X-Device-Id', 'anon');
        $deviceId = substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $deviceId), 0, 64) ?: 'anon';

        // Per-device cap per event (MVP: 50)
        $deviceCount = DB::table('photos')->where('event_id', $event->id)->where('guest_name', $deviceId)->count();
        if ($deviceCount >= 50) {
            return response()->json(['error' => ['code' => 'limit_reached', 'message' => 'Upload-Limit erreicht']], 429);
        }

        $validated = $request->validate([
            'photo' => ['required', 'image', 'max:6144'], // 6 MB
            'emotion_id' => ['nullable', 'integer'],
            'task_id' => ['nullable', 'integer'],
            'guest_name' => ['nullable', 'string', 'max:255'],
        ]);

        $file = $validated['photo'];
        $path = Storage::disk('public')->putFile("events/{$event->id}/photos", $file);
        $url = Storage::url($path);

        // Generate thumbnail (JPEG) under photos/thumbs
        $baseName = pathinfo($path, PATHINFO_FILENAME);
        $thumbRel = "events/{$event->id}/photos/thumbs/{$baseName}_thumb.jpg";
        $thumbPath = ImageHelper::makeThumbnailOnDisk('public', $path, $thumbRel, 640, 82);
        $thumbUrl = $thumbPath ? Storage::url($thumbPath) : $url;

        $id = DB::table('photos')->insertGetId([
            'event_id' => $event->id,
            'emotion_id' => $validated['emotion_id'] ?? null,
            'task_id' => $validated['task_id'] ?? null,
            'guest_name' => $validated['guest_name'] ?? $deviceId,
            'file_path' => $url,
            'thumbnail_path' => $thumbUrl,
            'likes_count' => 0,
            'is_featured' => 0,
            'metadata' => null,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return response()->json([
            'id' => $id,
            'file_path' => $url,
            'thumbnail_path' => $thumbUrl,
        ], 201);
    }
}
