<?php

namespace App\Libs\Services;

use App\Models\Document;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class DocumentService {
    public function list(array $searchData): array {
        $orderDir = $searchData['orderDir'] ? $searchData['orderDir'] : 'asc';
        $userData = Auth::user();

        $hasLegalOpinionsPermission = $userData->member->user_permission_level
            ? $userData->legal_opinion_permission
            : $userData->member->legal_opinions;

        $hasFinanceSubCommitteePermission = $userData->finance_sub_committee_permission;

        $query = Document::full()
            ->select('documents.*', 'document_languages.*')
            ->where('status', 'published')
            ->where(function ($query) {
                $query->whereNull('publish_date')
                    ->orWhere('publish_date', '<=', now()->tz('Europe/Berlin'));
            })->where(function ($query) {
                $query->whereNull('expiration_date')
                    ->orWhere('expiration_date', '>', now()->tz('Europe/Berlin'));
            })
            ->join('committees', 'committees.id', 'documents.committee_id');

            if ($userData->member->member_type !== 'noType') {
                $query->where(function ($query) use ($userData, $hasLegalOpinionsPermission, $hasFinanceSubCommitteePermission) {
                    $query->where('committees.type', 'standard');

                    if ($userData->member->legal_committee) {
                        $query->orWhere('committees.type', 'legalCommittee');
                    }

                    if ($hasLegalOpinionsPermission) {
                        $query->orWhere('committees.type', 'legalOpinions');
                    }

                    if ($hasFinanceSubCommitteePermission) {
                        $query->orWhere('committees.type', 'financeSubCommittee');
                    }
                });
            } else {
                $query->where('committees.type', 'legalOpinions');
            }


        if (!empty($searchData['userFlag'])) {
            $committeeByworkGroupsIds = DB::table('work_groups')
                ->select(DB::raw('DISTINCT(committee_id)'))
                ->whereExists(function ($query) use ($userData) {
                    $query->select(DB::raw(1))->from('user_work_group')
                        ->whereRaw('user_work_group.work_group_id = work_groups.id')
                        ->where('user_work_group.user_id', $userData->id);
                })
                ->pluck('committee_id');

            $committeeIds = DB::table('committees')
                ->select(DB::raw('DISTINCT(id)'))
                ->whereExists(function ($query) use ($userData) {
                    $query->select(DB::raw(1))->from('committee_user')
                        ->whereRaw('committee_user.committee_id = committees.id')
                        ->where('committee_user.user_id', $userData->id);
                })
                ->pluck('id');

            $mergedCollection = $committeeByworkGroupsIds->merge($committeeIds)->unique();
            $resultCollection = $mergedCollection->values();
            $resultArray = $resultCollection->all();

            if (!empty($resultArray)) {
                $query->whereIn('committee_id', $resultArray);
            }
        }

        switch ($searchData['orderBy']) {
            case 'name':
                $query->orderBy('name', $orderDir);
                break;
            case 'date':
                $query->orderBy('documents.document_date', $orderDir);
                break;
            default:
                # latest
                $query->orderBy('documents.document_date', $orderDir);
                break;
        }

        $perPage = $searchData['perPage'] ?? 12;
        $page = $searchData['page'] ?? 1;

        $query->with([
            'documentFile',
            'country' => function($query) {
                $query->full()->with('flag');
            },
        ]);

        if ($searchData['limit']) {
            $documents = $query->limit($searchData['limit'])->get();
            $totalDocuments = $documents->count();

            if ($totalDocuments < $perPage) {
                $perPage = $totalDocuments;
            }

            $documents = $documents->forPage($page, $perPage);

            $paginator = new LengthAwarePaginator(
                $documents,
                $totalDocuments,
                $perPage,
                $page,
                ['path' => Paginator::resolveCurrentPath()]
            );

            $paginationData = [
                'currentPage' =>  intval($paginator->currentPage()),
                'lastPage' => intval($paginator->lastPage()),
                'perPage' =>  intval($paginator->perPage()),
                'total' =>  intval($paginator->total()),
                'count' =>  intval($paginator->count()),
                'hasMorePages' => $paginator->hasMorePages(),
                'nextPageUrl' => $paginator->nextPageUrl(),
                'prevPageUrl' => $paginator->previousPageUrl(),
            ];
        } else {
            $documents = $query->paginate($perPage, ['*'], 'page', $page);

            $paginationData = [
                'currentPage' =>  intval($documents->currentPage()),
                'lastPage' => intval($documents->lastPage()),
                'perPage' =>  intval($documents->perPage()),
                'total' =>  intval($documents->total()),
                'count' =>  intval($documents->count()),
                'hasMorePages' => $documents->hasMorePages(),
                'nextPageUrl' => $documents->nextPageUrl(),
                'prevPageUrl' => $documents->previousPageUrl(),
            ];
        }

        return [
            'documents' => $documents,
            'pagination' => $paginationData,
        ];
    }

    public function findBySlug(string $slug): ?Document {
        $userData = Auth::user();

        $hasLegalOpinionsPermission = $userData->member->user_permission_level
            ? $userData->legal_opinion_permission
            : $userData->member->legal_opinions;

        $hasFinanceSubCommitteePermission = $userData->finance_sub_committee_permission;

        $query = Document::full()
            ->where('status', 'published')
            ->where('lang_slug', $slug)
            ->where(function ($query) {
                $query->whereNull('publish_date')
                    ->orWhere('publish_date', '<=', now()->tz('Europe/Berlin'));
            })->where(function ($query) {
                $query->whereNull('expiration_date')
                    ->orWhere('expiration_date', '>', now()->tz('Europe/Berlin'));
            })
            ->join('committees', 'committees.id', 'documents.committee_id');

            if ($userData->member->member_type !== 'noType') {
                $query->where(function ($query) use ($userData, $hasLegalOpinionsPermission, $hasFinanceSubCommitteePermission) {
                    $query->where('committees.type', 'standard');

                    if ($userData->member->legal_committee) {
                        $query->orWhere('committees.type', 'legalCommittee');
                    }

                    if ($hasLegalOpinionsPermission) {
                        $query->orWhere('committees.type', 'legalOpinions');
                    }

                    if ($hasFinanceSubCommitteePermission) {
                        $query->orWhere('committees.type', 'financeSubCommittee');
                    }
                });
            } else {
                $query->where('committees.type', 'legalOpinions');
            }


        $query->with([
            'country' => function($query) {
                $query->full()->with('flag');
            },
            'documentFile',
            'tags' => function($query) {
                $query->full()->select('*');
            }
        ]);

        return $query->first();
    }
}
