<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreMeetingRequest;
use App\Http\Resources\MeetingActionItemResource;
use App\Http\Resources\MeetingResource;
use App\Http\Resources\TaskResource;
use App\Models\ActionItem;
use App\Models\Blocker;
use App\Models\Decision;
use App\Models\Meeting;
use App\Models\MeetingActionItem;
use App\Models\MeetingType;
use App\Models\Task;
use App\Models\User;
use App\Services\NotificationService;
use App\Services\ResourceAccessService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MeetingController extends Controller
{
    public function __construct(
        protected NotificationService $notificationService,
        protected ResourceAccessService $resourceAccess,
    ) {}

    public function index(Request $request): JsonResponse
    {
        try {
            $query = $this->resourceAccess->meetings($request->user())
                ->with(['project', 'sprint', 'type', 'creator', 'participants']);

            if ($request->filled('project_id')) {
                $query->where('project_id', $request->project_id);
            }
            if ($request->filled('date_from')) {
                $query->whereDate('date', '>=', $request->date_from);
            }
            if ($request->filled('date_to')) {
                $query->whereDate('date', '<=', $request->date_to);
            }
            if ($request->filled('meeting_type')) {
                $query->where('meeting_type', $request->meeting_type);
            }
            if ($request->filled('sprint_id')) {
                $query->where('sprint_id', $request->sprint_id);
            }
            if ($request->filled('status')) {
                $query->where('status', $request->status);
            }

            $perPage = $request->input('per_page', 15);
            $sortBy = $request->input('sort_by', 'date');
            $sortDir = $request->input('sort_dir', 'desc');
            $meetings = $query->orderBy($sortBy, $sortDir)->paginate($perPage);

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

    public function show(Meeting $meeting): JsonResponse
    {
        try {
            $meeting->load([
                'project', 'sprint', 'type', 'creator', 'owner', 'facilitator',
                'participants', 'actionItems.assignee', 'structuredDecisions',
                'structuredActionItems', 'blockers', 'files',
            ]);

            return response()->json([
                'success' => true,
                'data' => new MeetingResource($meeting),
                'message' => 'اطلاعات جلسه',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت اطلاعات جلسه',
            ], 500);
        }
    }

    public function store(StoreMeetingRequest $request): JsonResponse
    {
        try {
            $data = $request->validated();
            if (! empty($data['project_id'])) {
                abort_unless(
                    $this->resourceAccess->projects($request->user())->whereKey($data['project_id'])->exists(),
                    403,
                    'شما به پروژه انتخاب‌شده دسترسی ندارید.'
                );
            }
            $data['created_by'] = $request->user()->id;
            $data['owner_id'] ??= $request->user()->id;
            $meeting = Meeting::create($data);
            $meeting->load(['project', 'sprint', 'type', 'creator', 'owner']);

            return response()->json([
                'success' => true,
                'data' => new MeetingResource($meeting),
                'message' => 'جلسه با موفقیت ایجاد شد',
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در ایجاد جلسه',
            ], 500);
        }
    }

    public function update(Request $request, Meeting $meeting): JsonResponse
    {
        try {
            $data = $request->validate([
                'title' => 'sometimes|required|string|max:255',
                'date' => 'sometimes|required|date',
                'start_time' => 'nullable',
                'end_time' => 'nullable',
                'meeting_type' => 'sometimes|required|string|max:50',
                'meeting_type_id' => 'nullable|exists:meeting_types,id',
                'project_id' => 'nullable|exists:projects,id',
                'sprint_id' => 'nullable|exists:sprints,id',
                'status' => 'sometimes|string|in:draft,scheduled,in_progress,completed,cancelled,postponed',
                'location' => 'nullable|string',
                'meeting_link' => 'nullable|url',
                'objective' => 'nullable|string',
                'agenda' => 'nullable|string',
                'notes' => 'nullable|string',
                'summary' => 'nullable|string',
                'decisions' => 'nullable|string',
                'owner_id' => 'nullable|exists:users,id',
                'facilitator_id' => 'nullable|exists:users,id',
                'reminder_minutes' => 'nullable|integer|min:0|max:10080',
                'recurrence_rule' => 'nullable|array',
            ]);
            if (isset($data['project_id'])) {
                abort_unless(
                    $this->resourceAccess->projects($request->user())->whereKey($data['project_id'])->exists(),
                    403,
                    'شما به پروژه انتخاب‌شده دسترسی ندارید.'
                );
            }

            $meeting->update(collect($data)->only([
                'title', 'project_id', 'sprint_id', 'date', 'start_time', 'end_time',
                'meeting_type', 'meeting_type_id', 'status', 'location', 'meeting_link',
                'objective', 'agenda', 'notes', 'summary', 'decisions', 'owner_id',
                'facilitator_id', 'reminder_minutes', 'recurrence_rule',
            ])->all());
            $meeting->load(['project', 'sprint', 'type', 'creator', 'owner', 'facilitator']);

            return response()->json([
                'success' => true,
                'data' => new MeetingResource($meeting->fresh()),
                'message' => 'جلسه به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی جلسه',
            ], 500);
        }
    }

    public function destroy(Meeting $meeting): JsonResponse
    {
        try {
            $meeting->delete();

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

    public function addParticipant(Request $request, Meeting $meeting): JsonResponse
    {
        try {
            $request->validate(['user_id' => 'required|exists:users,id']);
            $meeting->participants()->syncWithoutDetaching([$request->user_id]);

            $this->notificationService->create(
                $request->user_id,
                'meeting_assigned',
                [
                    'meeting_id' => $meeting->id,
                    'project_id' => $meeting->project_id,
                    'url' => '/meetings',
                    'notifiable_type' => 'App\\Models\\Meeting',
                    'notifiable_id' => $meeting->id,
                ],
                "شما به جلسه {$meeting->title} اضافه شدید"
            );

            return response()->json([
                'success' => true,
                'message' => 'شرکت‌کننده اضافه شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در اضافه کردن شرکت‌کننده',
            ], 500);
        }
    }

    public function removeParticipant(Meeting $meeting, User $user): JsonResponse
    {
        try {
            $meeting->participants()->detach($user->id);

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

    public function addActionItem(Request $request, Meeting $meeting): JsonResponse
    {
        try {
            $request->validate([
                'title' => 'required|string|max:255',
                'assigned_to' => 'nullable|exists:users,id',
                'due_date' => 'nullable|date',
            ]);

            $actionItem = $meeting->actionItems()->create([
                'title' => $request->title,
                'assigned_to' => $request->assigned_to,
                'due_date' => $request->due_date,
                'is_completed' => false,
            ]);
            $actionItem->load('assignee');

            if ($actionItem->assigned_to) {
                $this->notificationService->create(
                    $actionItem->assigned_to,
                    'meeting_action_assigned',
                    [
                        'meeting_id' => $meeting->id,
                        'action_item_id' => $actionItem->id,
                        'url' => '/meetings',
                        'notifiable_type' => 'App\\Models\\MeetingActionItem',
                        'notifiable_id' => $actionItem->id,
                    ],
                    "اقدام جلسه {$actionItem->title} به شما اختصاص داده شد"
                );
            }

            return response()->json([
                'success' => true,
                'data' => new MeetingActionItemResource($actionItem),
                'message' => 'ایتم اقدام ایجاد شد',
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در ایجاد ایتم اقدام',
            ], 500);
        }
    }

    public function updateActionItem(Request $request, Meeting $meeting, MeetingActionItem $actionItem): JsonResponse
    {
        try {
            $request->validate([
                'title' => 'sometimes|required|string|max:255',
                'assigned_to' => 'nullable|exists:users,id',
                'due_date' => 'nullable|date',
                'is_completed' => 'nullable|boolean',
            ]);

            $actionItem->update($request->only(['title', 'assigned_to', 'due_date', 'is_completed']));
            $actionItem->load('assignee');

            return response()->json([
                'success' => true,
                'data' => new MeetingActionItemResource($actionItem->fresh()),
                'message' => 'ایتم اقدام به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی ایتم اقدام',
            ], 500);
        }
    }

    public function convertActionItemToTask(Request $request, Meeting $meeting, MeetingActionItem $actionItem): JsonResponse
    {
        try {
            $request->validate([
                'project_id' => 'required|exists:projects,id',
            ]);
            abort_unless(
                $this->resourceAccess->projects($request->user())->whereKey($request->project_id)->exists(),
                403,
                'شما به پروژه انتخاب‌شده دسترسی ندارید.'
            );

            $task = Task::create([
                'title' => $actionItem->title,
                'project_id' => $request->project_id,
                'assignee_id' => $actionItem->assigned_to,
                'reporter_id' => $request->user()->id,
                'created_by' => $request->user()->id,
                'due_date' => $actionItem->due_date,
                'status' => 'todo',
            ]);

            $actionItem->update(['converted_to_task_id' => $task->id]);
            $task->load(['project', 'assignee']);

            return response()->json([
                'success' => true,
                'data' => new TaskResource($task),
                'message' => 'ایتم اقدام به وظیفه تبدیل شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در تبدیل ایتم اقدام به وظیفه',
            ], 500);
        }
    }

    public function workspace(Meeting $meeting): JsonResponse
    {
        $meeting->load([
            'project', 'sprint', 'type', 'creator', 'owner', 'facilitator',
            'participants', 'actionItems.assignee', 'structuredDecisions',
            'structuredActionItems', 'blockers', 'files',
        ]);

        return response()->json([
            'success' => true,
            'data' => new MeetingResource($meeting),
            'message' => 'فضای کاری جلسه',
        ]);
    }

    public function start(Request $request, Meeting $meeting): JsonResponse
    {
        if (! in_array($meeting->status, ['draft', 'scheduled', 'postponed'], true)) {
            return response()->json(['success' => false, 'message' => 'این جلسه قابل شروع نیست'], 422);
        }

        $meeting->update(['status' => 'in_progress', 'started_at' => now()]);

        return response()->json([
            'success' => true,
            'data' => new MeetingResource($meeting->fresh()),
            'message' => 'جلسه شروع شد',
        ]);
    }

    public function complete(Request $request, Meeting $meeting): JsonResponse
    {
        $data = $request->validate([
            'summary' => 'nullable|string',
            'force' => 'nullable|boolean',
        ]);
        if ($meeting->status !== 'in_progress') {
            return response()->json(['success' => false, 'message' => 'فقط جلسه در حال برگزاری قابل تکمیل است'], 422);
        }
        if (blank($data['summary'] ?? $meeting->summary) && ! $request->boolean('force')) {
            return response()->json(['success' => false, 'message' => 'برای تکمیل جلسه، خلاصه را ثبت کنید یا تأیید ویژه بدهید.'], 422);
        }

        $meeting->update([
            'status' => 'completed',
            'completed_at' => now(),
            'summary' => $data['summary'] ?? $meeting->summary,
        ]);

        return response()->json([
            'success' => true,
            'data' => new MeetingResource($meeting->fresh()),
            'message' => 'جلسه تکمیل شد',
        ]);
    }

    public function addDecision(Request $request, Meeting $meeting): JsonResponse
    {
        $data = $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'status' => 'nullable|in:proposed,pending,approved,rejected,reversed,superseded',
            'owner_id' => 'nullable|exists:users,id',
            'rationale' => 'nullable|string',
            'impact' => 'nullable|string',
        ]);

        $decision = Decision::create($data + [
            'meeting_id' => $meeting->id,
            'sprint_id' => $meeting->sprint_id,
            'project_id' => $meeting->project_id,
            'created_by' => $request->user()->id,
        ]);

        return response()->json(['success' => true, 'data' => $decision, 'message' => 'تصمیم ثبت شد'], 201);
    }

    public function addStructuredActionItem(Request $request, Meeting $meeting): JsonResponse
    {
        $data = $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'owner_id' => 'required|exists:users,id',
            'due_date' => 'required|date',
            'priority' => 'nullable|in:low,medium,high,urgent',
        ]);

        $item = ActionItem::create($data + [
            'meeting_id' => $meeting->id,
            'sprint_id' => $meeting->sprint_id,
            'project_id' => $meeting->project_id,
            'created_by' => $request->user()->id,
        ]);

        return response()->json(['success' => true, 'data' => $item, 'message' => 'اقدام ثبت شد'], 201);
    }

    public function addBlocker(Request $request, Meeting $meeting): JsonResponse
    {
        $data = $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'severity' => 'nullable|in:low,medium,high,critical',
            'owner_id' => 'nullable|exists:users,id',
            'task_id' => 'nullable|exists:tasks,id',
            'due_date' => 'nullable|date',
        ]);

        $blocker = Blocker::create($data + [
            'meeting_id' => $meeting->id,
            'sprint_id' => $meeting->sprint_id,
            'project_id' => $meeting->project_id,
            'raised_by' => $request->user()->id,
        ]);

        return response()->json(['success' => true, 'data' => $blocker, 'message' => 'مانع ثبت شد'], 201);
    }

    public function types(): JsonResponse
    {
        return response()->json([
            'success' => true,
            'data' => MeetingType::where('is_active', true)->orderBy('name')->get(),
            'message' => 'انواع جلسه',
        ]);
    }
}
