<?php
/**
 * Ubicacion estructurada en el instalador (empresa y sucursales).
 */

/**
 * @return array{
 *   street:string,
 *   city:string,
 *   state:string,
 *   stateCode:string,
 *   country:string,
 *   countryCode:string,
 *   coordinates: array<string, mixed>|null
 * }
 */
function antara_install_empty_location(): array
{
    return [
        'street' => '',
        'city' => '',
        'state' => '',
        'stateCode' => '',
        'country' => '',
        'countryCode' => '',
        'coordinates' => null,
    ];
}

/**
 * @param array<string, mixed> $loc
 */
function antara_install_compose_address(array $loc): string
{
    $parts = [];
    $street = trim((string) ($loc['street'] ?? ''));
    if ($street !== '') {
        $parts[] = $street;
    }
    $city = trim((string) ($loc['city'] ?? ''));
    if ($city !== '') {
        $parts[] = $city;
    }
    $state = trim((string) ($loc['state'] ?? ''));
    if ($state !== '') {
        $parts[] = $state;
    }
    $country = trim((string) ($loc['country'] ?? ''));
    if ($country !== '') {
        $parts[] = $country;
    }

    return implode(', ', $parts);
}

/**
 * @param string $s
 */
function antara_install_geo_truncate(string $s, int $max): string
{
    $s = trim($s);
    if ($s === '') {
        return '';
    }
    if (function_exists('mb_strlen') && mb_strlen($s, 'UTF-8') > $max) {
        return (string) mb_substr($s, 0, $max, 'UTF-8');
    }
    if (strlen($s) > $max) {
        return substr($s, 0, $max);
    }

    return $s;
}

/**
 * @param array<string, mixed>|null $coords
 * @return array<string, mixed>|null
 */
function antara_install_sanitize_coordinates(?array $coords): ?array
{
    if ($coords === null || $coords === []) {
        return null;
    }
    $lat = isset($coords['lat']) ? (float) $coords['lat'] : (isset($coords['latitude']) ? (float) $coords['latitude'] : null);
    $lon = isset($coords['lon']) ? (float) $coords['lon'] : (isset($coords['longitude']) ? (float) $coords['longitude'] : null);
    if ($lat === null || $lon === null || !is_finite($lat) || !is_finite($lon)) {
        return null;
    }
    if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) {
        return null;
    }
    $out = [
        'lat' => round($lat, 7),
        'lon' => round($lon, 7),
        'source' => antara_install_geo_truncate((string) ($coords['source'] ?? 'geolocation'), 32),
    ];
    if ($out['source'] === '') {
        $out['source'] = 'geolocation';
    }
    if (isset($coords['accuracy']) && is_numeric($coords['accuracy'])) {
        $out['accuracy'] = max(0, (float) $coords['accuracy']);
    }
    if (isset($coords['timestamp']) && is_numeric($coords['timestamp'])) {
        $out['timestamp'] = (int) $coords['timestamp'];
    }

    return $out;
}

/**
 * @param array<string, mixed> $in
 * @return array{
 *   street:string,
 *   city:string,
 *   state:string,
 *   stateCode:string,
 *   country:string,
 *   countryCode:string,
 *   coordinates: array<string, mixed>|null
 * }
 */
function antara_install_normalize_location(array $in): array
{
    $loc = antara_install_empty_location();
    $loc['street'] = antara_install_geo_truncate((string) ($in['street'] ?? ''), 200);
    $loc['city'] = antara_install_geo_truncate((string) ($in['city'] ?? ''), 120);
    $loc['state'] = antara_install_geo_truncate((string) ($in['state'] ?? ''), 120);
    $loc['stateCode'] = antara_install_geo_truncate(preg_replace('/[^a-zA-Z0-9_-]/', '', (string) ($in['stateCode'] ?? '')) ?? '', 16);
    $loc['country'] = antara_install_geo_truncate((string) ($in['country'] ?? ''), 120);
    $cc = strtoupper(antara_install_geo_truncate(preg_replace('/[^a-zA-Z]/', '', (string) ($in['countryCode'] ?? '')) ?? '', 2));
    $loc['countryCode'] = strlen($cc) === 2 ? $cc : '';
    $coords = $in['coordinates'] ?? null;
    $loc['coordinates'] = is_array($coords) ? antara_install_sanitize_coordinates($coords) : null;

    return $loc;
}

/**
 * @param string $json
 * @return array{
 *   street:string,
 *   city:string,
 *   state:string,
 *   stateCode:string,
 *   country:string,
 *   countryCode:string,
 *   coordinates: array<string, mixed>|null
 * }
 */
function antara_install_parse_location_json(string $json): array
{
    $json = trim($json);
    if ($json === '') {
        return antara_install_empty_location();
    }
    $data = json_decode($json, true);
    if (!is_array($data)) {
        return antara_install_empty_location();
    }

    return antara_install_normalize_location($data);
}

/**
 * @param array<string, mixed> $loc
 * @return array{location: array<string, mixed>, address: string}
 */
function antara_install_merge_location_into_address(array $loc): array
{
    $location = antara_install_normalize_location($loc);
    $address = antara_install_compose_address($location);
    if (strlen($address) > 500) {
        $address = function_exists('mb_substr')
            ? (string) mb_substr($address, 0, 500, 'UTF-8')
            : substr($address, 0, 500);
    }

    return ['location' => $location, 'address' => $address];
}

/**
 * @param array<string, mixed> $settings
 * @return array<string, mixed>
 */
function antara_install_company_location_from_settings(array $settings): array
{
    if (isset($settings['companyLocation']) && is_array($settings['companyLocation'])) {
        return antara_install_normalize_location($settings['companyLocation']);
    }

    return antara_install_empty_location();
}

/**
 * @param array<string, mixed> $branch
 * @return array<string, mixed>
 */
function antara_install_branch_location_from_row(array $branch): array
{
    if (isset($branch['location']) && is_array($branch['location'])) {
        return antara_install_normalize_location($branch['location']);
    }

    return antara_install_empty_location();
}

/**
 * @param array<string, mixed> $loc
 */
/**
 * Compara dos ubicaciones (direccion compuesta normalizada).
 *
 * @param array<string, mixed> $a
 * @param array<string, mixed> $b
 */
function antara_install_locations_match(array $a, array $b): bool
{
    $na = antara_install_normalize_location($a);
    $nb = antara_install_normalize_location($b);
    $addrA = antara_install_compose_address($na);
    $addrB = antara_install_compose_address($nb);
    if ($addrA === '' && $addrB === '') {
        return true;
    }

    return $addrA !== '' && $addrB !== '' && $addrA === $addrB;
}

function antara_install_location_is_empty(array $loc): bool
{
    foreach (['street', 'city', 'state', 'country', 'countryCode'] as $k) {
        if (trim((string) ($loc[$k] ?? '')) !== '') {
            return false;
        }
    }

    return ($loc['coordinates'] ?? null) === null;
}

/**
 * Bloque HTML de ubicacion (empresa o sucursal).
 *
 * @param array<string, mixed> $location
 * @param array{
 *   mode: 'company'|'branch'|'personal',
 *   esc: callable,
 *   readonly?: bool,
 *   inheritNote?: string
 * } $opts
 */
function antara_install_render_location_block(array $location, array $opts): string
{
    $esc = $opts['esc'];
    $mode = (string) ($opts['mode'] ?? 'company');
    $readonly = !empty($opts['readonly']);
    $loc = antara_install_normalize_location($location);
    $composed = antara_install_compose_address($loc);
    $json = json_encode($loc, JSON_UNESCAPED_UNICODE);
    if ($json === false) {
        $json = '{}';
    }

    $parts = [];
    $parts[] = '<div class="install-location-block" data-install-location-block';
    if ($readonly) {
        $parts[] = ' data-location-readonly="1"';
    }
    $parts[] = '>';

    if ($readonly && !empty($opts['inheritNote'])) {
        $parts[] = '<p class="muted" style="margin:0 0 .5rem;font-size:.82rem">' . $esc((string) $opts['inheritNote']) . '</p>';
    }

    if (!$readonly) {
        $parts[] = '<div class="install-geo-toolbar" style="display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;margin:.35rem 0 .35rem">';
        $parts[] = '<button type="button" class="btn" data-geo-gps style="margin-top:0;padding:.4rem .85rem;font-size:.82rem">Usar mi ubicacion</button>';
        $parts[] = '<span class="muted" data-geo-status style="font-size:.8rem" aria-live="polite"></span>';
        $parts[] = '</div>';
    }

    $hasCoords = is_array($loc['coordinates'] ?? null)
        && isset($loc['coordinates']['lat'], $loc['coordinates']['lon']);
    $parts[] = '<div class="install-geo-map-circle" data-geo-map' . ($hasCoords ? '' : ' hidden') . ' aria-hidden="false">';
    $parts[] = '<iframe title="Mapa de ubicacion" loading="lazy" referrerpolicy="no-referrer-when-downgrade" data-geo-map-frame></iframe>';
    $parts[] = '</div>';

    $parts[] = '<label>Pais</label>';
    $parts[] = '<select data-geo-country' . ($readonly ? ' disabled' : '') . '><option value="">Pais</option></select>';

    $parts[] = '<label>Estado / provincia</label>';
    $parts[] = '<select data-geo-state' . ($readonly ? ' disabled' : '') . '><option value="">Estado / provincia</option></select>';
    $parts[] = '<div data-geo-state-text-wrap style="display:none"><input type="text" data-geo-state-text placeholder="Estado o provincia" maxlength="120" value="' . $esc($loc['state']) . '"' . ($readonly ? ' disabled' : '') . '></div>';

    $parts[] = '<label>Ciudad</label>';
    $parts[] = '<select data-geo-city' . ($readonly ? ' disabled' : '') . '><option value="">Ciudad</option></select>';
    $parts[] = '<div data-geo-city-text-wrap style="display:none"><input type="text" data-geo-city-text placeholder="Ciudad" maxlength="120" value="' . $esc($loc['city']) . '"' . ($readonly ? ' disabled' : '') . '></div>';

    $parts[] = '<label>Calle y numero</label>';
    $parts[] = '<input type="text" data-geo-street placeholder="Calle, numero, colonia" maxlength="200" value="' . $esc($loc['street']) . '"' . ($readonly ? ' disabled' : '') . '>';

    if ($mode === 'company') {
        $parts[] = '<input type="hidden" name="company_location_json" data-geo-json value="' . $esc($json) . '">';
        $parts[] = '<input type="hidden" name="companyAddress" id="companyAddress" data-geo-address value="' . $esc($composed) . '">';
    } elseif ($mode === 'personal') {
        $parts[] = '<input type="hidden" name="personal_location_json" data-geo-json value="' . $esc($json) . '">';
        $parts[] = '<input type="hidden" name="personalAddress" id="personalAddress" data-geo-address value="' . $esc($composed) . '">';
    } else {
        $parts[] = '<input type="hidden" name="branch_location_json[]" data-geo-json value="' . $esc($json) . '">';
        $parts[] = '<input type="hidden" name="branch_address[]" data-geo-address value="' . $esc($composed) . '">';
    }

    $parts[] = '</div>';

    return implode('', $parts);
}
