<?php

namespace App\Repositories;

use App\Models\RateMyPay;
use App\Models\Rating;
use App\Models\PostComment;
use App\Models\PostLike;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class RateMyPayRepository
{
    public function getAllPosts(array $filters = []): LengthAwarePaginator
    {
        $query = RateMyPay::with(['user', 'jobExperience', 'ratings', 'comments.user'])
            ->withCount(['likes', 'comments', 'ratings'])
            ->latest();

        // Apply filters
        if (isset($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }

        if (isset($filters['search'])) {
            $query->where(function ($q) use ($filters) {
                $q->where('content', 'like', "%{$filters['search']}%")
                  ->orWhereHas('jobExperience', function ($q) use ($filters) {
                      $q->where('job_title', 'like', "%{$filters['search']}%")
                        ->orWhere('company_name', 'like', "%{$filters['search']}%");
                  });
            });
        }

        return $query->paginate(15);
    }

    public function findById(int $id): ?RateMyPay
    {
        return RateMyPay::with([
            'user', 
            'jobExperience', 
            'ratings.user',
            'comments.user',
            'comments.replies.user',
            'likes.user'
        ])
        ->withCount(['likes', 'comments', 'ratings'])
        ->find($id);
    }

    public function createPost(array $data): RateMyPay
    {
        return DB::transaction(function () use ($data) {
            // Handle file upload if present
            if (isset($data['payslip']) && $data['payslip']->isValid()) {
                $data['payslip_path'] = $this->storePayslip($data['payslip']);
            }
            // Remove payslip from data array to prevent mass assignment issues
            $postData = array_diff_key($data, array_flip(['payslip', 'community_ids']));
            
            $post = RateMyPay::create($postData);
            
            return $post;
        });
    }

    public function addPostToCommunities(RateMyPay $post, array $communityIds): void
    {
        DB::transaction(function () use ($post, $communityIds) {
            $post->communities()->attach($communityIds);
        });
    }

    public function deletePayslip(string $filePath): bool
    {
        if (Storage::disk('public')->exists($filePath)) {
            return Storage::disk('public')->delete($filePath);
        }
        return false;
    }

    public function deletePost(RateMyPay $rateMyPay): bool
    {
        return DB::transaction(function () use ($rateMyPay) {
            // Delete associated file if exists
            if ($rateMyPay->payslip_path) {
                Storage::disk('public')->delete($rateMyPay->payslip_path);
            }

            return $rateMyPay->delete();
        });
    }

    public function addRating(RateMyPay $rateMyPay, array $data): Rating
    {
        return DB::transaction(function () use ($rateMyPay, $data) {
            $rating = Rating::updateOrCreate(
                [
                    'rate_my_pay_id' => $rateMyPay->id,
                    'user_id' => $data['user_id'],
                ],
                [
                    'rating' => $data['rating'],
                    'salary' => $data['salary'] ?? null,
                ]
            );

            // Update post rating stats
            $rateMyPay->updateRatingStats();

            return $rating;
        });
    }

    public function removeRating(RateMyPay $rateMyPay, int $userId): bool
    {
        return DB::transaction(function () use ($rateMyPay, $userId) {
            $deleted = Rating::where('rate_my_pay_id', $rateMyPay->id)
                ->where('user_id', $userId)
                ->delete();

            if ($deleted) {
                $rateMyPay->updateRatingStats();
            }

            return $deleted;
        });
    }

    public function addComment(RateMyPay $rateMyPay, array $data): PostComment
    {
        return DB::transaction(function () use ($rateMyPay, $data) {
            $comment = PostComment::create([
                'rate_my_pay_id' => $rateMyPay->id,
                'user_id' => $data['user_id'],
                'parent_id' => $data['parent_id'] ?? null,
                'content' => $data['content'],
            ]);

            // Increment comments count
            $rateMyPay->increment('comments_count');

            return $comment;
        });
    }

    public function updateComment(PostComment $comment, array $data): bool
    {
        return $comment->update([
            'content' => $data['content'],
        ]);
    }

    public function deleteComment(PostComment $comment): bool
    {
        return DB::transaction(function () use ($comment) {
            // Decrement post comments count
            $comment->rateMyPay->decrement('comments_count');

            return $comment->delete();
        });
    }

    public function toggleLike(RateMyPay $rateMyPay, int $userId): bool
    {
        return DB::transaction(function () use ($rateMyPay, $userId) {
            $like = PostLike::where('user_id', $userId)
                ->where('likeable_id', $rateMyPay->id)
                ->where('likeable_type', RateMyPay::class)
                ->first();

            if ($like) {
                $like->delete();
                $rateMyPay->decrement('likes_count');
                return false; // Unlike
            } else {
                PostLike::create([
                    'user_id' => $userId,
                    'likeable_id' => $rateMyPay->id,
                    'likeable_type' => RateMyPay::class,
                ]);
                $rateMyPay->increment('likes_count');
                return true; // Like
            }
        });
    }

    public function toggleCommentLike(PostComment $comment, int $userId): bool
    {
        return DB::transaction(function () use ($comment, $userId) {
            $like = PostLike::where('user_id', $userId)
                ->where('likeable_id', $comment->id)
                ->where('likeable_type', PostComment::class)
                ->first();

            if ($like) {
                $like->delete();
                $comment->decrementLikesCount();
                return false; // Unlike
            } else {
                PostLike::create([
                    'user_id' => $userId,
                    'likeable_id' => $comment->id,
                    'likeable_type' => PostComment::class,
                ]);
                $comment->incrementLikesCount();
                return true; // Like
            }
        });
    }

    public function getUserRating(RateMyPay $rateMyPay, int $userId): ?Rating
    {
        return Rating::where('rate_my_pay_id', $rateMyPay->id)
            ->where('user_id', $userId)
            ->first();
    }

    public function canUserRate(RateMyPay $rateMyPay, int $userId): bool
    {
        return !$this->getUserRating($rateMyPay, $userId);
    }

    public function getPostsByUser(int $userId, array $filters = []): LengthAwarePaginator
    {
        $query = RateMyPay::where('user_id', $userId)
            ->with(['jobExperience', 'ratings'])
            ->withCount(['likes', 'comments', 'ratings'])
            ->latest();

        if (isset($filters['is_anonymous'])) {
            $query->where('is_anonymous', $filters['is_anonymous']);
        }

        return $query->paginate(10);
    }

    private function storePayslip($file): string
    {
        // Generate unique filename to prevent overwrites
        $filename = 'payslip_' . time() . '_' . Str::random(10) . '.' . $file->getClientOriginalExtension();
        
        // Store in payslips directory with unique name
        return $file->storeAs('payslips', $filename, 'public');
    }
}