<?php

namespace Modules\Transport\Services;

use App\Models\ActivityLogModel;
use App\Models\TransportLocationModel;

class LocationService
{
    protected TransportLocationModel $locations;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->locations = new TransportLocationModel();
        $this->activity  = new ActivityLogModel();
    }

    public function create(array $input, ?int $actingUserId): array
    {
        $name = trim((string) ($input['name'] ?? ''));
        if ($name === '') {
            return ['success' => false, 'errors' => ['name' => 'Location name is required.']];
        }

        $data = $this->mapInput($input, $actingUserId);
        $data['number']     = $this->locations->nextNumber();
        $data['name']       = $name;
        $data['created_by'] = $actingUserId;
        $data['updated_by'] = $actingUserId;

        if (! $this->locations->insert($data, true)) {
            return ['success' => false, 'errors' => $this->locations->errors()];
        }

        $id = (int) $this->locations->getInsertID();
        $this->activity->log('transport_locations', 'created', $actingUserId, "Created location #{$id} ({$data['number']})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function update(int $id, array $input, ?int $actingUserId): array
    {
        if (! $this->locations->find($id)) {
            return ['success' => false, 'errors' => ['id' => 'Location not found.']];
        }

        $name = trim((string) ($input['name'] ?? ''));
        if ($name === '') {
            return ['success' => false, 'errors' => ['name' => 'Location name is required.']];
        }

        $data = $this->mapInput($input, $actingUserId);
        $data['name']       = $name;
        $data['updated_by'] = $actingUserId;

        if (! $this->locations->update($id, $data)) {
            return ['success' => false, 'errors' => $this->locations->errors()];
        }

        $this->activity->log('transport_locations', 'updated', $actingUserId, "Updated location #{$id}", (string) $id);

        return ['success' => true];
    }

    public function delete(int $id, ?int $actingUserId): array
    {
        if (! $this->locations->find($id)) {
            return ['success' => false, 'error' => 'Location not found.'];
        }

        $this->locations->delete($id);
        $this->activity->log('transport_locations', 'deleted', $actingUserId, "Deleted location #{$id}", (string) $id);

        return ['success' => true];
    }

    protected function mapInput(array $input, ?int $actingUserId): array
    {
        $type = (string) ($input['location_type'] ?? 'stop');
        if (! in_array($type, TransportLocationModel::TYPES, true)) {
            $type = 'stop';
        }

        $status = (string) ($input['status'] ?? 'active');
        if (! in_array($status, ['active', 'inactive'], true)) {
            $status = 'active';
        }

        return [
            'code'          => trim((string) ($input['code'] ?? '')) ?: null,
            'location_type' => $type,
            'address'       => trim((string) ($input['address'] ?? '')) ?: null,
            'city'          => trim((string) ($input['city'] ?? '')) ?: null,
            'country'       => trim((string) ($input['country'] ?? '')) ?: null,
            'latitude'      => $this->nullableDecimal($input['latitude'] ?? null),
            'longitude'     => $this->nullableDecimal($input['longitude'] ?? null),
            'contact_name'  => trim((string) ($input['contact_name'] ?? '')) ?: null,
            'contact_phone' => trim((string) ($input['contact_phone'] ?? '')) ?: null,
            'status'        => $status,
            'notes'         => trim((string) ($input['notes'] ?? '')) ?: null,
        ];
    }

    protected function nullableDecimal($value): ?float
    {
        if ($value === null || $value === '') {
            return null;
        }

        return round((float) $value, 7);
    }
}
