<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\ReportWaypointRequest;
use App\Models\Report;
use App\Models\ReportWaypoint;
use App\Models\Item;
use App\Models\Type;
use App\Models\Billing;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Common\SendErrorMessage;
use Illuminate\Support\Facades\Mail;
use App\Mail\MailEmergency;

class EmergencyController extends Controller
{
  public function index(Request $request)
    {
        // チェックポイント保存
        session(['checkpoint-second' => url()->full()]);

        // パラメータ取得
        $params = $request->all();

        // パラメータ初期値
        if (empty($params['sort'])) {
          $params['sort'] = 'report_waypoints.id';
          $params['direction'] = 'asc';
        }

        // ページネーション設定
        // $page_max = config('const.DEFAULT_PAGE_MAX');
        $page_max = 10;

        // クエリ成形
        $report_waypointQuery = ReportWaypoint::query();
        $report_waypointQuery = $report_waypointQuery->where('report_waypoints.emergency', '=', '1');

        // DBよりReportWaypintテーブルの値を検索
        $report_waypoints = $report_waypointQuery
            ->join('reports', 'report_waypoints.report_id', '=', 'reports.id')
            ->whereDate('reports.start_at', '=', date('Y-m-d', strtotime('today')))
            ->orderBy($params['sort'], $params['direction'])
            ->paginate($page_max);
            
        // 取得した値をビュー「_emergency/index」に渡す
        return view('_emergency/index')
            ->with([
                'report_waypoints' => $report_waypoints,
                'params' => $params,
            ]);
    }

    public function create()
    {
        // 空の$report_waypointを渡す
        $report_waypoint = new ReportWaypoint();

        // セレクトボックス用にItemsを取得
        $items = Item::get();

        // セレクトボックス用にTypesを取得
        $types = Type::get();

        // セレクトボックス用にBillingsを取得
        $billings = Billing::get();

        // セレクトボックス用にReportsを取得
        $today_reports = Report::whereDate('start_at', '=', date('Y-m-d', strtotime('today')))->get();

        return view('_emergency/create', compact('report_waypoint', 'items', 'types', 'billings', 'today_reports'));
    }

    public function store(ReportWaypointRequest $request)
    {
        // エラーメッセージ
        $error_messages = [];
        if (empty($request->report_id)) {
          $error_messages[] = '運転者が割り当てられていません。「自動割り当て」から割り当てを実行してください。';
        }
        if (!empty($error_messages)) {
          return SendErrorMessage::validationException($request, $error_messages);
        }

        $report_waypoint = new ReportWaypoint();
        $report_waypoint->report_id = $request->report_id;
        $report_waypoint->take_up = $request->take_up;
        $report_waypoint->take_down = $request->take_down;
        $report_waypoint->item_name = $request->item_name;
        $report_waypoint->quantity = $request->quantity;
        $report_waypoint->unit = $request->unit;
        $report_waypoint->unit_price = $request->unit_price;
        $report_waypoint->type_id = $request->type_id;
        $report_waypoint->billing_id = $request->billing_id;
        $report_waypoint->billing_disposal_name = $request->billing_disposal_name;
        $report_waypoint->highway_money = $request->highway_money;
        $report_waypoint->highway_payment = $request->highway_payment;
        $report_waypoint->emergency = $request->emergency;
        $report_waypoint->address = $request->address;
        $report_waypoint->save();
    
        // Send E-Mail
        $sent = false;
        $report = Report::findOrFail($request->report_id);
        if (!empty($report->user->email)) {
          $mail_text = "\n";
          // $mail_text .= \Lang::get('db.report_waypoint.take_up') . ' : ' . $request->take_up . "\n";
          // $mail_text .= \Lang::get('db.report_waypoint.take_down') . ' : ' . $request->take_down . "\n";
          // $mail_text .= \Lang::get('db.report_waypoint.quantity') . ' : ' . $request->quantity . config('const.UNITS.'.$request->unit) . "\n";
          // $mail_text .= \Lang::get('db.report_waypoint.address') . ' : ' . $request->address . "\n";

          // IDの簡易暗号化
          $encrypt = $this->encrypt_decrypt('encrypt', $request->report_id);
          $url = route('view.emergency.details', ['reportId' => $encrypt]);

          Mail::to($report->user->email)->send(new MailEmergency($url));
          if (count(Mail::failures()) == 0) {
            $sent = true;
          };
        }

        // return redirect(session()->get('checkpoint-second') ?? './');
        // return redirect('/emergency/sendmail');
        return view('_emergency/sendmail', compact('sent'));
      }

    public function getReportId(Request $request)
    {
      // 返り値初期化
      $result = array('status'=>"fail");

      // 住所から都道府県と市区町村を分離
      $matches = array();
      if (!empty($request->address)) {
        preg_match('/(東京都|北海道|(?:京都|大阪)府|.{6,9}県)((?:四日市|廿日市|野々市|臼杵|かすみがうら|つくばみらい|いちき串木野)市|(?:杵島郡大町|余市郡余市|高市郡高取)町|.{3,12}市.{3,12}区|.{3,9}区|.{3,15}市(?=.*市)|.{3,15}市|.{6,27}町(?=.*町)|.{6,27}町|.{9,24}村(?=.*村)|.{9,24}村)(.*)/', $request->address, $matches);
      }

      // 市区町村から検索文字列を整形
      $search = '';
      if (!empty($matches[2])) {
        // 検索文字列を抽出
        $search = $matches[2];
        // 一部の区や町が後ろにくっついてくる住所は先頭の市や郡だけで検索する
        if (strpos($search, '名古屋市') === 0) {
          $search = '名古屋市';   // 北名古屋市は名古屋市に該当しない
        }
        if (strpos($search, '丹羽郡') === 0) {
          $search = '丹羽郡';
        }
      }

      // 検索文字列から検索ターゲットの作成
      $targets = array();
      if (!empty($search)) {
        // 最初は検索ターゲット＝検索文字列の1件とする
        $targets = array($search);
        // 検索文字列がエリアに含まれる場合はそのエリアを検索ターゲットに追加する
        $area1 = array('江南市', '丹羽郡', '小牧市', '犬山市', '春日井市', '瀬戸市', '岩倉市', '北名古屋市', '西春日井郡豊山町', '一宮市');
        if (in_array($search, $area1)) {
          $targets = array_merge($targets, $area1);
        }
        $area2 = array('名古屋市', '清須市', '長久手市', '日進市', '尾張旭市', '愛知郡東郷町', '豊明市', 'みよし市', '刈谷市', '東海市', '大府市', '知多市', '愛知郡東浦町');
        if (in_array($search, $area2)) {
          $targets = array_merge($targets, $area2);
        }
        $area3 = array('愛西市', '弥冨市', '海部郡蟹江町', '海部郡大治町', '稲沢市', '海部郡飛島村', '津島市', 'あま市');
        if (in_array($search, $area3)) {
          $targets = array_merge($targets, $area3);
        }
        // 検索ターゲットの重複を削除する
        $targets = array_values(array_unique($targets));
      }
      
      // 検索ターゲットが存在する場合に検索を実行する
      if (!empty($targets)) {
        // クエリ整形
        $report_waypointQuery = ReportWaypoint::query();
        // 他の条件とAND検索するグループを作成
        $report_waypointQuery = $report_waypointQuery->where(function($query) use($targets) {
          // 全ての検索ターゲットをOR検索
          foreach ($targets as $target) {
            $query->orWhere('report_waypoints.address', 'like', '%'.$target.'%');
          }
        });
        // DBよりReportWaypintテーブルの値を検索
        $report_waypoints = $report_waypointQuery
            ->join('reports', 'report_waypoints.report_id', '=', 'reports.id')
            ->whereDate('reports.start_at', '=', date('Y-m-d', strtotime('today')))
            ->orderBy('report_waypoints.id', 'asc');
        // 返り値作成
        $data = $report_waypoints->get()->toArray();
        if (!empty($data)) {
          $result = array('status'=>"success", 'data'=>$data[0]['report_id']);
        }
      }

      $json = json_encode($result);

      return $json;
    }

    public function details($reportId)
    {
        // IDの簡易復号化
        $decrypt = $this->encrypt_decrypt('decrypt', $reportId);

        // 復号化に失敗した場合は403
        if (!$decrypt) {
          abort(403, 'Unauthorized action');
        }

        // DBよりURIパラメータと同じIDを持つReportの情報を取得
        // findOrFailにより、指定のIDが存在しない場合は404になる
        $id = $decrypt;
        $report = Report::findOrFail($id);

        // 最後に発信された緊急配車を取得
        $report_waypoint_emergency = $report->waypoints()
          ->whereNotNull('emergency')
          ->orderBy('created_at', 'desc')
          ->first();

        // 緊急配車が無い、消されたなどの場合には404とする
        if (empty($report_waypoint_emergency)) {
          abort(404);
        }

        // 現在日時との差分を取得
        $elapsed = strtotime(date("Y-m-d H:i:s")) - strtotime($report_waypoint_emergency->created_at->format('Y-m-d H:i:s'));
        // 48時間経過している場合は403とする
        if ($elapsed > (60 * 60 * 48)) {
          abort(403, 'expired');
        }

        // 取得した値をビューに渡す
        return view('_emergency/details', compact('report'));
    }

    public static function encrypt_decrypt($action, $string)
    {
        /* =================================================
         * ENCRYPTION-DECRYPTION
         * =================================================
         * ENCRYPTION: encrypt_decrypt('encrypt', $string);
         * DECRYPTION: encrypt_decrypt('decrypt', $string) ;
         */
         
        $output = false;
        $encrypt_method = "AES-256-CBC";
        $secret_key = 'MnL5ASaWWRjjUQEe.XADR7Ci/6L6H-qm3LUwMJrv7JTJbP1JT1YYRvjUQdL:hPuA';
        $secret_iv = '2022.08.22';
        // hash
        $key = hash('sha256', $secret_key);
        // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
        $iv = substr(hash('sha256', $secret_iv), 0, 16);
        if ($action == 'encrypt') {
          $output = bin2hex(openssl_encrypt($string, $encrypt_method, $key, 0, $iv));
        }
        if ($action == 'decrypt') {
          try {
            $output = openssl_decrypt(hex2bin($string), $encrypt_method, $key, 0, $iv);
          } catch (\Exception $e) {
            return false;
          }
        }
        return $output;
    }

}
