<?php

namespace App\Models\Advisories;

use App\Models\Asset;
use App\Models\Companies\Company;
use App\Models\Companies\CompanyMember;
use App\Support\HasObjectsTrait;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;

class Advisory extends Model {
    use UuidScopeTrait, SoftDeletes, RelationValuesTrait, HasObjectsTrait;

    protected $dates = [
    ];

    protected $fillable = [
        'uuid',
        'parent_id',
        'logo_id',
        'document_id',
        'type',
        'name',
        'title',
        'number',
        'email',
        'phone',
        'director_name',
        'secretary_name',
        'is_main'
    ];

    protected $hidden = [
        'id'
    ];


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

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

    public function advisoryCompanies(): HasMany {
        return $this->hasMany(AdvisoryCompany::class);
    }

    public function companies(): BelongsToMany {
        return $this->belongsToMany(Company::class, 'advisory_companies');
    }

    public function members(): HasMany {
        return $this->hasMany(AdvisoryMember::class);
    }

    public function companyMembers(): BelongsToMany {
        return $this->belongsToMany(CompanyMember::class, 'advisory_members')->wherePivotNull('deleted_at');
    }

    public function parent(): BelongsTo {
        return $this->belongsTo(self::class, 'parent_id');
    }

    public function children(): HasMany {
        return $this->hasMany(self::class, 'parent_id');
    }

    public function siblings(): HasMany {
        return $this->hasMany(Advisory::class, 'parent_id', 'parent_id')->where('id', '!=', $this->id);
    }



    public function getParsedTypeAttribute(): array {
        return ['name' => $this->type, 'title' => AdvisoryType::TITLES[$this->type] ?? null];
    }

    public function getCaptionAttribute(): string {
        return "{$this->number} «{$this->title}»";
    }

    public function getPathTitleAttribute(): string {
        $advisory = $this;
        $result = [$advisory->number];
        while ($advisory = $advisory->parent) $result[] = $advisory->number;
        return implode(' / ', $result);
    }

    /*
    public function getSecretaryAttribute() {
        return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::SECRETARY)->first();
    }
    */
    public function getSecretaryAssistantsAttribute(): Collection {
        return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::SECRETARY_ASSISTANT)->get();
    }
    public function getSecretaryAndAssistantsAttribute(): Collection {
        return $this->companyMembers()->wherePivotIn('rank', [AdvisoryMemberRank::SECRETARY, AdvisoryMemberRank::SECRETARY_ASSISTANT])->get();
    }
    public function getChairmanAttribute() {
        return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::CHAIRMAN)->first();
    }
    public function getChairmanVicesAttribute(): Collection {
        return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::VICE_CHAIRMAN)->get();
    }
    public function getOrdinaryMembersAttribute(): Collection {
        return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::ORDINARY)->get();
    }



    public function setLogo($val) {
        $asset = Asset::byUuid($val)->first();
        $this->update(['logo_id' => $asset->id ?? null]);
    }
    public function setDocument($val) {
        $asset = Asset::byUuid($val)->first();
        $this->update(['document_id' => $asset->id ?? null]);
    }


    public function addMember(CompanyMember $companyMember, $rank = null): Model {
        $member = $this->members()->firstOrCreate(['company_member_id' => $companyMember->id]);
        $member->update(['rank' => $rank ?? AdvisoryMemberRank::ORDINARY]);
        return $member;
    }


    public function syncMembers(Collection $companyMembers, $rank, ?Company $company = null) {
        $exists = $companyMembers->map(function(CompanyMember $companyMember) use($rank) {
            return $this->members()->firstOrCreate(['company_member_id' => $companyMember->id, 'rank' => $rank]);
        });
        $this->deleteDisappearedMembers($exists, $rank, $company);
    }
    public function deleteDisappearedMembers(Collection $exists, $rank, ?Company $company) {
        $query = $this->members()->where(['rank' => $rank])->whereNotIn('id', $exists->pluck('id')->all());
        if ($company && in_array($rank, [AdvisoryMemberRank::ORDINARY, AdvisoryMemberRank::VOTER])) $query->whereHas('companyMember', function($query) use($company) {
            $query->where(['company_id' => $company->id]);
        });
        $query->delete();
    }



    public static function main() {
        return self::query()->where(['is_main' => 1])->first();
    }

    public static function root() {
        return self::query()->where(['parent_id' => 0])->get();
    }

}
