<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Events\Achievements\AchievementCheckRequested;
use App\Http\Controllers\Controller;
use App\Models\Artwork;
use App\Notifications\ArtworkLikedNotification;
use App\Services\FollowService;
use App\Services\Activity\UserActivityService;
use App\Services\ArtworkStatsService;
use App\Services\UserStatsService;
use App\Services\XPService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

final class ArtworkInteractionController extends Controller
{
    public function bookmark(Request $request, int $artworkId): JsonResponse
    {
        $this->toggleSimple(
            request: $request,
            table: 'artwork_bookmarks',
            keyColumns: ['user_id', 'artwork_id'],
            keyValues: ['user_id' => (int) $request->user()->id, 'artwork_id' => $artworkId],
            insertPayload: ['created_at' => now(), 'updated_at' => now()],
            requiredTable: 'artwork_bookmarks'
        );

        return response()->json($this->statusPayload((int) $request->user()->id, $artworkId));
    }

    public function favorite(Request $request, int $artworkId): JsonResponse
    {
        $state = $request->boolean('state', true);

        $changed = $this->toggleSimple(
            request: $request,
            table: 'artwork_favourites',
            keyColumns: ['user_id', 'artwork_id'],
            keyValues: ['user_id' => (int) $request->user()->id, 'artwork_id' => $artworkId],
            insertPayload: ['created_at' => now(), 'updated_at' => now()],
            requiredTable: 'artwork_favourites'
        );

        $this->syncArtworkStats($artworkId);

        // Update creator's favorites_received_count
        $creatorId = (int) DB::table('artworks')->where('id', $artworkId)->value('user_id');
        if ($creatorId) {
            $svc = app(UserStatsService::class);
            if ($state && $changed) {
                $svc->incrementFavoritesReceived($creatorId);
                $svc->setLastActiveAt((int) $request->user()->id);

                // Record activity event (new favourite only)
                try {
                    \App\Models\ActivityEvent::record(
                        actorId:    (int) $request->user()->id,
                        type:       \App\Models\ActivityEvent::TYPE_FAVORITE,
                        targetType: \App\Models\ActivityEvent::TARGET_ARTWORK,
                        targetId:   $artworkId,
                    );
                } catch (\Throwable) {}

                try {
                    app(UserActivityService::class)->logFavourite((int) $request->user()->id, $artworkId);
                } catch (\Throwable) {}
            } elseif (! $state && $changed) {
                $svc->decrementFavoritesReceived($creatorId);
            }
        }

        return response()->json($this->statusPayload((int) $request->user()->id, $artworkId));
    }

    public function like(Request $request, int $artworkId): JsonResponse
    {
        $changed = $this->toggleSimple(
            request: $request,
            table: 'artwork_likes',
            keyColumns: ['user_id', 'artwork_id'],
            keyValues: ['user_id' => (int) $request->user()->id, 'artwork_id' => $artworkId],
            insertPayload: ['created_at' => now(), 'updated_at' => now()],
            requiredTable: 'artwork_likes'
        );

        $this->syncArtworkStats($artworkId);

        if ($request->boolean('state', true) && $changed) {
            $creatorId = (int) DB::table('artworks')->where('id', $artworkId)->value('user_id');
            $actorId = (int) $request->user()->id;
            try {
                app(UserActivityService::class)->logLike($actorId, $artworkId);
            } catch (\Throwable) {}
            if ($creatorId > 0 && $creatorId !== $actorId) {
                app(XPService::class)->awardArtworkLikeReceived($creatorId, $artworkId, $actorId);
                $creator = \App\Models\User::query()->find($creatorId);
                $artwork = Artwork::query()->find($artworkId);
                if ($creator && $artwork) {
                    $creator->notify(new ArtworkLikedNotification($artwork, $request->user()));
                }
                event(new AchievementCheckRequested($creatorId));
            }
        }

        return response()->json($this->statusPayload((int) $request->user()->id, $artworkId));
    }

    public function report(Request $request, int $artworkId): JsonResponse
    {
        if (! Schema::hasTable('artwork_reports')) {
            return response()->json(['message' => 'Reporting unavailable'], 422);
        }

        $data = $request->validate([
            'reason' => ['nullable', 'string', 'max:1000'],
        ]);

        DB::table('artwork_reports')->updateOrInsert(
            [
                'artwork_id' => $artworkId,
                'reporter_user_id' => (int) $request->user()->id,
            ],
            [
                'reason' => trim((string) ($data['reason'] ?? '')) ?: null,
                'reported_at' => now(),
                'created_at' => now(),
                'updated_at' => now(),
            ]
        );

        return response()->json(['ok' => true, 'reported' => true]);
    }

    public function follow(Request $request, int $userId): JsonResponse
    {
        $actorId = (int) $request->user()->id;

        if ($actorId === $userId) {
            return response()->json(['message' => 'Cannot follow yourself'], 422);
        }

        $svc = app(FollowService::class);
        $state = $request->has('state')
            ? $request->boolean('state')
            : ! $request->isMethod('delete');

        if ($state) {
            $svc->follow($actorId, $userId);
        } else {
            $svc->unfollow($actorId, $userId);
        }

        return response()->json([
            'ok'              => true,
            'is_following'    => $state,
            'followers_count' => $svc->followersCount($userId),
        ]);
    }

    /**
     * POST /api/artworks/{id}/share — record a share event (Phase 2 tracking).
     */
    public function share(Request $request, int $artworkId): JsonResponse
    {
        $data = $request->validate([
            'platform' => ['required', 'string', 'in:facebook,twitter,pinterest,email,copy,embed,native'],
        ]);

        if (Schema::hasTable('artwork_shares')) {
            DB::table('artwork_shares')->insert([
                'artwork_id' => $artworkId,
                'user_id'    => $request->user()?->id,
                'platform'   => $data['platform'],
                'created_at' => now(),
            ]);

            $this->syncArtworkStats($artworkId);
        }

        return response()->json(['ok' => true]);
    }

    private function toggleSimple(
        Request $request,
        string $table,
        array $keyColumns,
        array $keyValues,
        array $insertPayload,
        string $requiredTable
    ): bool {
        if (! Schema::hasTable($requiredTable)) {
            abort(422, 'Interaction unavailable');
        }

        $state = $request->boolean('state', true);

        $query = DB::table($table);
        foreach ($keyColumns as $column) {
            $query->where($column, $keyValues[$column]);
        }

        if ($state) {
            if (! $query->exists()) {
                DB::table($table)->insert(array_merge($keyValues, $insertPayload));
                return true;
            }
        } else {
            return $query->delete() > 0;
        }

        return false;
    }

    private function syncArtworkStats(int $artworkId): void
    {
        app(ArtworkStatsService::class)->syncEngagementCounts($artworkId);
    }

    private function statusPayload(int $viewerId, int $artworkId): array
    {
        $isBookmarked = Schema::hasTable('artwork_bookmarks')
            ? DB::table('artwork_bookmarks')->where('user_id', $viewerId)->where('artwork_id', $artworkId)->exists()
            : false;

        $isFavorited = Schema::hasTable('artwork_favourites')
            ? DB::table('artwork_favourites')->where('user_id', $viewerId)->where('artwork_id', $artworkId)->exists()
            : false;

        $isLiked = Schema::hasTable('artwork_likes')
            ? DB::table('artwork_likes')->where('user_id', $viewerId)->where('artwork_id', $artworkId)->exists()
            : false;

        $favorites = Schema::hasTable('artwork_favourites')
            ? (int) DB::table('artwork_favourites')->where('artwork_id', $artworkId)->count()
            : 0;

        $bookmarks = Schema::hasTable('artwork_bookmarks')
            ? (int) DB::table('artwork_bookmarks')->where('artwork_id', $artworkId)->count()
            : 0;

        $likes = Schema::hasTable('artwork_likes')
            ? (int) DB::table('artwork_likes')->where('artwork_id', $artworkId)->count()
            : 0;

        return [
            'ok' => true,
            'is_bookmarked' => $isBookmarked,
            'is_favorited' => $isFavorited,
            'is_liked' => $isLiked,
            'stats' => [
                'bookmarks' => $bookmarks,
                'favorites' => $favorites,
                'likes' => $likes,
            ],
        ];
    }
}
