<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Order;
use App\Http\Resources\Admin\OrderResource;
use Validator;

/**
 * Class OrderController
 *
 * @package App\Http\Controllers
 */
class OrderController extends Controller
{
	const ITEM_PER_PAGE = 100;
	
	public function index(Request $request)
	{
		$searchParams = $request->all();
		$list = Order::notDeleted();
		$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
		$keyword = Arr::get($searchParams, 'keyword', '');
		$status = Arr::get($searchParams, 'status', '');
		$paymentDeadlineFilter = Arr::get($searchParams, 'payment_deadline_filter', '');
		$shippingDeadlineFilter = Arr::get($searchParams, 'shipping_deadline_filter', '');
		
		if (!empty($keyword)) {
			$keyword = str_replace("#", "", $keyword);
			$list->where('code', 'LIKE', '%' . $keyword . '%');
		}
		
		if ($status != '') {
			$list->where('status', $status);
		}
		
		// Payment deadline filter (11 days or less from wear date)
		if ($paymentDeadlineFilter == '1') {
			$list->whereHas('order_detail', function ($query) {
				$query->whereNotNull('wear_date')
				      ->whereRaw('DATEDIFF(wear_date, CURDATE()) <= 11');
			});
		}
		
		// Shipping deadline filter
		if ($shippingDeadlineFilter == '6') {
			$list->whereHas('order_detail', function ($query) {
				$query->whereNotNull('wear_date')
				      ->whereRaw('DATEDIFF(wear_date, CURDATE()) <= 6');
			});
		} elseif ($shippingDeadlineFilter == '3') {
			$list->whereHas('order_detail', function ($query) {
				$query->whereNotNull('wear_date')
				      ->whereRaw('DATEDIFF(wear_date, CURDATE()) <= 3');
			});
		}
		
		$list->orderBy('id', 'DESC');
		
		return OrderResource::collection($list->paginate($limit));
	}
	
	public function all(Request $request)
	{
		$searchParams = $request->all();
		$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
		$list = Order::select('id', 'name', 'slug')->notDeleted()->orderBy('id', 'DESC');
		
		return OrderResource::collection($list->paginate($limit));
	}
	
	public function allNested(Request $request)
	{
		$ignoreId = Arr::get($request->all(), 'ignoreId', '');
		$list = Order::select('*')->isPublished();
		
		if ($ignoreId != null && $ignoreId != "") {
			$list = $list->where('id', '!=', $ignoreId);
		}
		
		$list = $list->orderBy('id', 'DESC')->get();
		
		$rs = $this->getChildItems($list, 0);
		
		return response()->json(['data' => $rs], 200);
	}
	
	public function getChildItems($list, $parent = 0)
	{
		$rs = [];
		foreach ($list as $item) {
			if ($item->parent_id == $parent) {
				$cate = ['value' => $item->id, 'label' => $item->name];
				$children = $this->getChildItems($list, $item->id);
				if ($children !== null && count($children) > 0) $cate['children'] = $children;
				$rs[] = $cate;
			}
		}
		
		return $rs;
	}
	
	public function available(Request $request)
	{
		
		$ignoreId = Arr::get($request->all(), 'ignoreId', '');
		$list = Order::select('id', 'name')->isPublished();
		
		if ($ignoreId != null && $ignoreId != "") {
			$list->where('id', '!=', $ignoreId);
		}
		
		$list->orderBy('id');
		
		return OrderResource::collection($list->get());
	}
	
	public function show($id = 0)
	{
		$order = Order::notDeleted()->where('id', $id)->first();
		if (!isset($order)) return response()->json(['errors' => __('messages.order_not_valid')], 403);
		
		return new OrderResource($order);
	}
	
	public function store(Request $request)
	{
		return response()->json(null, 204);
	}
	
	public function update(Request $request, $id = 0)
	{
		$order = Order::notDeleted()->where('id', $id)->first();
		if (!isset($order)) return response()->json(['errors' => __('messages.order_not_valid')], 403);
		$params = $request->all();
		
		// If only status is being updated (old behavior)
		if (isset($params['status']) && count($params) == 1) {
			$validator = Validator::make($request->all(), ['status' => ['required']]);
			if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
			
			$order->update([
				'status'       => $params['status'],
				'is_activated' => false,
				'updated_at'   => date('Y-m-d H:i:s')
			]);
			
			return response()->json(null, 204);
		}
		
		// Full order update (new behavior)
		$validator = Validator::make($request->all(), [
			'payment_method'                         => 'sometimes|integer|in:0,1',
			'payment_status'                         => 'sometimes|integer|in:0,1',
			'status'                                 => 'sometimes|integer|in:0,1,2,3,4,5,6,7,8',
			'delivery.first_name'                    => 'sometimes|string|max:255',
			'delivery.last_name'                     => 'sometimes|string|max:255',
			'delivery.furigana_first_name'           => 'sometimes|string|max:255',
			'delivery.furigana_last_name'            => 'sometimes|string|max:255',
			'delivery.post_code'                     => 'sometimes|string|max:20',
			'delivery.district'                      => 'sometimes|string|max:255',
			'delivery.city'                          => 'sometimes|string|max:255',
			'delivery.address'                       => 'sometimes|string|max:500',
			'delivery.phone_number'                  => 'sometimes|string|max:20',
			'delivery.email'                         => 'sometimes|email|max:255',
			'order_detail'                           => 'sometimes|array',
			'order_detail.*.id'                      => 'required|integer|exists:order_details,id',
			'order_detail.*.wear_date'               => 'sometimes|date',
			'order_detail.*.preferred_delivery_time' => 'sometimes|nullable|string|max:50'
		]);
		
		if ($validator->fails()) {
			return response()->json(['errors' => $validator->errors()], 422);
		}
		
		// Check for payment method change
		$paymentMethodChanged = false;
		$oldPaymentMethod = $order->payment_method;
		$newPaymentMethod = isset($params['payment_method']) ? $params['payment_method'] : $oldPaymentMethod;
		
		if (isset($params['payment_method']) && $oldPaymentMethod != $newPaymentMethod) {
			$paymentMethodChanged = true;
		}
		
		// Update order basic fields
		$orderUpdateData = [];
		if (isset($params['payment_method'])) $orderUpdateData['payment_method'] = $params['payment_method'];
		if (isset($params['payment_status'])) $orderUpdateData['payment_status'] = $params['payment_status'];
		if (isset($params['status'])) $orderUpdateData['status'] = $params['status'];
		
		// Generate payment token if changing to credit card
		if ($paymentMethodChanged && $newPaymentMethod == 1) {
			$orderUpdateData['payment_token'] = \Illuminate\Support\Str::random(32);
			$orderUpdateData['payment_token_expires_at'] = now()->addHours(24);
		}
		
		if (!empty($orderUpdateData)) {
			$orderUpdateData['updated_at'] = date('Y-m-d H:i:s');
			$order->update($orderUpdateData);
		}
		
		// Send email if payment method changed
		if ($paymentMethodChanged && $order->delivery()->exists()) {
			$delivery = $order->delivery()->first();
			$paymentLink = null;
			
			if ($newPaymentMethod == 1) {
				// Changed to credit card - generate payment link
				$paymentLink = url('/payment/' . $order->payment_token);
			}
			
			// Send email notification
			\Mail::to($delivery->email)->send(new \App\Mail\PaymentMethodChangedUser($order, $newPaymentMethod, $paymentLink));
		}
		
		// Update delivery information
		if (isset($params['delivery']) && $order->delivery()->exists()) {
			$delivery = $order->delivery()->first();
			$deliveryData = [];
			
			if (isset($params['delivery']['first_name'])) $deliveryData['first_name'] = $params['delivery']['first_name'];
			if (isset($params['delivery']['last_name'])) $deliveryData['last_name'] = $params['delivery']['last_name'];
			if (isset($params['delivery']['furigana_first_name'])) $deliveryData['furigana_first_name'] = $params['delivery']['furigana_first_name'];
			if (isset($params['delivery']['furigana_last_name'])) $deliveryData['furigana_last_name'] = $params['delivery']['furigana_last_name'];
			if (isset($params['delivery']['post_code'])) $deliveryData['post_code'] = $params['delivery']['post_code'];
			if (isset($params['delivery']['district'])) $deliveryData['district'] = $params['delivery']['district'];
			if (isset($params['delivery']['city'])) $deliveryData['city'] = $params['delivery']['city'];
			if (isset($params['delivery']['address'])) $deliveryData['address'] = $params['delivery']['address'];
			if (isset($params['delivery']['phone_number'])) $deliveryData['phone_number'] = $params['delivery']['phone_number'];
			if (isset($params['delivery']['email'])) $deliveryData['email'] = $params['delivery']['email'];
			
			if (!empty($deliveryData)) {
				$deliveryData['updated_at'] = date('Y-m-d H:i:s');
				$delivery->update($deliveryData);
			}
		}
		
		// Update order details
		if (isset($params['order_detail']) && is_array($params['order_detail'])) {
			foreach ($params['order_detail'] as $itemData) {
				if (isset($itemData['id'])) {
					$orderDetail = \App\OrderDetail::where('id', $itemData['id'])
						->where('order_id', $order->id)
						->first();
					
					if ($orderDetail) {
						$updateData = [];
						if (isset($itemData['wear_date'])) $updateData['wear_date'] = $itemData['wear_date'];
						if (isset($itemData['preferred_delivery_time'])) $updateData['preferred_delivery_time'] = $itemData['preferred_delivery_time'];
						
						if (!empty($updateData)) {
							$updateData['updated_at'] = date('Y-m-d H:i:s');
							$orderDetail->update($updateData);
						}
					}
				}
			}
		}
		
		return response()->json(['message' => 'Order updated successfully'], 200);
	}
	
	public function destroy($id = 0)
	{
		$order = Order::notDeleted()->where('id', $id)->first();
		if (!isset($order)) response()->json(['error' => __('messages.cannot_delete_order')], 403);
		
		try {
			$order->update(['is_deleted' => true]);
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	public function destroyMultiple(Request $request)
	{
		$validator = Validator::make($request->all(), ['ids' => 'required']);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$listIds = $request->get('ids', []);
		$orders = Order::notDeleted()->whereIn('id', $listIds)->get();
		if ($orders->count() <= 0) response()->json(['error' => __('messages.order_is_invalid')], 403);
		try {
			Order::notDeleted()->whereIn('id', $listIds)->update(['is_deleted' => true]);
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	public function activateMultiple(Request $request)
	{
		$validator = Validator::make($request->all(), ['ids' => 'required']);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$listIds = $request->get('ids', []);
		$orders = Order::notDeleted()->whereIn('id', $listIds)->get();
		if ($orders->count() <= 0) response()->json(['error' => __('messages.order_is_invalid')], 403);
		try {
			Order::notDeleted()->whereIn('id', $listIds)->update(['is_activated' => true]);
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	public function deactivateMultiple(Request $request)
	{
		$validator = Validator::make($request->all(), ['ids' => 'required']);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$listIds = $request->get('ids', []);
		$orders = Order::notDeleted()->whereIn('id', $listIds)->get();
		if ($orders->count() <= 0) response()->json(['error' => __('messages.order_is_invalid')], 403);
		try {
			Order::notDeleted()->whereIn('id', $listIds)->update(['is_activated' => false]);
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	public function position(Request $request)
	{
		if (!$request->has('position')) return response()->json(['errors' => __('messages.data_is_invalid')], 403);
		$newIndexes = $request->position;
		if (is_array($newIndexes)) {
			foreach ($newIndexes as $item) {
				Order::where('id', $item['id'])->update(['position' => $item['order']]);
			}
		}
		
		return response()->json(null, 204);
	}
	
	public function downloadAll(Request $request)
	{
		$searchParams = $request->all();
		$list = Order::notDeleted()->with(['user', 'delivery', 'order_detail.product_owner.owner', 'payment']);
		$keyword = Arr::get($searchParams, 'keyword', '');
		$status = Arr::get($searchParams, 'status', '');
		$paymentDeadlineFilter = Arr::get($searchParams, 'payment_deadline_filter', '');
		$shippingDeadlineFilter = Arr::get($searchParams, 'shipping_deadline_filter', '');
		
		if (!empty($keyword)) {
			$keyword = str_replace("#", "", $keyword);
			$list->where('code', 'LIKE', '%' . $keyword . '%');
		}
		
		if ($status != '') {
			$list->where('status', $status);
		}
		
		// Payment deadline filter (11 days or less from wear date)
		if ($paymentDeadlineFilter == '1') {
			$list->whereHas('order_detail', function ($query) {
				$query->whereNotNull('wear_date')
				      ->whereRaw('DATEDIFF(wear_date, CURDATE()) <= 11');
			});
		}
		
		// Shipping deadline filter
		if ($shippingDeadlineFilter == '6') {
			$list->whereHas('order_detail', function ($query) {
				$query->whereNotNull('wear_date')
				      ->whereRaw('DATEDIFF(wear_date, CURDATE()) <= 6');
			});
		} elseif ($shippingDeadlineFilter == '3') {
			$list->whereHas('order_detail', function ($query) {
				$query->whereNotNull('wear_date')
				      ->whereRaw('DATEDIFF(wear_date, CURDATE()) <= 3');
			});
		}
		
		$list->orderBy('id', 'DESC');
		$orders = $list->get();
		
		return OrderResource::collection($orders);
	}
}
