<?php

namespace App\Services\ProjectManagement;

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

class IssueService
{
    /**
     * 이슈 목록 조회 (페이지네이션)
     */
    public function getIssues(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = AdminPmIssue::query()
            ->with(['project', 'task', 'creator'])
            ->withTrashed();

        // 프로젝트 필터
        if (! empty($filters['project_id'])) {
            $query->where('project_id', $filters['project_id']);
        }

        // 작업 필터
        if (! empty($filters['task_id'])) {
            $query->where('task_id', $filters['task_id']);
        }

        // 검색 필터
        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['type'])) {
            $query->where('type', $filters['type']);
        }

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

        // 열린 이슈만 필터
        if (! empty($filters['open_only']) && $filters['open_only']) {
            $query->open();
        }

        // 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 getIssuesByProject(int $projectId): Collection
    {
        return AdminPmIssue::query()
            ->where('project_id', $projectId)
            ->with(['task', 'creator'])
            ->latest()
            ->get();
    }

    /**
     * 작업별 이슈 목록
     */
    public function getIssuesByTask(int $taskId): Collection
    {
        return AdminPmIssue::query()
            ->where('task_id', $taskId)
            ->with(['creator'])
            ->latest()
            ->get();
    }

    /**
     * 특정 이슈 조회
     */
    public function getIssueById(int $id, bool $withTrashed = false): ?AdminPmIssue
    {
        $query = AdminPmIssue::query()
            ->with(['project', 'task', 'creator', 'updater']);

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

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

    /**
     * 이슈 생성
     */
    public function createIssue(array $data): AdminPmIssue
    {
        $data['created_by'] = auth()->id();

        return AdminPmIssue::create($data);
    }

    /**
     * 이슈 수정
     */
    public function updateIssue(int $id, array $data): bool
    {
        $issue = AdminPmIssue::findOrFail($id);

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

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

    /**
     * 이슈 삭제 (Soft Delete)
     */
    public function deleteIssue(int $id): bool
    {
        $issue = AdminPmIssue::findOrFail($id);

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

        return $issue->delete();
    }

    /**
     * 이슈 복원
     */
    public function restoreIssue(int $id): bool
    {
        $issue = AdminPmIssue::onlyTrashed()->findOrFail($id);

        $issue->deleted_by = null;

        return $issue->restore();
    }

    /**
     * 이슈 영구 삭제
     */
    public function forceDeleteIssue(int $id): bool
    {
        return AdminPmIssue::withTrashed()->findOrFail($id)->forceDelete();
    }

    /**
     * 이슈 상태 변경
     */
    public function changeStatus(int $id, string $status): AdminPmIssue
    {
        $issue = AdminPmIssue::findOrFail($id);

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

        return $issue;
    }

    /**
     * 이슈 긴급 토글
     */
    public function toggleUrgent(int $id): AdminPmIssue
    {
        $issue = AdminPmIssue::findOrFail($id);

        $issue->is_urgent = ! $issue->is_urgent;
        $issue->updated_by = auth()->id();
        $issue->save();

        return $issue;
    }

    /**
     * 다중 이슈 상태 일괄 변경
     */
    public function bulkChangeStatus(array $issueIds, string $status): int
    {
        return AdminPmIssue::whereIn('id', $issueIds)
            ->update([
                'status' => $status,
                'updated_by' => auth()->id(),
                'updated_at' => now(),
            ]);
    }

    /**
     * 다중 이슈 타입 일괄 변경
     */
    public function bulkChangeType(array $issueIds, string $type): int
    {
        return AdminPmIssue::whereIn('id', $issueIds)
            ->update([
                'type' => $type,
                'updated_by' => auth()->id(),
                'updated_at' => now(),
            ]);
    }

    /**
     * 다중 이슈 작업 연결 일괄 변경
     */
    public function bulkLinkToTask(array $issueIds, ?int $taskId): int
    {
        return AdminPmIssue::whereIn('id', $issueIds)
            ->update([
                'task_id' => $taskId,
                'updated_by' => auth()->id(),
                'updated_at' => now(),
            ]);
    }

    /**
     * 다중 이슈 일괄 삭제
     */
    public function bulkDelete(array $issueIds): int
    {
        AdminPmIssue::whereIn('id', $issueIds)
            ->update([
                'deleted_by' => auth()->id(),
            ]);

        return AdminPmIssue::whereIn('id', $issueIds)->delete();
    }

    /**
     * 다중 이슈 일괄 복원
     */
    public function bulkRestore(array $issueIds): int
    {
        return AdminPmIssue::onlyTrashed()
            ->whereIn('id', $issueIds)
            ->update([
                'deleted_by' => null,
                'deleted_at' => null,
            ]);
    }

    /**
     * 이슈 통계 (프로젝트별)
     */
    public function getIssueStatsByProject(int $projectId): array
    {
        return [
            'total' => AdminPmIssue::where('project_id', $projectId)->count(),
            'open' => AdminPmIssue::where('project_id', $projectId)
                ->status(AdminPmIssue::STATUS_OPEN)->count(),
            'in_progress' => AdminPmIssue::where('project_id', $projectId)
                ->status(AdminPmIssue::STATUS_IN_PROGRESS)->count(),
            'resolved' => AdminPmIssue::where('project_id', $projectId)
                ->status(AdminPmIssue::STATUS_RESOLVED)->count(),
            'closed' => AdminPmIssue::where('project_id', $projectId)
                ->status(AdminPmIssue::STATUS_CLOSED)->count(),
            'by_type' => [
                'bug' => AdminPmIssue::where('project_id', $projectId)
                    ->type(AdminPmIssue::TYPE_BUG)->count(),
                'feature' => AdminPmIssue::where('project_id', $projectId)
                    ->type(AdminPmIssue::TYPE_FEATURE)->count(),
                'improvement' => AdminPmIssue::where('project_id', $projectId)
                    ->type(AdminPmIssue::TYPE_IMPROVEMENT)->count(),
            ],
        ];
    }

    /**
     * 전체 이슈 통계
     */
    public function getIssueStats(): array
    {
        return [
            '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(),
            'trashed' => AdminPmIssue::onlyTrashed()->count(),
            'by_type' => [
                'bug' => AdminPmIssue::type(AdminPmIssue::TYPE_BUG)->count(),
                'feature' => AdminPmIssue::type(AdminPmIssue::TYPE_FEATURE)->count(),
                'improvement' => AdminPmIssue::type(AdminPmIssue::TYPE_IMPROVEMENT)->count(),
            ],
        ];
    }

    /**
     * 열린 이슈 목록 (대시보드용)
     */
    public function getOpenIssues(?int $projectId = null, int $limit = 10): Collection
    {
        $query = AdminPmIssue::open()
            ->with(['project', 'task', 'creator'])
            ->latest();

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

        return $query->limit($limit)->get();
    }
}
