<?php

namespace App\Services;

use App\Models\ActionItem;
use App\Models\Meeting;
use App\Models\Project;
use App\Models\Sprint;
use App\Models\Task;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Collection;

class CalendarService
{
    public function __construct(private readonly ResourceAccessService $access) {}

    public function events(User $user, Carbon $from, Carbon $to, array $types = []): Collection
    {
        $enabled = fn (string $type): bool => $types === [] || in_array($type, $types, true);
        $events = collect();

        if ($enabled('meeting')) {
            $this->access->meetings($user)->with(['project:id,title', 'sprint:id,title'])
                ->whereBetween('date', [$from->toDateString(), $to->toDateString()])
                ->orderBy('date')
                ->orderBy('start_time')
                ->get()
                ->each(function (Meeting $meeting) use ($events) {
                    $start = $meeting->date->format('Y-m-d').'T'.($meeting->start_time ?: '00:00:00');
                    $end = $meeting->end_time ? $meeting->date->format('Y-m-d').'T'.$meeting->end_time : null;
                    $events->push([
                        'id' => "meeting-{$meeting->id}",
                        'event_type' => 'meeting',
                        'entity_type' => 'meeting',
                        'entity_id' => $meeting->id,
                        'title' => $meeting->title,
                        'start_at' => $start,
                        'end_at' => $end,
                        'all_day' => ! $meeting->start_time,
                        'status' => $meeting->status ?? 'scheduled',
                        'color_token' => 'info',
                        'project' => $meeting->project?->only(['id', 'title']),
                        'sprint' => $meeting->sprint?->only(['id', 'title']),
                        'preview' => [
                            'زمان' => $meeting->start_time ? substr($meeting->start_time, 0, 5) : 'تمام روز',
                            'مکان' => $meeting->location,
                            'هدف' => $meeting->objective,
                        ],
                        'target_url' => "/meetings/{$meeting->id}/workspace",
                    ]);
                });
        }

        if ($enabled('task')) {
            $this->access->tasks($user)->with('project:id,title')
                ->whereNotNull('due_date')
                ->whereBetween('due_date', [$from->toDateString(), $to->toDateString()])
                ->where('status', '!=', 'done')
                ->orderBy('due_date')
                ->get()
                ->each(fn (Task $task) => $events->push([
                    'id' => "task-{$task->id}",
                    'event_type' => 'task',
                    'entity_type' => 'task',
                    'entity_id' => $task->id,
                    'title' => $task->title,
                    'start_at' => $task->due_date?->format('Y-m-d'),
                    'end_at' => null,
                    'all_day' => true,
                    'status' => $task->status,
                    'color_token' => $task->priority === 'urgent' ? 'danger' : 'warning',
                    'project' => $task->project?->only(['id', 'title']),
                    'sprint' => null,
                    'preview' => [
                        'وضعیت' => $task->status,
                        'اولویت' => $task->priority,
                    ],
                    'target_url' => "/tasks?preview={$task->id}",
                ]));
        }

        if ($enabled('sprint')) {
            $this->access->sprints($user)->with('project:id,title')
                ->where(function ($query) use ($from, $to) {
                    $query->whereBetween('start_date', [$from->toDateString(), $to->toDateString()])
                        ->orWhereBetween('end_date', [$from->toDateString(), $to->toDateString()]);
                })
                ->get()
                ->each(function (Sprint $sprint) use ($events, $from, $to) {
                    foreach ([['start_date', 'شروع'], ['end_date', 'پایان']] as [$field, $label]) {
                        $date = $sprint->{$field};
                        if (! $date || $date->lt($from) || $date->gt($to)) {
                            continue;
                        }
                        $events->push([
                            'id' => "sprint-{$field}-{$sprint->id}",
                            'event_type' => 'sprint',
                            'entity_type' => 'sprint',
                            'entity_id' => $sprint->id,
                            'title' => "{$label} {$sprint->title}",
                            'start_at' => $date->format('Y-m-d'),
                            'end_at' => null,
                            'all_day' => true,
                            'status' => $sprint->status,
                            'color_token' => $field === 'start_date' ? 'success' : 'primary',
                            'project' => $sprint->project?->only(['id', 'title']),
                            'sprint' => $sprint->only(['id', 'title']),
                            'preview' => [
                                'هدف' => $sprint->goal,
                                'ظرفیت' => $sprint->capacity_hours,
                            ],
                            'target_url' => "/sprints/{$sprint->id}/workspace",
                        ]);
                    }
                });
        }

        if ($enabled('project')) {
            $this->access->projects($user)->where(function ($query) use ($from, $to) {
                $query->whereBetween('start_date', [$from->toDateString(), $to->toDateString()])
                    ->orWhereBetween('end_date', [$from->toDateString(), $to->toDateString()]);
            })->get()->each(function (Project $project) use ($events, $from, $to) {
                foreach ([['start_date', 'شروع'], ['end_date', 'پایان']] as [$field, $label]) {
                    $date = $project->{$field};
                    if (! $date || Carbon::parse($date)->lt($from) || Carbon::parse($date)->gt($to)) {
                        continue;
                    }
                    $events->push([
                        'id' => "project-{$field}-{$project->id}",
                        'event_type' => 'project',
                        'entity_type' => 'project',
                        'entity_id' => $project->id,
                        'title' => "{$label} {$project->title}",
                        'start_at' => Carbon::parse($date)->format('Y-m-d'),
                        'end_at' => null,
                        'all_day' => true,
                        'status' => $project->status,
                        'color_token' => 'secondary',
                        'project' => $project->only(['id', 'title']),
                        'sprint' => null,
                        'preview' => ['پیشرفت' => "{$project->progress}%"],
                        'target_url' => "/projects/{$project->id}",
                    ]);
                }
            });
        }

        if ($enabled('action_item') && class_exists(ActionItem::class)) {
            ActionItem::with(['project:id,title', 'sprint:id,title'])
                ->when(! $this->access->canSeeAll($user), function ($query) use ($user) {
                    $query->where(function ($scope) use ($user) {
                        $scope->where('owner_id', $user->id)
                            ->orWhere('created_by', $user->id)
                            ->orWhereIn('project_id', $this->access->projects($user)->select('projects.id'));
                    });
                })
                ->whereNotNull('due_date')
                ->whereBetween('due_date', [$from->toDateString(), $to->toDateString()])
                ->whereNotIn('status', ['completed', 'cancelled'])
                ->get()
                ->each(fn (ActionItem $item) => $events->push([
                    'id' => "action-item-{$item->id}",
                    'event_type' => 'action_item',
                    'entity_type' => 'action_item',
                    'entity_id' => $item->id,
                    'title' => $item->title,
                    'start_at' => $item->due_date?->format('Y-m-d'),
                    'end_at' => null,
                    'all_day' => true,
                    'status' => $item->status,
                    'color_token' => $item->due_date?->isPast() ? 'danger' : 'warning',
                    'project' => $item->project?->only(['id', 'title']),
                    'sprint' => $item->sprint?->only(['id', 'title']),
                    'preview' => ['اولویت' => $item->priority, 'وضعیت' => $item->status],
                    'target_url' => $item->sprint_id ? "/sprints/{$item->sprint_id}/workspace?tab=action-items" : '/meetings',
                ]));
        }

        return $events->sortBy('start_at')->values();
    }
}
