<?php

namespace App\Models;

use App\Mail\ApproveFirm;
use App\Traits\HasBillingAccount;
use App\Traits\HasCategories;
use App\Traits\HasCurrency;
use App\Traits\HasPortfolios;
use App\Traits\HasWallet;
use App\Traits\HasWorkerPhotos;
use App\Traits\Invitable;
use App\Traits\Locationable;
use App\Traits\Phonable;
use App\Traits\Rateable;
use App\Traits\Sociable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Mail;
use Laravel\Scout\Searchable;
use Overtrue\LaravelLike\Traits\Liker;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

class Firm extends Model
{

    use HasFactory;
    use HasCategories;
    use HasSlug;
    use Sociable;
    use Phonable;
    use Locationable;
    use Rateable;
    use HasPortfolios;
    use HasCurrency;
    use Liker;
    use HasBillingAccount;
    use Notifiable;
    use Searchable;
    use SoftDeletes;
    use Invitable;
    use HasWallet;
    use HasWorkerPhotos;


    protected $guarded = [];
    protected $appends = [
        "verified",
        "hierarchicalCategories",
        "socials",
        "currency",
        'averageRating',
        'servicesOrders',
        "profile_photo_url",
        "cover_photo_url",

    ];
    public function toSearchableArray()
    {
        $array = $this->toArray();

        $array = $this->transform($array);
        $array['categories']=[\App\Models\Category::find($this->category_id)->name];
        foreach ($this->specialties() as $specialty){
            $array['categories'][]=$specialty->name;
        }
        return $array;
    }
    public function getSlugOptions(): SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom("name")
            ->saveSlugsTo("slug")
            ->slugsShouldBeNoLongerThan(50)
            ->doNotGenerateSlugsOnUpdate();
    }

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

    public function chats()
    {
        return $this->morphMany(Chat::class, 'worker');
    }

    public function FirmSize()
    {
        return $this->belongsTo(FirmSize::class);
    }
    public function invitedProjects(){
        return $this->morphToMany(Project::class,'invited_worker');
    }
    public function FirmType()
    {
        return $this->belongsTo(FirmType::class);
    }

    public function verificationRequests()
    {
        return $this->morphMany(VerificationRequest::class,'entity');
    }
    public function skills()
    {
        return $this->morphToMany(Skill::class, "skillable");
    }

    public function licenses()
    {
        return $this->hasMany(License::class);
    }

    public function projects()
    {
        return $this->morphMany(Project::class, "projectable");
    }

    public function proposals()
    {
        return $this->morphMany(Proposal::class, "proposalable");
    }

    public function savedProjects()
    {
        $likes = $this->likes()
            ->with("likeable")
            ->withType(Project::class)
            ->get();
        $saved = [];
        foreach ($likes as $like) {
            $saved[] = $like->likeable;
        }
        return $saved;
    }

    public function verify()
    {
        $this->update([
            "verified_at" => now(),
        ]);
        $this->save();
        Mail::to($this->email)->send(new ApproveFirm($this));
    }

    public function getVerifiedAttribute()
    {
        return !!$this->verified_at;
    }

    public function services()
    {
        return $this->morphMany(Service::class, "serviceable");
    }

    public function successfulJobs()
    {
        $count = 0;
        if (is_countable($this->projects)) {
            $count += count($this->projects->where("status", "Completed"));
        }
        if (is_countable($this->serviceOrders)) {
            $count += count(
                collect($this->servicesOrders())->where("status", "Completed")
            );
        }
        return $count;
    }

    public function getSuccessfulJobsAttribute()
    {
        $count = 0;
        try {
            $count += $this->projects()->where('status', 'Completed')->count();
            $count += collect($this->orderedServices())->where("status", "closed")->count();
        } catch (\Exception $exception){
            dd($exception);
        }
        return $count;
    }

    public function getProcessingProjectsCountAttribute()
    {
        return $this->projects()->where('status','Processing')->count();
    }

    public function getServicesOrdersAttribute(){
        $orders=[];
        if($this->services == null){
            return $orders;
        }
        foreach ($this->services()->withTrashed()->get() as $service){
            $order = $service->orders()->with(['user.location','milestones.transaction'])->get()->map(function($item) use ($service){
                    $item->tier = $service->getFormattedTier($item->tier);
                    $item['service'] = $service->load('images');
                    return $item;
                });

            $orders[] = $order;
        }
        return collect($orders)->flatten();
    }

    public function orderedServices(){
        $services=[];
        foreach ($this->services as $service){
            foreach($service->orders as $order){


                $service = $order->service->load('images',
            'skills',
            'location',
            'tierOptions',
            'orders',
            'serviceable.user',
            'serviceable.currency',
            );

            $service->active_order_id = $order->id;
            $service->active_order_status = $order->status;
            $services[] = $service;
            }
        }
        return $services;
    }

    public function getActiveOrdersCountAttribute(){

        return collect($this->orderedServices())->where('status', 'in progress')->count();
    }

    public function getUnreadMessageCountAttribute() {
        $unread = 0;
        foreach ($this->chats as $chat) {
            $unread += $chat->messages()->where('sender_uid', '!=', $this->user->id)->where('read_at', null)->count();
        }
        return $unread;
    }
}
