<?php

namespace App\Services\ProjectManagement;

use App\Models\Admin\AdminPmIssue;
use App\Models\Admin\AdminPmProject;
use App\Models\Admin\AdminPmTask;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;

class ProjectService
{
    /**
     * 프로젝트 목록 조회 (페이지네이션)
     */
    public function getProjects(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = AdminPmProject::query()
            ->withCount(['tasks', 'issues'])
            ->withTrashed();

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

        // 상태 필터
        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        // Soft Delete 필터
        if (isset($filters['trashed'])) {
            if ($filters['trashed'] === 'only') {
                $query->onlyTrashed();
            } elseif ($filters['trashed'] === 'with') {
                $query->withTrashed();
            }
        }

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

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

    /**
     * 활성 프로젝트 목록 (드롭다운용)
     */
    public function getActiveProjects(): Collection
    {
        return AdminPmProject::query()
            ->active()
            ->orderBy('name')
            ->get(['id', 'name', 'status']);
    }

    /**
     * 특정 프로젝트 조회
     */
    public function getProjectById(int $id, bool $withTrashed = false): ?AdminPmProject
    {
        $query = AdminPmProject::query()
            ->with(['tasks' => function ($q) {
                $q->orderBy('sort_order')->orderBy('id');
            }, 'issues' => function ($q) {
                $q->latest();
            }])
            ->withCount(['tasks', 'issues']);

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

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

    /**
     * 프로젝트 생성
     */
    public function createProject(array $data): AdminPmProject
    {
        $data['created_by'] = auth()->id();

        return AdminPmProject::create($data);
    }

    /**
     * 프로젝트 수정
     */
    public function updateProject(int $id, array $data): bool
    {
        $project = AdminPmProject::findOrFail($id);

        $data['updated_by'] = auth()->id();

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

    /**
     * 프로젝트 삭제 (Soft Delete)
     */
    public function deleteProject(int $id): bool
    {
        $project = AdminPmProject::findOrFail($id);

        $project->deleted_by = auth()->id();
        $project->save();

        return $project->delete();
    }

    /**
     * 프로젝트 복원
     */
    public function restoreProject(int $id): bool
    {
        $project = AdminPmProject::onlyTrashed()->findOrFail($id);

        $project->deleted_by = null;

        return $project->restore();
    }

    /**
     * 프로젝트 영구 삭제
     */
    public function forceDeleteProject(int $id): bool
    {
        $project = AdminPmProject::withTrashed()->findOrFail($id);

        // 관련 작업/이슈 삭제 (cascade 설정됨)
        return $project->forceDelete();
    }

    /**
     * 프로젝트 통계
     */
    public function getProjectStats(): array
    {
        return [
            'total' => AdminPmProject::count(),
            'active' => AdminPmProject::where('status', AdminPmProject::STATUS_ACTIVE)->count(),
            'completed' => AdminPmProject::where('status', AdminPmProject::STATUS_COMPLETED)->count(),
            'on_hold' => AdminPmProject::where('status', AdminPmProject::STATUS_ON_HOLD)->count(),
            'trashed' => AdminPmProject::onlyTrashed()->count(),
        ];
    }

    /**
     * 대시보드용 프로젝트 요약
     */
    public function getDashboardSummary(): array
    {
        $today = now()->format('Y-m-d');

        $activeProjects = AdminPmProject::active()
            ->withCount(['tasks', 'issues'])
            ->with(['tasks' => function ($q) {
                $q->select('id', 'project_id', 'status');
            }, 'issues' => function ($q) {
                $q->whereIn('status', [AdminPmIssue::STATUS_OPEN, AdminPmIssue::STATUS_IN_PROGRESS]);
            }, 'dailyLogs' => function ($q) use ($today) {
                $q->where('log_date', $today)->with('entries');
            }])
            ->get();

        $taskStats = [
            'total' => AdminPmTask::count(),
            'todo' => AdminPmTask::status(AdminPmTask::STATUS_TODO)->count(),
            'in_progress' => AdminPmTask::status(AdminPmTask::STATUS_IN_PROGRESS)->count(),
            'done' => AdminPmTask::status(AdminPmTask::STATUS_DONE)->count(),
            'overdue' => AdminPmTask::overdue()->count(),
            'due_soon' => AdminPmTask::dueSoon()->count(),
        ];

        $issueStats = [
            'total' => AdminPmIssue::count(),
            'open' => AdminPmIssue::status(AdminPmIssue::STATUS_OPEN)->count(),
            'in_progress' => AdminPmIssue::status(AdminPmIssue::STATUS_IN_PROGRESS)->count(),
            'resolved' => AdminPmIssue::status(AdminPmIssue::STATUS_RESOLVED)->count(),
            'closed' => AdminPmIssue::status(AdminPmIssue::STATUS_CLOSED)->count(),
        ];

        return [
            'projects' => $activeProjects,
            'project_stats' => $this->getProjectStats(),
            'task_stats' => $taskStats,
            'issue_stats' => $issueStats,
        ];
    }

    /**
     * 프로젝트 상태 변경
     */
    public function changeStatus(int $id, string $status): AdminPmProject
    {
        $project = AdminPmProject::findOrFail($id);

        $project->status = $status;
        $project->updated_by = auth()->id();
        $project->save();

        return $project;
    }

    /**
     * 프로젝트 복제
     */
    public function duplicateProject(int $id, ?string $newName = null): AdminPmProject
    {
        $original = AdminPmProject::with(['tasks.issues'])->findOrFail($id);

        $newProject = $original->replicate();
        $newProject->name = $newName ?? $original->name.' (복사본)';
        $newProject->status = AdminPmProject::STATUS_ACTIVE;
        $newProject->created_by = auth()->id();
        $newProject->updated_by = null;
        $newProject->deleted_by = null;
        $newProject->created_at = now();
        $newProject->updated_at = now();
        $newProject->save();

        // 작업 및 이슈 복제 (task_id 매핑 유지)
        foreach ($original->tasks as $task) {
            $newTask = $task->replicate();
            $newTask->project_id = $newProject->id;
            $newTask->status = AdminPmTask::STATUS_TODO;
            $newTask->created_by = auth()->id();
            $newTask->updated_by = null;
            $newTask->deleted_by = null;
            $newTask->created_at = now();
            $newTask->updated_at = now();
            $newTask->save();

            // 해당 작업의 이슈들 복제
            foreach ($task->issues as $issue) {
                $newIssue = $issue->replicate();
                $newIssue->project_id = $newProject->id;
                $newIssue->task_id = $newTask->id;
                $newIssue->status = AdminPmIssue::STATUS_OPEN;
                $newIssue->created_by = auth()->id();
                $newIssue->updated_by = null;
                $newIssue->deleted_by = null;
                $newIssue->created_at = now();
                $newIssue->updated_at = now();
                $newIssue->save();
            }
        }

        return $newProject->load('tasks.issues');
    }
}
