<?php

namespace App\Models;

use App\Traits\BelongsToOrg;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Notifications\Notifiable;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

/**
 * @method static \Database\Factories\AssociationFactory factory()
 */
class Association extends Model implements HasMedia
{
    use BelongsToOrg, HasFactory, InteractsWithMedia, Notifiable; // , TrackWorkflowModelEvents;

    protected $fillable = [
        'name',

        'license_number',
        'license_expiration_date',

        'user_id',
        'org_id',

        'city',
        'street',
        'district',
        'postal_code',
        'building_number',
        'secondary_number',

        'lat',
        'lng',
        'location',

        'iban',
        'bank_name',
        'account_holder_name',

        'is_verified',
        'is_locked',

        // Media collection attributes for SpatieMediaLibraryFileUpload
        'logo',
        'authorization_letter',
        'license_certificate',
        'iban_certificate',
        'national_address_certificate',
        'governance_certificate',
        'financial_reports',
        'basic_bylaws',
    ];

    protected $casts = [
        'license_expiration_date' => 'date',
        'lat' => 'decimal:8',
        'lng' => 'decimal:8',
        'is_verified' => 'boolean',
        'is_locked' => 'boolean',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    protected $appends = [
        'location',
    ];

    public function representative(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function states(): BelongsToMany
    {
        return $this->belongsToMany(State::class);
    }

    public function cities(): BelongsToMany
    {
        return $this->belongsToMany(City::class);
    }

    public function centers(): BelongsToMany
    {
        return $this->belongsToMany(Center::class);
    }

    /**
     * Get all users associated with this association.
     */
    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'user_association')
            ->withPivot('org_id')
            ->withTimestamps();
    }

    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('logo')->singleFile();
        $this->addMediaCollection('authorization_letter')->singleFile();
        $this->addMediaCollection('license_certificate')->singleFile();
        $this->addMediaCollection('iban_certificate')->singleFile();
        $this->addMediaCollection('national_address_certificate')->singleFile();
        $this->addMediaCollection('governance_certificate')->singleFile();
        $this->addMediaCollection('financial_reports')->singleFile();
        $this->addMediaCollection('basic_bylaws')->singleFile();
    }

    /**
     * Get the logo URL
     */
    public function getLogoUrlAttribute(): ?string
    {
        return $this->getFirstMedia('logo')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the authorization letter URL
     */
    public function getAuthorizationLetterUrlAttribute(): ?string
    {
        return $this->getFirstMedia('authorization_letter')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the license certificate URL
     */
    public function getLicenseCertificateUrlAttribute(): ?string
    {
        return $this->getFirstMedia('license_certificate')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the IBAN certificate URL
     */
    public function getIbanCertificateUrlAttribute(): ?string
    {
        return $this->getFirstMedia('iban_certificate')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the national address certificate URL
     */
    public function getNationalAddressCertificateUrlAttribute(): ?string
    {
        return $this->getFirstMedia('national_address_certificate')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the governance certificate URL
     */
    public function getGovernanceCertificateUrlAttribute(): ?string
    {
        return $this->getFirstMedia('governance_certificate')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the financial reports URL
     */
    public function getFinancialReportsUrlAttribute(): ?string
    {
        return $this->getFirstMedia('financial_reports')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get the basic bylaws URL
     */
    public function getBasicBylawsUrlAttribute(): ?string
    {
        return $this->getFirstMedia('basic_bylaws')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Returns the 'lat' and 'lng' attributes as the computed 'location' attribute,
     * as a standard Google Maps style Point array with 'lat' and 'lng' attributes.
     *
     * Used by the Filament Google Maps package.
     *
     * Requires the 'location' attribute be included in this model's $fillable array.
     */
    public function getLocationAttribute(): array
    {
        return [
            'lat' => (float) $this->lat,
            'lng' => (float) $this->lng,
        ];
    }

    /**
     * Takes a Google style Point array of 'lat' and 'lng' values and assigns them to the
     * 'lat' and 'lng' attributes on this model.
     *
     * Used by the Filament Google Maps package.
     *
     * Requires the 'location' attribute be included in this model's $fillable array.
     */
    public function setLocationAttribute(?array $location): void
    {
        if (is_array($location)) {
            $this->attributes['lat'] = $location['lat'];
            $this->attributes['lng'] = $location['lng'];
            unset($this->attributes['location']);
        }
    }

    /**
     * Get the lat and lng attribute/field names used on this table
     *
     * Used by the Filament Google Maps package.
     *
     * @return string[]
     */
    public static function getLatLngAttributes(): array
    {
        return [
            'lat' => 'lat',
            'lng' => 'lng',
        ];
    }

    /**
     * Get the name of the computed location attribute
     *
     * Used by the Filament Google Maps package.
     */
    public static function getComputedLocation(): string
    {
        return 'location';
    }
}
