<?php

namespace App\Services\Roadmap;

use App\Models\Admin\AdminRoadmapMilestone;
use App\Models\Admin\AdminRoadmapPlan;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class RoadmapPlanService
{
    public function getPlans(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = AdminRoadmapPlan::query()
            ->withCount('milestones')
            ->withTrashed();

        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                    ->orWhere('description', 'like', "%{$search}%");
            });
        }

        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        if (! empty($filters['category'])) {
            $query->where('category', $filters['category']);
        }

        if (! empty($filters['priority'])) {
            $query->where('priority', $filters['priority']);
        }

        if (! empty($filters['phase'])) {
            $query->where('phase', $filters['phase']);
        }

        if (isset($filters['trashed'])) {
            if ($filters['trashed'] === 'only') {
                $query->onlyTrashed();
            }
        }

        $sortBy = $filters['sort_by'] ?? 'sort_order';
        $sortDirection = $filters['sort_direction'] ?? 'asc';
        $query->orderBy($sortBy, $sortDirection)->orderBy('id', 'desc');

        return $query->paginate($perPage);
    }

    public function getTimelineData(?string $phase = null): array
    {
        $query = AdminRoadmapPlan::query()
            ->whereIn('status', [
                AdminRoadmapPlan::STATUS_PLANNED,
                AdminRoadmapPlan::STATUS_IN_PROGRESS,
                AdminRoadmapPlan::STATUS_COMPLETED,
                AdminRoadmapPlan::STATUS_DELAYED,
            ])
            ->withCount('milestones')
            ->orderBy('phase')
            ->orderBy('sort_order')
            ->orderBy('start_date');

        if ($phase) {
            $query->where('phase', $phase);
        }

        $plans = $query->get();
        $grouped = [];

        foreach (AdminRoadmapPlan::getPhases() as $key => $label) {
            $phasePlans = $plans->where('phase', $key);
            if ($phase && $key !== $phase) {
                continue;
            }
            $grouped[$key] = [
                'label' => $label,
                'plans' => $phasePlans->values(),
            ];
        }

        return $grouped;
    }

    public function getStats(): array
    {
        return [
            'total' => AdminRoadmapPlan::count(),
            'planned' => AdminRoadmapPlan::status(AdminRoadmapPlan::STATUS_PLANNED)->count(),
            'in_progress' => AdminRoadmapPlan::status(AdminRoadmapPlan::STATUS_IN_PROGRESS)->count(),
            'completed' => AdminRoadmapPlan::status(AdminRoadmapPlan::STATUS_COMPLETED)->count(),
            'delayed' => AdminRoadmapPlan::status(AdminRoadmapPlan::STATUS_DELAYED)->count(),
            'cancelled' => AdminRoadmapPlan::status(AdminRoadmapPlan::STATUS_CANCELLED)->count(),
        ];
    }

    public function getDashboardSummary(): array
    {
        $stats = $this->getStats();
        $timeline = $this->getTimelineData();

        return [
            'stats' => $stats,
            'timeline' => $timeline,
        ];
    }

    public function getPlanById(int $id, bool $withTrashed = false): ?AdminRoadmapPlan
    {
        $query = AdminRoadmapPlan::query()
            ->with(['milestones' => function ($q) {
                $q->orderBy('sort_order')->orderBy('id');
            }, 'milestones.assignee', 'creator', 'updater'])
            ->withCount('milestones');

        if ($withTrashed) {
            $query->withTrashed();
        }

        return $query->find($id);
    }

    public function createPlan(array $data): AdminRoadmapPlan
    {
        $data['created_by'] = auth()->id();

        return AdminRoadmapPlan::create($data);
    }

    public function updatePlan(int $id, array $data): bool
    {
        $plan = AdminRoadmapPlan::findOrFail($id);
        $data['updated_by'] = auth()->id();

        return $plan->update($data);
    }

    public function deletePlan(int $id): bool
    {
        $plan = AdminRoadmapPlan::findOrFail($id);
        $plan->deleted_by = auth()->id();
        $plan->save();

        return $plan->delete();
    }

    public function restorePlan(int $id): bool
    {
        $plan = AdminRoadmapPlan::onlyTrashed()->findOrFail($id);
        $plan->deleted_by = null;

        return $plan->restore();
    }

    public function changeStatus(int $id, string $status): AdminRoadmapPlan
    {
        $plan = AdminRoadmapPlan::findOrFail($id);
        $plan->status = $status;
        $plan->updated_by = auth()->id();
        $plan->save();

        return $plan;
    }

    public function recalculateProgress(int $planId): void
    {
        $plan = AdminRoadmapPlan::findOrFail($planId);
        $total = $plan->milestones()->count();

        if ($total === 0) {
            return;
        }

        $completed = $plan->milestones()
            ->where('status', AdminRoadmapMilestone::STATUS_COMPLETED)
            ->count();

        $plan->progress = (int) round(($completed / $total) * 100);
        $plan->save();
    }
}
