<?php

namespace App\Services;

use App\Models\MstCity;
use App\Models\MstPrefecture;
use App\Models\MstTown;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;

class AddressParserService
{
    public static function strToAddress($str, $building){
        $data = self::geocode($str);

        $results = [
            'pref' => null,
            'city' => null,
            'town' => null,
            'towns' => [],
            'cities' => [],
            'data' => $data,
            'address' => '',
            'postcode' => ''
        ];
        $longNames = [];
        $locality = '';
        $sublocality_level_1 = '';
        $sublocality_level_2 = '';
        $sublocality_level_3 = '';
        $sublocality_level_4 = '';
        $sublocality_level_3_list = [];
        $premise = '';
        if ($data->status === 'OK'){
            if (isset($data->results)){
              $resultCount = count($data->results);
              $addressComponents = [];
          
              if ($resultCount === 1) {
                  $addressComponents = current($data->results)->address_components;
              } elseif ($resultCount > 1) {
                  $geoCode =self::geocode($str . $building);
                  
                  if ($geoCode->status === 'OK' && isset($geoCode->results)) {
                      $geoResultCount = count($geoCode->results);
                      
                      if ($geoResultCount === 1) {
                          $addressComponents = current($geoCode->results)->address_components;
                      } else {
                          $specialList = configProject('google_map_address_special_for_csv', []);
                          $addressComponents = in_array($str, $specialList) ? current($geoCode->results)->address_components : last($geoCode->results)->address_components;
                      }
                  }
              }

              foreach (($addressComponents ?? []) as $component){
                      $longNames[] = $component->long_name;

                      if (in_array('locality', $component->types)){
                          $locality = $component->long_name;
                      }
                      if (in_array('sublocality_level_1', $component->types)){
                          $sublocality_level_1 = $component->long_name;
                      }
                      if (in_array('sublocality_level_2', $component->types)){
                          $sublocality_level_2 = $component->long_name;
                      }

                      if (in_array('sublocality_level_3', $component->types)){
                          $sublocality_level_3 = $component->long_name;
                      }

                      if ($sublocality_level_3 !== ''){
                          $level3 = strtr($sublocality_level_3, ["１" => "一" , "２" => "二" , "３" => '三', "４"=> '四' , '５'=> '五', '６' => '六' , '７' => '七' , '８' => '八', '９' => '九' , '１０' => '十'  ]);
                          $longNames[] = $component->long_name.$sublocality_level_3;
                          $longNames[] = $component->long_name.$level3;
                          $longNames[] = $level3;
                          $longNames[] = $sublocality_level_3;

                          $sublocality_level_3_list [] = $level3;
                          $sublocality_level_3_list [] = $sublocality_level_3;
                      }

                      if (in_array('sublocality_level_4', $component->types)){
                          $sublocality_level_4 = $component->long_name;
                      }

                      if (in_array('premise', $component->types)){
                          $premise = $component->long_name;
                      }
                      if (in_array('postal_code', $component->types)){
                          $results['postcode'] = $component->long_name;
                      }
                  }
              if ($sublocality_level_1 != '' && $locality != ''){
                  $longNames [] = $locality.$sublocality_level_1;
              }
              $results['pref'] = MstPrefecture::whereIn('name', $longNames)->first();
              $results['city'] = MstCity::whereIn('name', $longNames)->where('pref_code', ($results['pref']->code ?? ''))->first();
              $results['address'] = $sublocality_level_3 .$sublocality_level_4. $premise;
            }

            if (isset($results['pref'])){
                $results['cities'] = MstCity::getData(['pref_id' => $results['pref']->code]);
            }
            if (isset($results['city'])){
                $results['towns'] = MstTown::getData(['pref_id' => $results['pref']->code, 'city_id' => $results['city']->code]);
            }
            $townName = explode('市', $str)[1] ?? '';
            $orderBy = [];
            if ($townName != ''){
                $longNames[] = $townName;
                $orderBy[] = $townName;
            }
            if ($sublocality_level_2 !== '' || $sublocality_level_3 !== ''){
                $orderBy [] = $sublocality_level_2.$sublocality_level_3;
            }
            if ($sublocality_level_2 != ''){
                $orderBy [] = $sublocality_level_2;
            }
            if (count($orderBy) > 0){
                $orderByStr = implode("', '",$orderBy);
            }

            $townQuery = MstTown::where(function ($sub) use ($longNames){
                    $sub->whereIn('name', $longNames);
                    $sub->orWhereIn('chome_name', $longNames);
                    $sub->orWhereIn('koaza_name', $longNames);
                })
                ->where('pref_code', '=', $results['pref']->code ?? '')
                ->where('city_code', '=', $results['city']->code ?? '');
            if ($sublocality_level_2 !== ''){
                //$townQuery->where('name', $sublocality_level_2);
            }
            if (count($sublocality_level_3_list) > 0){
                $townQuery->whereIn('chome_name', $sublocality_level_3_list);
            }
            if (isset($orderByStr)){
                $townQuery->orderByRaw("FIELD(`name`, '{$orderByStr}')");
            }
            $townFound = $townQuery->first();
            if (!isset($townFound)){
                $townQuery = MstTown::where(function ($sub) use ($longNames){
                    $sub->whereIn('name', $longNames);
                    $sub->orWhereIn('chome_name', $longNames);
                    $sub->orWhereIn('koaza_name', $longNames);
                }) ->where('pref_code', '=', $results['pref']->code ?? '')
                   ->where('city_code', '=', $results['city']->code ?? '');
                if (isset($orderByStr)){
                    $townQuery->orderByRaw("FIELD(`name`, '{$orderByStr}')");
                }
                $townFound = $townQuery->first();
            }
            $results['town'] = $townFound;
        }
        $results['sublocality_level_3'] = $sublocality_level_3;
        return  $results;
    }

    public static function geocode($str){
        $mapUrl = 'https://maps.googleapis.com/maps/api/geocode/json';
        $client = new Client();
        $response = $client->request('GET', $mapUrl, ['query'=> [
            'key' => env('GOOGLE_MAP_API_KEY',''),
            'language'=> 'ja',
            'address' => mb_convert_kana($str, 'N')
        ]]);
        $body = (string)$response->getBody();

        return json_decode($body);
    }
}
