<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Mail;

use App\Traits\TagsTrait;

use App\Models\Livestream;
use App\Models\User;
use App\Models\Location;

use App\Mail\InquiryConfirmation;
use App\Mail\InquiryCreated;

class Inquiry extends Model
{
    use HasFactory;
    use TagsTrait;
    use SoftDeletes;

    protected $casts = [
        'archived_at' => 'datetime',
    ];

    protected $with = ['user'];

    public function saveInquiry(array $input, $id = null)
    {
        if ($id) {
            $inquiry = Inquiry::findOrFail($id);
        } else {
            $inquiry = new Inquiry();
        }

        $user = User::findOrCreateByEmail($input);
        $inquiry->user_id = $user->id;

        $inquiry->phone = Arr::get($input, 'phone');
        $inquiry->target_grade = Arr::get($input, 'target_grade');
        $inquiry->target_year = Arr::get($input, 'target_year');
        $inquiry->student_type = Arr::get($input, 'student_type');
        $inquiry->question = Arr::get($input, 'question');
        $inquiry->location_id = (new Location())->saveLocation()->id;
        $inquiry->type = Arr::get($input, 'type');
        $inquiry->secondary_name = Arr::get($input, 'secondary_name');

        $inquiry->save();

        $livestream_registrations = $inquiry->saveLivestreams($input);

        $inquiry->refresh();

        if (!$inquiry->url) {
            $inquiry->url = URL::signedRoute('inquiries.view', ['id' => $inquiry->id]);
            $inquiry->save();
        }

        $inquiry->saveTags($input);

        cache()->tags([cache_name($inquiry)])->flush();

        if (!$id) {
            $notification_email = null;

            if ( Arr::get($input, 'inquiry_form_id') ) {
                $inquiry_form = InquiryForm::find( Arr::get($input, 'inquiry_form_id'));
                if (filter_var($inquiry_form?->notification_email, FILTER_VALIDATE_EMAIL)) {
                    $notification_email = $inquiry_form->notification_email;
                }
            }

            Mail::to($inquiry->user->email)
                ->queue(new InquiryConfirmation($inquiry, $livestream_registrations, $notification_email));

            if ($notification_email) {
                Mail::to($notification_email)
                    ->queue(new InquiryCreated($inquiry));
            }
            
        }

        return $inquiry;
    }

    public function saveLivestreams($input)
    {
        $livestreams = collect();
        if (is_array(Arr::get($input, 'livestreams'))) {
            foreach (Arr::get($input, 'livestreams') as $livestream_data) {
                $livestream = Livestream::findOrFail(Arr::get($livestream_data, 'id'));
                $livestreams->push($livestream);
            }
        }

        if (Arr::get($input, 'livestream')) {
            $livestream = Livestream::findOrFail(Arr::get($input, 'livestream.id'));
            $livestreams->push($livestream);
        }

        foreach ($livestreams as $livestream) {
            if (!$this->user->livestreams->contains('id', $livestream->id)) {
                $livestream->registerUser($this->user, true); // true = skip confirmation email
            }
        }

        return LivestreamRegistration::where('user_id', $this->user->id)
            ->whereIn('livestream_id', $livestreams->pluck('id'))
            ->get();
    }

    public static function findPage()
    {
        return Page::whereHas('versions', function ($query) {
            $query->where('slug', 'inquiry-content');
        })->first();
    }

    public static function getTags()
    {
        $tags = self::findPage()
                    ->published_content_elements
                    ->map(function ($content_element) {
                        return $content_element->tags;
                    })
                    ->flatten();

        $boarding_tag = Tag::where('name', 'Boarding Student')->first();
        $day_tag = Tag::where('name', 'Day Student')->first();

        $tags->push($boarding_tag);
        $tags->push($day_tag);

        $inquiry_tags = $tags->unique(function ($tag) {
            return $tag->id;
        });

        return Tag::filterWithHierarchy($inquiry_tags);
    }

    public function getFilteredTagsAttribute()
    {
        $boarding_tag = Tag::where('name', 'Boarding Student')->first();
        $day_tag = Tag::where('name', 'Day Student')->first();

        return $this->tags->filter(function ($tag) use ($boarding_tag, $day_tag) {
            return $tag->id !== $boarding_tag->id && $tag->id !== $day_tag->id;
        });
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function location()
    {
        return $this->belongsTo(Location::class);
    }
}
