<?php

namespace App\Services;

use Exception;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

/**
 * Google Maps API サービス
 * SHJ-1本人確認自動処理で距離計算に使用
 */
class GoogleMapsService
{
    protected $apiKey;
    protected $baseUrl;
    protected $config;

    public function __construct()
    {
        $this->apiKey = config('shj1.apis.google_maps.api_key');
        $this->baseUrl = config('shj1.apis.google_maps.base_url');
        $this->config = config('shj1.distance.google_maps_config');
    }

    /**
     * 2点間の距離を計算（Google Maps Distance Matrix API使用）
     * 
     * @param string $origin 出発地（住所）
     * @param string $destination 目的地（住所）
     * @return array ['distance_meters' => int, 'distance_text' => string, 'status' => string]
     * @throws Exception
     */
    public function calculateDistance(string $origin, string $destination): array
    {
        try {
            $url = "{$this->baseUrl}/distancematrix/json";
            
            $params = [
                'origins' => $origin,
                'destinations' => $destination,
                'units' => $this->config['units'] ?? 'metric',
                'mode' => $this->config['mode'] ?? 'walking',
                'language' => $this->config['language'] ?? 'ja',
                'region' => $this->config['region'] ?? 'jp',
                'key' => $this->apiKey,
            ];

            $response = Http::timeout(30)->get($url, $params);

            if (!$response->successful()) {
                throw new Exception("Google Maps API request failed: " . $response->status());
            }

            $data = $response->json();

            // APIエラーチェック
            if ($data['status'] !== 'OK') {
                throw new Exception("Google Maps API error: " . $data['status']);
            }

            $element = $data['rows'][0]['elements'][0];

            if ($element['status'] !== 'OK') {
                throw new Exception("Distance calculation failed: " . $element['status']);
            }

            return [
                'distance_meters' => $element['distance']['value'],
                'distance_text' => $element['distance']['text'],
                'duration_text' => $element['duration']['text'] ?? null,
                'status' => 'success'
            ];

        } catch (Exception $e) {
            Log::error('Google Maps distance calculation error', [
                'origin' => $origin,
                'destination' => $destination,
                'error' => $e->getMessage()
            ]);

            throw $e;
        }
    }

    /**
     * 住所から座標を取得（Geocoding API使用）
     * 
     * @param string $address 住所
     * @return array ['lat' => float, 'lng' => float]
     * @throws Exception
     */
    public function geocodeAddress(string $address): array
    {
        try {
            $url = "{$this->baseUrl}/geocode/json";
            
            $params = [
                'address' => $address,
                'language' => $this->config['language'] ?? 'ja',
                'region' => $this->config['region'] ?? 'jp',
                'key' => $this->apiKey,
            ];

            $response = Http::timeout(30)->get($url, $params);

            if (!$response->successful()) {
                throw new Exception("Google Geocoding API request failed: " . $response->status());
            }

            $data = $response->json();

            if ($data['status'] !== 'OK') {
                throw new Exception("Google Geocoding API error: " . $data['status']);
            }

            $location = $data['results'][0]['geometry']['location'];

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

        } catch (Exception $e) {
            Log::error('Google Maps geocoding error', [
                'address' => $address,
                'error' => $e->getMessage()
            ]);

            throw $e;
        }
    }

    /**
     * 座標から直線距離を計算（Haversine formula）
     * Google Maps APIが利用できない場合のフォールバック
     * 
     * @param float $lat1 緯度1
     * @param float $lon1 経度1
     * @param float $lat2 緯度2
     * @param float $lon2 経度2
     * @return int 距離（メートル）
     */
    public function calculateStraightLineDistance(float $lat1, float $lon1, float $lat2, float $lon2): int
    {
        $earthRadius = 6371000; // 地球の半径（メートル）

        $dLat = deg2rad($lat2 - $lat1);
        $dLon = deg2rad($lon2 - $lon1);

        $a = sin($dLat / 2) * sin($dLat / 2) +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($dLon / 2) * sin($dLon / 2);

        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
        $distance = $earthRadius * $c;

        return round($distance);
    }

    /**
     * 距離詳細文字列を生成（SHJ-1の要求仕様に準拠）
     * 
     * @param int $parkId 駐輪場ID
     * @param int $distanceMeters 距離（メートル）
     * @param string $method 計算方法
     * @return string
     */
    public function generateDistanceDetailString(int $parkId, int $distanceMeters, string $method = 'google_maps'): string
    {
        return $parkId . "/" . $parkId . "/二点間距離：" . $distanceMeters . "m (" . $method . ")";
    }

    /**
     * APIキーが設定されているかチェック
     * 
     * @return bool
     */
    public function isApiKeyConfigured(): bool
    {
        $dummyKey = env('GOOGLE_MAPS_API_KEY') === 'dummy_google_maps_api_key_replace_with_real_one';
        return !empty($this->apiKey) && !$dummyKey;
    }
}
