<?php

namespace App\Libs\Services;

use App\Models\Document;
use App\Models\User;
use App\Models\RatificationLetter;
use App\Notifications\NewRatificationLetterUploaded;
use App\Notifications\RatificationLetterApproved;
use App\Notifications\RatificationLetterRejected;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Notification;

class RatificationLetterService
{
    public function readRatificationLetter($ratificationLetterId)
    {
        $authUser = Auth::user();
        $ratificationLetter = null;

        if ($authUser->role === "user") {
            $ratificationLetter = RatificationLetter::where(function ($query) use ($ratificationLetterId, $authUser) {
                $query->where('id', $ratificationLetterId)
                    ->where('user_id', $authUser->id);
                })
                ->orWhere(function ($query) use ($ratificationLetterId) {
                    $query->where('id', $ratificationLetterId)
                        ->where('status', 'approved');
                })
                ->first();
        } else {
            $ratificationLetter = RatificationLetter::find($ratificationLetterId);
        }
        return $ratificationLetter;
    }

    public function getRatificationLetters($data)
    {
        $authUser = Auth::user();
        $now = Carbon::now();
        $orderDir = $data['orderDir'] ? $data['orderDir'] : 'asc';
        $query = RatificationLetter::select('*');

        if ($authUser && $authUser->role === "user") {
            $query->where(function ($query) use ($authUser, $data) {
                $query->where('ratification_letters.user_id', $authUser->id)
                      ->orWhere(function ($query) use ($data) {
                          $query->where('status', 'approved');
                      });
            });
        } else {
            if (!empty($data['status'])) {
                $query->where('status', $data['status']);
            }
        }

        if (!empty($data['filterBy'])) {
            switch ($data['filterBy']) {
                case 'closed':
                    $query->whereDate('status_updated_at', '<', $now);
                    break;
                case 'open':
                    $query->whereDate('status_updated_at', '>=', $now);
                    break;
            }
        }

        switch ($data['orderBy']) {
            case 'statusUpdatedAt':
                $query->orderBy('status_updated_at', $orderDir);
                break;
            case 'createAt':
                $query->orderBy('created_at', $orderDir);
                break;
            default:
                # company_name
                $query->leftJoin('users', 'users.id', '=', 'ratification_letters.user_id')
                ->leftJoin('legal_entities', 'legal_entities.id', '=', 'ratification_letters.legal_entity_id')
                ->select('ratification_letters.*', 'users.company_name', 'legal_entities.legal_entity')
                ->orderByRaw("CASE
                    WHEN legal_entities.legal_entity IS NOT NULL
                        THEN CONCAT(legal_entities.legal_entity, ' ', COALESCE(users.company_name, ''), ' ', ratification_letters.title)
                    WHEN users.company_name IS NOT NULL
                        THEN CONCAT(users.company_name, ' ', COALESCE(legal_entities.legal_entity, ''), ' ', ratification_letters.title)
                    ELSE
                        ratification_letters.title
                    END {$orderDir}");
                break;
        }

        if (!empty($data['countOnly'])) {
            $count = $query->count();

            return [
                'count' => $count,
            ];
        } else {
            $perPage = $data['perPage'] ?? 12;
            $page = $data['page'] ?? 1;

            $ratificationLetters = $query->paginate($perPage, ['*'], 'page', $page);

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

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

    public function createRatificationLetter($data)
    {
        $tempFileName = $data['filename'];
        $tempPath = 'temp_document/' . $tempFileName;
        $ext = pathinfo($data['filename'], PATHINFO_EXTENSION);
        $uniqueName = md5(pathinfo($data['filename'], PATHINFO_FILENAME) . microtime(true));
        $newFileName = $uniqueName . '.' . $ext;
        $finalPath = 'ratification-letters/' . $newFileName;

        $privateDisk = Storage::disk('private');

        if (!$privateDisk->exists(dirname($finalPath))) {
            $privateDisk->makeDirectory(dirname($finalPath));
        }

        if ($privateDisk->exists($tempPath)) {
            $privateDisk->move($tempPath, $finalPath);
        } else {
            return [];
        }

        $fileSize = $privateDisk->size($finalPath);

        $document = Document::create([
            'filename'              => $newFileName,
            'original_filename'     => $tempFileName,
            'extension'             => $ext,
            'size'                  => $fileSize,
        ]);

        $ratificationLetter = RatificationLetter::create([
            'title'             => $data['title'],
            'status'            => 'pending',
            'document_id'       => $document->id,
            'letter_id'         => $data['letterId'],
            'user_id'           => Auth::user()->id,
            'legal_entity_id'   => $data['legalEntityId'],
            'company_id'        => $data['companyId']
        ]);

        $users = User::where('role', 'super')->get();
        Notification::send($users, new NewRatificationLetterUploaded());

        return $ratificationLetter;
    }

    public function updateRatificationLetter($data)
    {
        $authUser = Auth::user();
        $ratificationLetter = RatificationLetter::find($data['id']);

        if (empty($ratificationLetter) || $authUser->id !== $ratificationLetter->user_id) {
            return null;
        }

        if ($data['filename'] !== $ratificationLetter->document->filename) {
            $ratificationLetterOld = $ratificationLetter->document->filename;
            $tempFileName = $data['filename'];
            $tempPath = 'temp_document/' . $tempFileName;
            $finalPath = 'ratification-letters/' . $tempFileName;

            $privateDisk = Storage::disk('private');

            if ($privateDisk->exists($tempPath)) {
                $privateDisk->move($tempPath, $finalPath);

                $fileSize = $privateDisk->size($finalPath);

                $document = Document::find($ratificationLetter->document->id);
                $document->filename = $tempFileName;
                $document->original_filename = $tempFileName;
                $document->extension = pathinfo($tempFileName, PATHINFO_EXTENSION);
                $document->size = $fileSize;
                $document->save();
            } else {
                return [];
            }

            $filePath = 'ratification-letters/' . $ratificationLetterOld;
            if ($privateDisk->exists($filePath)) {
                $privateDisk->delete($filePath);
            }
        }

        $ratificationLetter->title = $data['title'];
        $ratificationLetter->save();

        return $ratificationLetter;
    }

    public function deleteRatificationLetter($ratificationLetterId)
    {
        $authUser = Auth::user();
        $ratificationLetter = RatificationLetter::find($ratificationLetterId);

        if ($authUser && $authUser->role !== 'user') {
            $ratificationLetter->delete();
        } else {
            if (empty($ratificationLetter) || $authUser->id !== $ratificationLetter->user_id) {
                return [
                    'message' => 'not allowed',
                ];
            }

            $ratificationLetter->delete();
        }

        $document = $ratificationLetter->document;

        if ($document) {
            $document->delete();

            $privateDisk = Storage::disk('private');

            $ratificationLetterOld = $ratificationLetter->document->filename;
            $filePath = 'ratification-letters/' . $ratificationLetterOld;
            if ($privateDisk->exists($filePath)) {
                $privateDisk->delete($filePath);
            }
        }

        return [
            'message' => 'success',
        ];
    }

    public function getRatificationLettersParty($data) {
        $authUser = Auth::user();
        $now = Carbon::now();
        $orderDir = $data['orderDir'] ? $data['orderDir'] : 'asc';

        $query = RatificationLetter::select('*')->where('letter_id', $data['letterId']);

        if ($authUser->role === "user") {
            $query->where(function ($query) use ($authUser, $data) {
                $query->where(function ($query) use ($authUser) {
                    $query->where('ratification_letters.user_id', $authUser->id)
                        ->where('status', 'pending');
                })->orWhere('status', 'approved');
            });
        } else {
            if (!empty($data['status'])) {
                $query->where('status', $data['status']);
            }
        }

        if (!empty($data['filterBy'])) {
            switch ($data['filterBy']) {
                case 'closed':
                    $query->whereDate('status_updated_at', '<', $now);
                    break;
                case 'open':
                    $query->whereDate('status_updated_at', '>=', $now);
                    break;
            }
        }

        switch ($data['orderBy']) {
            case 'statusUpdatedAt':
                $query->orderBy('status_updated_at', $orderDir);
                break;
            case 'createAt':
                $query->orderBy('created_at', $orderDir);
                break;
            default:
                # company_name
                $query->leftJoin('users', 'users.id', '=', 'ratification_letters.user_id')
                ->leftJoin('legal_entities', 'legal_entities.id', '=', 'ratification_letters.legal_entity_id')
                ->select('ratification_letters.*', 'users.company_name', 'legal_entities.legal_entity')
                ->orderByRaw("CASE
                    WHEN legal_entities.legal_entity IS NOT NULL
                        THEN CONCAT(legal_entities.legal_entity, ' ', COALESCE(users.company_name, ''), ' ', ratification_letters.title)
                    WHEN users.company_name IS NOT NULL
                        THEN CONCAT(users.company_name, ' ', COALESCE(legal_entities.legal_entity, ''), ' ', ratification_letters.title)
                    ELSE
                        ratification_letters.title
                    END {$orderDir}");
                break;
        }

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

        $ratificationLetters = $query->paginate($perPage, ['*'], 'page', $page);

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

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

    public function updateRatificationLetterStatus($data) {
        $ratificationLetter = RatificationLetter::find($data['id']);

        if (empty($ratificationLetter) && $ratificationLetter->status !== 'pending') {
            return [
                'message' => 'not allowed',
            ];
        }

        $ratificationLetter->status = $data['status'];
        $ratificationLetter->rejetion_comment = $data['rejetion_comment'];
        $ratificationLetter->status_updated_at = now();
        $ratificationLetter->save();

        if ($data['status'] === 'rejected') {
            $user = $ratificationLetter->user;

            if ($user) {
                $letter = $ratificationLetter->letter;
                Notification::send($user, new RatificationLetterRejected($letter));
            }
        }

        if ($data['status'] === 'approved') {
            $user = $ratificationLetter->user;

            if ($user) {
                $letter = $ratificationLetter->letter;
                Notification::send($user, new RatificationLetterApproved($letter));
            }
        }

        return $ratificationLetter;
    }
}
