<?php

namespace App\Models;

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

class Service extends Model
{
    use HasFactory, HasCategories, Locationable, Rateable, DraftableModel;
    use HasCurrency;
    use Filterable;
    use Likeable;
    use Searchable;
    use SoftDeletes;

    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->serviceable?->name;
        $array['user_tag_line'] = $this->serviceable?->tag_line;
        $array['categories']=[Category::find($this->category_id)];
        foreach ($this->specialties() as $specialty){
            $array['categories'][]=$specialty->name;
        }
        return $array;
    }

    protected $guarded = [];
    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = [
        'hierarchicalCategories',
        'averageRating',
        'rates',
        'isLikedByUser'
    ];

    static public function saveDraft(Request $request)
    {
        $service = new Service();
        $service->slug= Str::uuid()->toString();
        if ($request->has('title')) {
            $service->title = $request->title;
        }
        if ($request->has('description')) {
            $service->description = $request->description;
        }
        if ($request->has('three_tiers')) {
            $service->three_tiers = $request->three_tiers;
        }
        if ($request->has('basic_tier_price')) {
            $service->basic_tier_price = $request->basic_tier_price;
        }
        if($request->has("basic_tier_days")){
            $service->basic_tier_days = $request->basic_tier_days;
        }
        if ($request->three_tiers) {
            $service->standard_tier_price = $request->standard_tier_price;
            $service->pro_tier_price = $request->pro_tier_price;
            $service->standard_tier_days = $request->standard_tier_days;
            $service->pro_tier_days = $request->pro_tier_days;
        }
        if ($request->category_id != null) {
            $service->category_id = $request->category_id??null;
        }
       if ($request->specialties != null) {
           $service['categories'] = $request->specialties;
       }
       if ($request->skills != null) {
           $service['skills']=$request->skills;
       }
       if ($request->has('tier_options')) {
           $service['tierOptions'] = $request->tier_options;
       }
        if ($request->has('engineer')) {
            $service->serviceable_id = $request->engineer ? Auth::user()->engineer->id : Auth::user()->firm->id;
            $service->serviceable_type = $request->engineer ? 'App\Models\Engineer' : 'App\Models\Firm';
        }

        $service['location'] = [
            'lat' => $request->lat??null,
            'long' => $request->long??null,
            'address' => $request->address??null,
        ];

        $service->status = 'Draft';
        $service->saveAsDraft();
        return $service;
    }

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

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

    public function tierOptions()
    {
        return $this->hasMany(ServiceTierOption::class);
    }

    public function images()
    {
        return $this->hasMany(ServiceImage::class);
    }

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

    public function orders()
    {
        return $this->hasMany(ServiceOrder::class);
    }

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

    public function togglePauseStatus()
    {
        $this->update([
            "status" => $this->status == "Paused" ? "Published" : "Paused",
        ]);
        $this->save();
        return $this;
    }

    public function getTierEnabled(int $tier)
    {
        if (!$this->three_tiers) return 'basic_enabled';
        switch ($tier) {
            case 0:
                return 'basic_enabled';
                break;
            case 1:
                return 'standard_enabled';
                break;
            case 2:
                return 'pro_enabled';
        }
    }

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

    public function getFormattedTier(int $tier)
    {
        // $tier--;
        return [
            'duration' => $this->getTierDuration($tier),
            'price' => $this->getTierPrice($tier),
            'name' => $this->getTierName($tier),
        ];
    }

    public function getTierDuration(int $tier)
    {
        if (!$this->three_tiers) return $this->basic_tier_days;
        switch ($tier) {
            case 0:
                return $this->basic_tier_days;
                break;
            case 1:
                return $this->standard_tier_days;
                break;
            case 2:
                return $this->pro_tier_days;
        }
    }

    public function getTierPrice(int $tier)
    {
        if (!$this->three_tiers) return $this->basic_tier_price;
        switch ($tier) {
            case 0:
                return $this->basic_tier_price;
                break;
            case 1:
                return $this->standard_tier_price;
                break;
            case 2:
                return $this->pro_tier_price;
        }
    }

    public function getTierName(int $tier)
    {
        if (!$this->three_tiers) return 'Basic';
        switch ($tier) {
            case 0:
                return 'Basic';
                break;
            case 1:
                return 'Standard';
                break;
            case 2:
                return 'Pro';
        }
    }
}
