<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Http\Resources\DeliveryAddressResource;
use App\DeliveryAddress;
use Validator;

class AddressController extends Controller
{
	const ITEM_PER_PAGE = 20;
	private $_user;
	
	public function __construct()
	{
		$this->_user = auth('api')->user();
	}
	
	public function index(Request $request)
	{
		$searchParams = $request->all();
		$list = DeliveryAddress::where('user_id', $this->_user->id)->where('is_hidden', 0);
		$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
		$keyword = Arr::get($searchParams, 'keyword', '');
		
		if (!empty($keyword)) {
			$list->where(function ($query) use ($keyword) {
				$query->where('first_name', 'LIKE', '%' . $keyword . '%')
					->orWhere('last_name', 'LIKE', '%' . $keyword . '%')
					->orWhere('furigana_first_name', 'LIKE', '%' . $keyword . '%')
					->orWhere('furigana_last_name', 'LIKE', '%' . $keyword . '%')
					->orWhere('post_code', 'LIKE', '%' . $keyword . '%')
					->orWhere('district', 'LIKE', '%' . $keyword . '%')
					->orWhere('city', 'LIKE', '%' . $keyword . '%')
					->orWhere('address', 'LIKE', '%' . $keyword . '%')
					->orWhere('phone_number', 'LIKE', '%' . $keyword . '%')
					->orWhere('email', 'LIKE', '%' . $keyword . '%');
			});
		}
		
		$list->orderBy('id', 'DESC');
		
		return DeliveryAddressResource::collection($list->paginate($limit));
	}
	
	public function show($id = 0)
	{
		// is_hidden=1 は注文スナップショット（住所帳には出さない行）なので参照させない
		$address = DeliveryAddress::where('user_id', $this->_user->id)
			->where('is_hidden', 0)
			->where('id', $id)
			->first();
		if (!isset($address)) return response()->json(['errors' => 'Address is not valid'], 403);

		return new DeliveryAddressResource($address);
	}
	
	public function store(Request $request)
	{
		$validator = Validator::make($request->all(), [
			'first_name'          => ['required'],
			'last_name'           => ['required'],
			'furigana_first_name' => ['required'],
			'furigana_last_name'  => ['required'],
			'post_code'           => ['required'],
			'address'             => ['required'],
			'address2'            => ['required'],
			'address3'            => ['required'],
			'phone_number'        => ['required'],
			'email'               => ['nullable', 'email'],
		]);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		
		$params = $request->all();
		$address = DeliveryAddress::create([
			'first_name'          => $params['first_name'],
			'last_name'           => $params['last_name'],
			'furigana_first_name' => $params['furigana_first_name'],
			'furigana_last_name'  => $params['furigana_last_name'],
			'post_code'           => $params['post_code'],
			'district'            => $params['address'],
			'city'                => $params['address2'],
			'address'             => $params['address3'],
			'phone_number'        => $params['phone_number'],
			'email'               => (isset($params['email']) && $params['email'] != null) ? $params['email'] : $this->_user->email,
			'company'             => $params['company'] ?? null,
			'user_id'             => $this->_user->id,
			'is_default'          => false,
			'is_other_address'    => true,
			'created_at'          => date('Y-m-d H:i:s'),
			'updated_at'          => date('Y-m-d H:i:s')
		]);
		
		return new DeliveryAddressResource($address);
	}
	
	public function update(Request $request, $id = 0)
	{
		$validator = Validator::make($request->all(), [
			'first_name'          => ['required'],
			'last_name'           => ['required'],
			'furigana_first_name' => ['required'],
			'furigana_last_name'  => ['required'],
			'post_code'           => ['required'],
			'address'             => ['required'],
			'address2'            => ['required'],
			'address3'            => ['required'],
			'phone_number'        => ['required'],
			'email'               => ['nullable', 'email']
		]);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		
		$address = DeliveryAddress::where('user_id', $this->_user->id)->where('id', $id)->first();
		if (!isset($address)) return response()->json(['errors' => 'Address is not valid'], 403);

		// 注文に紐づく行は配送先スナップショットを兼ねているため、編集前の内容を
		// 非表示行として注文側に残し、編集対象の行は住所帳専用に切り離す
		if ($address->order_id) {
			DeliveryAddress::create([
				'order_id'            => $address->order_id,
				'first_name'          => $address->first_name,
				'last_name'           => $address->last_name,
				'furigana_first_name' => $address->furigana_first_name,
				'furigana_last_name'  => $address->furigana_last_name,
				'post_code'           => $address->post_code,
				'district'            => $address->district,
				'city'                => $address->city,
				'address'             => $address->address,
				'phone_number'        => $address->phone_number,
				'mobile_tel'          => $address->mobile_tel,
				'email'               => $address->email,
				'company'             => $address->company,
				'user_id'             => $address->user_id,
				'is_default'          => 0,
				'is_other_address'    => $address->is_other_address,
				'is_hidden'           => 1,
				'created_at'          => $address->created_at,
				'updated_at'          => date('Y-m-d H:i:s'),
			]);
			$address->order_id = null;
		}

		$params = $request->all();
		$address->update([
			'first_name'          => $params['first_name'],
			'last_name'           => $params['last_name'],
			'furigana_first_name' => $params['furigana_first_name'],
			'furigana_last_name'  => $params['furigana_last_name'],
			'post_code'           => $params['post_code'],
			'district'            => $params['address'],
			'city'                => $params['address2'],
			'address'             => $params['address3'],
			'phone_number'        => $params['phone_number'],
			'email'               => (isset($params['email']) && $params['email'] != null) ? $params['email'] : $this->_user->email,
			'company'             => $params['company'] ?? null,
			'updated_at'          => date('Y-m-d H:i:s')
		]);
		
		return response()->json(null, 204);
	}
	
	public function destroy($id = 0)
	{
		$address = DeliveryAddress::where('user_id', $this->_user->id)->where('id', $id)->first();
		if (!isset($address)) return response()->json(['error' => 'Can not delete this address'], 403);

		try {
			// 注文に紐づく行は管理画面の注文一覧・配送情報の表示元になっているため
			// 物理削除せず住所帳から非表示にする
			if ($address->order_id) {
				// 既定住所を非表示にすると「既定が無い」状態になるためフラグを落とす
				$wasDefault = (int) $address->is_default === 1;
				$address->update(['is_hidden' => 1, 'is_default' => 0, 'updated_at' => date('Y-m-d H:i:s')]);

				// 別の可視住所があれば既定に昇格させる
				if ($wasDefault) {
					$promote = DeliveryAddress::where('user_id', $this->_user->id)
						->where('is_hidden', 0)
						->orderBy('id', 'desc')
						->first();
					if ($promote) {
						$promote->update(['is_default' => 1, 'updated_at' => date('Y-m-d H:i:s')]);
					}
				}
			} else {
				$address->delete();
			}
		} catch (\Exception $ex) {
			return response()->json(['error' => $ex->getMessage()], 403);
		}

		return response()->json(null, 204);
	}
}
