<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Location extends Model
{
    protected $table = 'locations';

    protected $fillable = [
        'display_name',
        'place_name',
        'raw_address',
        'street',
        'city',
        'state',
        'postal',
        'country',
        'lat',
        'lon',
        'phone',
        'hours_json',
    ];

    protected $casts = [
        'lat' => 'float',
        'lon' => 'float',
    ];

    /**
     * find an existing location by its normalized components or create it.
     * backfills lat/lon/raw_address/place_name if the found row is missing them.
     */
    public static function findOrCreateNormalized(array $norm, ?string $raw = null): self
    {
        $lookup = [
            'display_name' => $norm['display_name'] ?? null,
            'street'       => $norm['street']       ?? null,
            'city'         => $norm['city']         ?? null,
            'state'        => $norm['state']        ?? null,
            'postal'       => $norm['postal']       ?? null,
            'country'      => $norm['country']      ?? null,
        ];

        $existing = static::where($lookup)->first();

        // fallback: try matching by the raw label (useful for seeds like "Home")
        if (!$existing && $raw) {
            $existing = static::where('display_name', $raw)
                ->orWhere('raw_address', $raw)
                ->first();
        }

        if ($existing) {
            $changed = false;

            // backfill coords if missing (and we have them)
            $hasNewCoords = (!empty($norm['lat']) || !empty($norm['lon']));
            if (($existing->lat === null || $existing->lon === null) && $hasNewCoords) {
                $existing->lat = $norm['lat'] ?? $existing->lat;
                $existing->lon = $norm['lon'] ?? $existing->lon;
                $changed = true;
            }

            // backfill raw address if missing
            if ($raw && $existing->raw_address === null) {
                $existing->raw_address = $raw;
                $changed = true;
            }

            // backfill place_name if missing
            if ($existing->place_name === null && !empty($norm['place_name'])) {
                $existing->place_name = $norm['place_name'];
                $changed = true;
            }


            if ($changed) {
                $existing->save();
            }

            return $existing;
        }

        return static::create([
            'display_name' => $norm['display_name'] ?? ($raw ?: 'Unknown'),
            'place_name'   => $norm['place_name']   ?? null,
            'raw_address'  => $norm['raw_address']  ?? $raw,
            'street'       => $norm['street']       ?? null,
            'city'         => $norm['city']         ?? null,
            'state'        => $norm['state']        ?? null,
            'postal'       => $norm['postal']       ?? null,
            'country'      => $norm['country']      ?? null,
            'lat'          => $norm['lat']          ?? null,
            'lon'          => $norm['lon']          ?? null,
        ]);
    }

    /**
     * thin alias for backwards compatibility with older call-sites.
     * prefer using findOrCreateNormalized() directly.
     */
    public static function firstOrCreateNormalized(array $norm, ?string $raw = null): self
    {
        return static::findOrCreateNormalized($norm, $raw);
    }

    /**
     * create/find a label-only location (no geocode)
     */
    public static function labelOnly(string $label): self
    {
        return static::firstOrCreate(
            ['display_name' => $label],
            ['raw_address'  => null]
        );
    }

    /**
     * accessor: short label for ui (falls back gracefully)
     */
    public function getShortLabelAttribute(): string
    {
        return $this->place_name
            ?? $this->display_name
            ?? trim(collect([$this->street, $this->city])->filter()->join(', '));
    }
}
