<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class Wisata extends Model
{
    use HasFactory;

    protected $fillable = [
        'kategori_id',
        'title',
        'slug',
        'location',
        'image',
        'rating',
        'distance',
        'elevation',
        'tiket_parkir',
        'jam_operasional',
        'short_description',
        'overview',
        'model_path',
        'video_path',
        'is_video',
        'latitude',
        'longitude',
    ];

    protected function casts(): array
    {
        return [
            'rating' => 'decimal:1',
            'is_video' => 'boolean',
            'latitude' => 'decimal:7',
            'longitude' => 'decimal:7',
        ];
    }

    public function setImageAttribute(?string $value): void
    {
        $this->attributes['image'] = $this->normalizeStoredFilePath($value);
    }

    public function setModelPathAttribute(?string $value): void
    {
        $this->attributes['model_path'] = $this->normalizeStoredFilePath($value);
    }

    public function setVideoPathAttribute(?string $value): void
    {
        $this->attributes['video_path'] = $this->normalizeStoredFilePath($value);
    }

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

    public function fileUrl(?string $path): ?string
    {
        if (! $path) {
            return null;
        }

        if (Str::startsWith($path, ['http://', 'https://'])) {
            return $path;
        }

        $storagePath = $this->publicStoragePath($path);

        if ($storagePath && Storage::disk('public')->exists($storagePath)) {
            return asset('storage/'.$storagePath);
        }

        $publicPath = $this->publicAssetPath($path);

        return $publicPath && file_exists(public_path($publicPath))
            ? asset($publicPath)
            : null;
    }

    public function getImageUrlAttribute(): string
    {
        return $this->fileUrl($this->image) ?? asset('images/placeholders/wisata.svg');
    }

    public function getRatingLabelAttribute(): string
    {
        return number_format((float) $this->rating, 1).' ⭐';
    }

    public function publicStoragePath(?string $path): ?string
    {
        if (! $path || Str::startsWith($path, ['http://', 'https://'])) {
            return null;
        }

        $path = ltrim(str_replace('\\', '/', $path), '/');

        foreach (['/storage/app/public/', '/public/storage/'] as $needle) {
            if (str_contains($path, $needle)) {
                $path = Str::after($path, $needle);
                break;
            }
        }

        foreach (['storage/app/public/', 'public/storage/', 'storage/', 'public/'] as $prefix) {
            if (Str::startsWith($path, $prefix)) {
                $path = Str::after($path, $prefix);
            }
        }

        return $path ?: null;
    }

    private function normalizeStoredFilePath(?string $path): ?string
    {
        if (! $path) {
            return null;
        }

        if (Str::startsWith($path, ['http://', 'https://'])) {
            return $path;
        }

        return $this->publicStoragePath($path);
    }

    private function publicAssetPath(string $path): ?string
    {
        $path = ltrim(str_replace('\\', '/', $path), '/');

        if (Str::startsWith($path, 'public/')) {
            $path = Str::after($path, 'public/');
        }

        return $path ?: null;
    }

    public function getTypeAttribute(): string
    {
        if ($this->model_path) {
            return 'ar';
        }

        if ($this->is_video) {
            return 'video';
        }

        return 'normal';
    }

    public function getGoogleMapsUrlAttribute(): ?string
    {
        if ($this->latitude === null || $this->longitude === null) {
            return null;
        }

        return "https://www.google.com/maps?q={$this->latitude},{$this->longitude}";
    }
}
