<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\FileResource;
use App\Models\Comment;
use App\Models\File;
use App\Models\Meeting;
use App\Models\Project;
use App\Models\Task;
use App\Services\ResourceAccessService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class FileController extends Controller
{
    public function __construct(private readonly ResourceAccessService $resourceAccess) {}

    public function index(Request $request): JsonResponse
    {
        try {
            $query = $this->resourceAccess->files($request->user())->with('user');

            if ($request->filled('fileable_type')) {
                $query->where('fileable_type', $request->fileable_type);
            }
            if ($request->filled('fileable_id')) {
                $query->where('fileable_id', $request->fileable_id);
            }

            $perPage = $request->input('per_page', 15);
            $files = $query->orderBy('created_at', 'desc')->paginate($perPage);

            return response()->json([
                'success' => true,
                'data' => FileResource::collection($files),
                'meta' => [
                    'current_page' => $files->currentPage(),
                    'last_page' => $files->lastPage(),
                    'per_page' => $files->perPage(),
                    'total' => $files->total(),
                ],
                'message' => 'لیست فایل‌ها',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت فایل‌ها',
            ], 500);
        }
    }

    public function store(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'file' => 'required|file|max:10240|mimes:pdf,doc,docx,xls,xlsx,ppt,pptx,txt,csv,jpg,jpeg,png,webp,zip',
                'fileable_type' => 'nullable|string|in:App\\Models\\Project,App\\Models\\Task,App\\Models\\Comment,App\\Models\\Meeting',
                'fileable_id' => 'nullable|integer',
                'project_id' => 'nullable|exists:projects,id',
            ]);

            $fileableType = $request->fileable_type;
            $fileableId = $request->fileable_id;

            if ($request->filled('project_id')) {
                $fileableType = Project::class;
                $fileableId = $request->project_id;
            }

            if (! $fileableType || ! $fileableId) {
                return response()->json([
                    'success' => false,
                    'message' => 'انتخاب محل آپلود فایل الزامی است',
                ], 422);
            }

            $allowed = match ($fileableType) {
                Project::class => $this->resourceAccess->projects($request->user())->whereKey($fileableId)->exists(),
                Task::class => $this->resourceAccess->tasks($request->user())->whereKey($fileableId)->exists(),
                Meeting::class => $this->resourceAccess->meetings($request->user())->whereKey($fileableId)->exists(),
                Comment::class => $this->resourceAccess->comments($request->user())->whereKey($fileableId)->exists(),
                default => false,
            };
            abort_unless($allowed, 403, 'شما به محل انتخاب‌شده برای فایل دسترسی ندارید.');

            $uploadedFile = $request->file('file');
            $originalName = $uploadedFile->getClientOriginalName();
            $extension = strtolower($uploadedFile->getClientOriginalExtension());
            $name = Str::uuid()->toString().($extension ? ".{$extension}" : '');
            $path = $uploadedFile->storeAs('files', $name, 'local');

            $file = File::create([
                'name' => $name,
                'original_name' => $originalName,
                'path' => $path,
                'mime_type' => $uploadedFile->getMimeType(),
                'size' => $uploadedFile->getSize(),
                'fileable_id' => $fileableId,
                'fileable_type' => $fileableType,
                'user_id' => $request->user()->id,
            ]);
            $file->load('user');

            return response()->json([
                'success' => true,
                'data' => new FileResource($file),
                'message' => 'فایل با موفقیت آپلود شد',
            ], 201);
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در آپلود فایل',
            ], 500);
        }
    }

    public function show(File $file): JsonResponse
    {
        try {
            $disk = Storage::disk('local')->exists($file->path) ? 'local' : 'public';

            if (! Storage::disk($disk)->exists($file->path)) {
                return response()->json([
                    'success' => false,
                    'message' => 'فایل یافت نشد',
                ], 404);
            }

            $filePath = Storage::disk($disk)->path($file->path);

            return response()->download($filePath, $file->original_name);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت فایل',
            ], 500);
        }
    }

    public function destroy(File $file): JsonResponse
    {
        try {
            foreach (['local', 'public'] as $disk) {
                if (Storage::disk($disk)->exists($file->path)) {
                    Storage::disk($disk)->delete($file->path);
                    break;
                }
            }

            $file->delete();

            return response()->json([
                'success' => true,
                'message' => 'فایل حذف شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در حذف فایل',
            ], 500);
        }
    }
}
