<?php

namespace App;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Mtc\MercuryDataModels\DealBuilder\Deal;
use Mtc\MercuryDataModels\DealBuilder\DealAttachment;
use Mtc\MercuryDataModels\DealBuilder\Status;
use Mtc\MercuryDataModels\User;

use function tenant;

class DealRepository
{
    /**
     * @param array $input
     * @return Deal|Model
     */
    public function create(array $input, int $user_id): Deal
    {
        $input['user_id'] = $user_id;
        $input['status_id'] = Status::query()->where('name', 'like', 'draft')->firstOrFail()->id;
        return Deal::query()->create($input);
    }
    public function assignUser(Deal $deal, int $user_id): bool
    {
        /** @var User $user */
        $user = User::query()->findOrFail($user_id);
        $updated = $deal->update(['assignee_id' => $user->id]);
        if ($deal->wasChanged('assignee_id') && $this->shouldNotify($user, 'deal_assigned')) {
            // TODO: send email about deal being assigned to user
        }

        return $updated;
    }

    public function addNote(Deal $deal, int $user_id, string $message, array $files = []): void
    {
        $note = $deal->notes()->create([
            'user_id' => $user_id,
            'message' => nl2br($message),
        ]);

        $this->processAttachments($deal, $files, $user_id, 'deal_note_id', $note->id);
    }

    public function addMessage(Deal $deal, string $message, int $user_id = null, array $files = []): void
    {
        $messageRecord = $deal->messages()->create([
            'user_id' => $user_id,
            'message' => nl2br($message),
        ]);

        $this->processAttachments($deal, $files, $user_id, 'deal_message_id', $messageRecord->id);

        // TODO: notify other side about new message
        $messageRecord->update([
            // Timestamp for notification as email sendout happens only from Admin API
            'notification_sent_at' => Carbon::now(),
        ]);
    }

    protected function processAttachments(
        Deal $deal,
        array $files,
        ?int $user_id,
        string $foreignKey,
        int $foreignId
    ): void {
        foreach ($files as $file) {
            if (!$file instanceof UploadedFile) {
                continue;
            }

            $filename = Str::uuid() . '.' . $file->getClientOriginalExtension();
            $path = tenant('id') . '/deals/' . $deal->id . '/' . $filename;

            Storage::disk('file-storage')->putFileAs(
                tenant('id') . '/deals/' . $deal->id,
                $file,
                $filename,
                ['visibility' => 'private']
            );

            DealAttachment::create([
                'deal_id' => $deal->id,
                $foreignKey => $foreignId,
                'user_id' => $user_id,
                'filename' => $filename,
                'original_filename' => $file->getClientOriginalName(),
                'path' => $path,
                'mime_type' => $file->getMimeType(),
                'size' => $file->getSize(),
            ]);
        }
    }

    public function updateStatus(Deal $deal, int $new_status_id, int $user_id = null): void
    {
        $deal->update(['status_id' => $new_status_id]);
        if ($deal->wasChanged('status_id')) {
            $deal->history()->create([
                'status_id' => $new_status_id,
                'user_id' => $user_id,
            ]);
        }
        // TODO: notify other side about status change
    }


    private function shouldNotify(User $user, string $action): bool
    {
        // TODO: check if user should receive notifications about this event
        return true;
    }
}
