<?php

namespace App\Models;

use App\Traits\Filterable;
use App\Traits\HasCategories;
use App\Traits\HasCurrency;
use App\Traits\Languagable;
use App\Traits\Locationable;
use App\Traits\Rateable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
use LaravelCreative\Draftable\traits\DraftableModel;
use Overtrue\LaravelLike\Traits\Likeable;
use Symfony\Component\HttpFoundation\Request;

class Project extends Model
{
    use HasFactory;
    use HasCategories;
    use DraftableModel;
    use Locationable;
    use Languagable;
    use Rateable;
    use HasCurrency;
    use Likeable;
    use Filterable;
    use Searchable;
    use SoftDeletes;
    protected $guarded = [];


    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = [
        'hierarchicalCategories',
        'deliverables',
        'milestones',
        'hired',
        'completionPercentage',
        'currency',
        'proposalCount',
        'averageRating',
        'rates',
        'isLikedByUser'
    ];



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

        $array = $this->transform($array);

        $array['long'] = $this->location?->long;
        $array['lat'] = $this->location?->lat;
        $array['address'] = $this->location?->address;
        $array['user_name']= $this->user?->name;
        $array['categories']=[Category::find($this->category_id)->name];
        foreach ($this->specialties() as $specialty){
            $array['categories'][]=$specialty->name;
        }
        return $array;
    }

    public function invitedEngineers(){
        return $this->morphedByMany(Engineer::class,'invited_worker');
    }

    public function invitedFirms(){
        return $this->morphedByMany(Firm::class,'invited_worker');
    }

    public function getIsLikedByUserAttribute(){
        return [
            'isLiked'=> Auth::user() != null && $this->isLikedBy(Auth::user()) && $this->deleted_at == null,
        ];
    }

    static public function saveDraft(Request $request)
    {
        $project = new Project();
        $project->title = $request->title;
        $project->description = $request->description;
        $project->slug= Str::uuid()->toString();
        $project->user_id = Auth::user()->id;
        $project->status = 'Drafted';
        $project->is_public = $request->is_public;
        $project->start_date = $request->start_date;
        $project->duration = $request->duration;
        $project->budget_type=$request->budget_type;
        $project->amount = $request->amount;
        $project->rate_type = $request->rate_type;
        $project->bidding_start=$request->bidding_start;
        $project->bidding_end= $request->bidding_end;

        if ($request->category_id != null) {
            $project->category_id = $request->category_id;
        }
        if ($request->specialties_ids != null) {
            $project->specialties_ids =($request->specialties);
        }
        if ($request->level_of_experience_id != null) {
            $project->level_of_experience_id = $request->level_of_experience_id;
        }
        if ($request->skills != null) {
            $project->skills_ids =$request->skills;
        }
        $project->location_array = ($request->location);
        $project->lang= ($request->language_id);
        $project->currency=(1);
        $project->saveAsDraft();
        return $project;
    }

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

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

    public function projectable()
    {
        return $this->morphTo();
    }

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

    public function files()
    {
        return $this->hasMany(ProjectFile::class);
    }

    public function location()
    {
        return $this->morphOne(Location::class, 'locationable');
    }

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

    public function getHiredAttribute()
    {
        return $this->proposals()->with(["proposalable.user", "files", 'contract', 'milestones' => ['files', 'deliverables']])->where('accepted', 1)->first();
    }

    public function proposals()
    {
        return $this->hasMany(Proposal::class);
    }

    public function getProposalCountAttribute()
    {
        return $this->proposals()->count();
    }

    public function getCompletionPercentageAttribute()
    {
        $hired = $this->proposals()->where('accepted', 1)->first();
        $total = $hired?->milestones()->count();
        $completed = $hired?->milestones()->where('accepted_at', '!=', null)->count();
        return $total == 0 || !$total ? 0 : round($completed / $total * 100);
    }

    public function getMilestonesAttribute()
    {
        return $this->proposals()->where('accepted', 1)->first()?->milestones()->with(['files', 'deliverables'])->get();
    }

    public function getDeliverablesAttribute()
    {
        return $this->proposals()->where('accepted', 1)->first()?->deliverables();
    }

    public function contract()
    {
        return $this->hasOne(Contract::class);
    }

    public function toggleHiddenStatus()
    {
        $this->update([
            "is_public" => !$this->is_public,
        ]);
        $this->save();
        return $this;
    }

    public function workerSubmittedProposals($worker)
    {
        return $this->proposals()->where('proposalable_id', $worker->id)->where('proposalable_type', get_class($worker))->get();
    }

    public function workerAcceptedProposal($worker)
    {
        try{
            return $worker!=null? $this->proposals()
                ->where('proposalable_id', $worker?->id)
                ->where('proposalable_type', get_class($worker))
                ->where('accepted', 1)
                ->with(["proposalable.user", "files", 'contract', 'milestones' => ['files', 'deliverables']])
                ->first():null;
        }catch (\Exception $e){
            return null;
        }

    }
}
