<?php
/**
 * File AuthController.php
 *
 * @author Tuan Duong <bacduong@gmail.com>
 * @package Laravue
 * @version 1.0
 */

namespace App\Http\Controllers;

use App\UserCard;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Http\Resources\UserResource;
use Illuminate\Support\Facades\Cache;
use App\BlockIP;
use App\Laravue\JsonResponse;
use App\User;
use Mail;
use Validator;
use Payjp\Payjp;

/**
 * Class AuthController
 *
 * @package App\Http\Controllers
 */
class AuthController extends Controller
{
	/**
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function login(Request $request)
	{
		$credentials = $request->only('email', 'password');
		$ip = null;
		if (config('block_ip.admin_ip_block')) {
			$ip = BlockIP::where('is_deleted', 0)->where('is_activated', 1)->where('ip', $request->ip())->first();
			if (!$ip) {
				return response()->json(new JsonResponse([], 'block_this_ip'), Response::HTTP_UNAUTHORIZED);
			}
		}
		
		$verifyCode = trim(str_replace("-", "", $request->get('code')));
		if ($verifyCode == null || $verifyCode == "") {
			return response()->json(new JsonResponse([], __('messages.verify_code_not_valid')), Response::HTTP_UNAUTHORIZED);
		} else {
			$user = User::where('is_activated', true)
				->where('is_deleted', false)
				->where('email', $request->get('email'))
				->first();
			
			if (!$user) return response()->json(new JsonResponse([], __('messages.email_or_password_incorrect')), Response::HTTP_UNAUTHORIZED);
			if (!Hash::check($request->get('password'), $user->password)) return response()->json(new JsonResponse([], __('messages.email_or_password_incorrect')), Response::HTTP_UNAUTHORIZED);
			if ($user->verify_code != $verifyCode) {
				return response()->json(new JsonResponse([], __('messages.verify_code_not_valid')), Response::HTTP_UNAUTHORIZED);
			} else {
				$finishTime = Carbon::parse($user->verify_created_at)->addMinutes(5);
				if ($finishTime < Carbon::now()) {
					return response()->json(new JsonResponse([], __('messages.verify_code_expired')), Response::HTTP_UNAUTHORIZED);
				}
			}
		}
		
		if (!Auth::attempt($credentials)) {
			if (config('block_ip.admin_ip_block') && $ip != null) {
				$ip->incorrect += 1;
				$ip->save();
				
				if ($ip->incorrect >= 10) {
					$ip->update(['is_activated' => 0, 'updated_at' => date('Y-m-d H:i:s')]);
					Cache::forget('white-ips');
					
					return response()->json(new JsonResponse([], 'block_this_ip'), Response::HTTP_UNAUTHORIZED);
				}
			}
			
			return response()->json(new JsonResponse([], __('messages.account_and_password_incorrect')), Response::HTTP_UNAUTHORIZED);
		}
		
		if (config('block_ip.admin_ip_block') && $ip != null) {
			$ip->update(['incorrect' => 0, 'updated_at' => date('Y-m-d H:i:s')]);
		}
		
		$user = $request->user();
		$token = $user->createToken('laravue');
		
		return response()->json(new UserResource($user), Response::HTTP_OK)->header('Authorization', $token->plainTextToken);
	}
	
	public function loginUser(Request $request)
	{
		$credentials = $request->only('email', 'password');
		if (!Auth::attempt($credentials)) {
			return response()->json(new JsonResponse([], 'アカウントが間違っています。'), Response::HTTP_UNAUTHORIZED);
		}
		
		$user = $request->user();
		$token = $user->createToken('laravue');
		
		return response()->json(new UserResource($user), Response::HTTP_OK)->header('Authorization', $token->plainTextToken);
	}
	
	public function logout(Request $request)
	{
		$request->user()->tokens()->delete();
		return response()->json((new JsonResponse())->success([]), Response::HTTP_OK);
	}
	
	public function user()
	{
		return new UserResource(Auth::user());
	}
	
	public function getUser(Request $request)
	{
		return $request->user();
	}
	
	public function verify(Request $request)
	{
		$params = $request->all();
		$ip = null;
		if (config('block_ip.admin_ip_block')) {
			$ip = BlockIP::where('is_deleted', 0)->where('is_activated', 1)->where('ip', $request->ip())->first();
			if (!$ip) {
				return response()->json(new JsonResponse([], 'block_this_ip'), Response::HTTP_UNAUTHORIZED);
			}
		}
		
		$user = User::where('is_activated', true)
			->where('is_deleted', false)
			->where('email', $params['email'])
			->first();
		
		if (!$user) {
			if (config('block_ip.admin_ip_block') && $ip != null) {
				$ip->incorrect += 1;
				$ip->save();
				
				if ($ip->incorrect >= 10) {
					$ip->update(['is_activated' => 0, 'updated_at' => date('Y-m-d H:i:s')]);
					Cache::forget('white-ips');
					
					return response()->json(new JsonResponse([], 'block_this_ip'), Response::HTTP_UNAUTHORIZED);
				}
			}
			
			return response()->json(['status' => 'error', 'email' => '', 'message' => __('messages.email_or_password_incorrect')], 200);
		} else {
			if (!Hash::check($params['password'], $user->password)) {
				if (config('block_ip.admin_ip_block') && $ip != null) {
					$ip->incorrect += 1;
					$ip->save();
					
					if ($ip->incorrect >= 10) {
						$ip->update(['is_activated' => 0, 'updated_at' => date('Y-m-d H:i:s')]);
						Cache::forget('white-ips');
						
						return response()->json(new JsonResponse([], 'block_this_ip'), Response::HTTP_UNAUTHORIZED);
					}
				}
				
				return response()->json(['status' => 'error', 'email' => '', 'message' => __('messages.email_or_password_incorrect')], 200);
			}
		}
		
		//$verifyCode = rand(111, 999) . rand(111, 999);
		$verifyCode = '123456'; // Testing
		$user->update(['verify_code' => $verifyCode, 'verify_created_at' => date('Y-m-d H:i:s')]);
		$userEmail = ($user->id == 1) ? config('settings.admin_email') : $user->email;
		
		$data = [
			'site'          => url("/"),
			'name'          => $user->name,
			'first_name'    => $user->first_name,
			'last_name'     => $user->last_name,
			'full_name'     => $user->full_name,
			'furigana_name' => $user->furigana_name,
			'code'          => $verifyCode,
		];
		
		try {
			if (config('app.url') == "http://127.0.0.1:8000" || config('app.url') == "http://localhost") {
				return response()->json(['status' => 'success', 'email' => $userEmail, 'message' => 'success', 'code' => $verifyCode], 200);
			}
			
			Mail::send('emails.verify_email', $data, function ($message) use ($userEmail) {
				$message->from(config('mail.from.address'), config('mail.from.name'));
				$message->to($userEmail);
				$message->subject("【KIREI】管理者ログインの確認");
			});
			
			return response()->json(['status' => 'success', 'email' => $userEmail, 'message' => 'success'], 200);
		} catch (\Exception $exception) {
			logger($exception->getMessage());
			return response()->json(['status' => 'error', 'email' => null, 'message' => __('messages.email_or_password_incorrect')], 200);
		}
	}
	
	public function registerCard(Request $request)
	{
		$validator = Validator::make($request->all(), [
			'card_number'  => ['required'],
			'card_exp'     => ['required'],
			'card_cvc'     => ['required'],
		]);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$params = $request->all();

		$user = Auth::user();

		// Parse card expiry (MM/YY format)
		$cardExp = explode('/', $params['card_exp']);
		$expMonth = $cardExp[0];
		$expYear = '20' . $cardExp[1];

		// Khởi tạo PayJP
		Payjp::setApiKey(config('payjp.secret_key'));

		try {
			// Tạo token từ raw card data (cần option đặc biệt)
			$cardNumber = str_replace(' ', '', $params['card_number']);
			$tokenResponse = \Payjp\Token::create([
				'card' => [
					'number'    => $cardNumber,
					'exp_month' => $expMonth,
					'exp_year'  => $expYear,
					'cvc'       => $params['card_cvc'],
					'name'      => $params['card_name'] ?? ''
				]
			], [
				'payjp_direct_token_generate' => 'true'
			]);
			$payjpToken = $tokenResponse->id;

			// Kiểm tra hoặc tạo PayJP customer
			$payjpCustomer = null;
			if ($user->payjp_customer_id) {
				try {
					$payjpCustomer = \Payjp\Customer::retrieve($user->payjp_customer_id);
				} catch (\Exception $e) {
					// Customer không tồn tại
				}
			}

			if (!$payjpCustomer) {
				// Tạo customer mới với thẻ
				$payjpCustomer = \Payjp\Customer::create([
					"email" => $user->email,
					"card"  => $payjpToken
				]);
				$user->payjp_customer_id = $payjpCustomer->id;
				$user->save();

				// Lấy card ID vừa tạo
				$payjpCardId = $payjpCustomer->default_card;
			} else {
				// Thêm thẻ mới cho customer đã tồn tại
				$newCard = $payjpCustomer->cards->create([
					"card" => $payjpToken
				]);
				$payjpCardId = $newCard->id;
			}

			// Lấy thông tin thẻ từ PayJP
			$payjpCard = $payjpCustomer->cards->retrieve($payjpCardId);
			$cardLastFour = $payjpCard->last4;
			$cardExpMonth = str_pad($payjpCard->exp_month, 2, '0', STR_PAD_LEFT);
			$cardExpYear = substr($payjpCard->exp_year, -2);
			$cardBrand = $payjpCard->brand ?? 'Credit Card';
			$cardBrandLogo = strtolower(str_replace(' ', '_', $cardBrand)) . '.png';
			$cardName = $payjpCard->name ?? ($params['card_name'] ?? '');

			// Kiểm tra thẻ đã tồn tại trong DB chưa (theo payjp_card_id)
			$existingCard = UserCard::where('user_id', $user->id)
				->where('payjp_card_id', $payjpCardId)
				->where('is_deleted', 0)
				->first();

			if ($existingCard) {
				return response()->json(['errors' => 'カードはすでに登録されています。'], 403);
			}

			// Lưu thông tin thẻ vào DB (không lưu card_number, cvc)
			$card = UserCard::create([
				'user_id'         => $user->id,
				'payjp_card_id'   => $payjpCardId,
				'card_number'     => null,
				'card_exp_month'  => $cardExpMonth,
				'card_exp_year'   => $cardExpYear,
				'card_cvc'        => null,
				'card_last_four'  => $cardLastFour,
				'card_name'       => $cardName,
				'card_brand'      => $cardBrand,
				'card_brand_logo' => $cardBrandLogo,
				'created_at'      => date('Y-m-d H:i:s'),
				'updated_at'      => date('Y-m-d H:i:s'),
			]);

			return response()->json(['status' => 'success', 'card_id' => $card->id], 200);

		} catch (\Payjp\Error\Card $e) {
			return response()->json(['errors' => 'カード情報が無効です。'], 403);
		} catch (\Exception $e) {
			logger('RegisterCard error: ' . $e->getMessage());
			return response()->json(['errors' => 'カードの登録に失敗しました。'], 500);
		}
	}
	
	public function updateCard(Request $request, UserCard $card)
	{
		$validator = Validator::make($request->all(), [
			'card_expiry' => ['required'],
			'card_cvc'    => ['required'],
			'card_name'   => ['required']
		]);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		
		if ($card->user_id != Auth::user()->id) {
			return response()->json(['status' => 'error', 'errors' => '無効なカードです。'], 403);
		}
		
		$params = $request->all();
		$cardExp = explode("/", $params['card_expiry']);
		$cardExpMonth = $cardExp[0];
		$cardExpYear = $cardExp[1];
		
		$card->update([
			'card_exp_month' => $cardExpMonth,
			'card_exp_year'  => $cardExpYear,
			'card_cvc'       => $params['card_cvc'],
			'card_name'      => $params['card_name'],
			'updated_at'     => date('Y-m-d H:i:s'),
		]);
		
		return response()->json(['status' => 'success'], 200);
	}
	
	public function updateCardDefault($id)
	{
		$card = UserCard::where('user_id', Auth::user()->id)->where('id', $id)->first();
		if (!$card) {
			return response()->json(['status' => 'error', 'errors' => '無効なカードです。'], 403);
		}
		
		UserCard::where('user_id', Auth::user()->id)->update(['is_default' => 0]);
		$card->update(['is_default' => 1]);
		
		return response()->json(['status' => 'success'], 200);
	}
	
	public function removeCard($id)
	{
		$card = UserCard::where('user_id', Auth::user()->id)->where('id', $id)->first();
		if (!$card) {
			return response()->json(['status' => 'error', 'errors' => '無効なカードです。'], 403);
		}
		
		$card->update(['is_activated' => 0, 'is_deleted' => 1]);
		if ($card->is_default == 1) {
			$card->update(['is_default' => 0]);
			$firstCard = UserCard::where('user_id', Auth::user()->id)
				->where('is_activated', 1)
				->where('is_deleted', 0)
				->orderBy('id')
				->first();
			if ($firstCard) $firstCard->update(['is_default' => 1]);
		}
		
		return response()->json(['status' => 'success'], 200);
	}
	
	private function detectCreditCardBrand($number)
	{
		$patterns = [
			'Visa'             => '/^4[0-9]{12}(?:[0-9]{3})?$/',
			'MasterCard'       => '/^5[1-5][0-9]{14}$/',
			'American Express' => '/^3[47][0-9]{13}$/',
			'Discover'         => '/^6(?:011|5[0-9]{2})[0-9]{12}$/',
			'Diners Club'      => '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
			'JCB'              => '/^(?:2131|1800|35\d{3})\d{11}$/'
		];
		
		foreach ($patterns as $brand => $pattern) {
			if (preg_match($pattern, $number)) {
				return $brand;
			}
		}
		
		return 'Credit Card';
	}
	
	private function detectCreditCardBrandLogo($number)
	{
		$patterns = [
			'visa'        => '/^4[0-9]{12}(?:[0-9]{3})?$/',
			'mastercard'  => '/^5[1-5][0-9]{14}$/',
			'amex'        => '/^3[47][0-9]{13}$/',
			'discover'    => '/^6(?:011|5[0-9]{2})[0-9]{12}$/',
			'diners_club' => '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
			'jcb'         => '/^(?:2131|1800|35\d{3})\d{11}$/'
		];
		
		foreach ($patterns as $brand => $pattern) {
			if (preg_match($pattern, $number)) {
				return $brand . '.png';
			}
		}
		
		return 'card.png';
	}
}
