<?php

namespace App\Filament\Resources\PhotoGeoData\Pages\Concerns;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

trait HandlesImageMetadata
{
    protected function syncMetadataFromImage(): void
    {
        $metadata = $this->extractImageMetadata($this->record->image_path);

        if ($metadata === null) {
            return;
        }

        $this->record->update(['metadata' => $metadata]);
    }

    private function extractImageMetadata(mixed $imagePath): ?array
    {
        if (empty($imagePath)) {
            return null;
        }

        $path = is_array($imagePath) ? reset($imagePath) : $imagePath;
        $fullPath = Storage::disk('public')->path($path);

        if (!file_exists($fullPath)) {
            Log::warning('extractImageMetadata: file not found', ['path' => $fullPath]);
            return null;
        }

        $exif = @exif_read_data($fullPath, null, true);

        if ($exif === false) {
            Log::debug('extractImageMetadata: no EXIF data', ['path' => $fullPath]);
            return null;
        }

        return $exif;
    }

    private function extractGpsCoordinates(array $exif): ?array
    {
        $gps = $exif['GPS'] ?? null;

        if (!$gps) {
            return null;
        }

        $lat = $this->rationalToDecimal($gps['GPSLatitude'] ?? null);
        $lng = $this->rationalToDecimal($gps['GPSLongitude'] ?? null);

        if ($lat === null || $lng === null) {
            return null;
        }

        if (($gps['GPSLatitudeRef'] ?? 'N') === 'S') {
            $lat = -$lat;
        }

        if (($gps['GPSLongitudeRef'] ?? 'E') === 'W') {
            $lng = -$lng;
        }

        return ['lat' => $lat, 'lng' => $lng];
    }

    private function rationalToDecimal(?array $rational): ?float
    {
        if (!$rational || count($rational) < 3) {
            return null;
        }

        return $this->rationalValue($rational[0])
            + $this->rationalValue($rational[1]) / 60
            + $this->rationalValue($rational[2]) / 3600;
    }

    private function rationalValue(string $rational): float
    {
        [$num, $den] = array_pad(explode('/', $rational, 2), 2, '1');
        return $den != 0 ? (float) $num / (float) $den : 0.0;
    }
}
