<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Plan;
use App\PlanDetail;
use App\Customer;
use App\Charge;
use App\User;
use App\Http\Resources\Admin\PlanResource;
use Validator;

class PlanController extends Controller
{
	const ITEM_PER_PAGE = 20;
	
	/**
	 * Display a listing of plans
	 *
	 * @param Request $request
	 * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
	 */
	public function index(Request $request)
	{
		$searchParams = $request->all();
		$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
		$keyword = Arr::get($searchParams, 'keyword', '');
		$status = Arr::get($searchParams, 'status', '');
		$planDate = Arr::get($searchParams, 'plan_date', '');
		$list = Plan::where('is_deleted', 0);
		
		if (!empty($keyword)) {
			$list->where('code', 'LIKE', '%' . $keyword . '%');
		}
		if ($status !== null && $status !== '') {
			$list->where('status', $status);
		}
		if (!empty($planDate)) {
			$list->where('plan_date', $planDate);
		}
		
		$list->with('user')->orderBy('plan_date', 'desc')->orderBy('id', 'desc');
		
		return PlanResource::collection($list->paginate($limit));
	}
	
	/**
	 * Display the specified plan
	 *
	 * @param int $id
	 * @return PlanResource|\Illuminate\Http\JsonResponse
	 */
	public function show($id = 0)
	{
		$plan = Plan::where('is_deleted', 0)
			->where('id', $id)
			->with(['user', 'planDetails.project', 'planDetails.customer', 'planDetails.charge', 'planDetails.users'])
			->first();
		
		if (!isset($plan)) {
			return response()->json(['errors' => 'Plan is not valid'], 403);
		}
		
		return new PlanResource($plan);
	}
	
	/**
	 * Store a newly created plan
	 *
	 * @param Request $request
	 * @return PlanResource|\Illuminate\Http\JsonResponse
	 */
	public function store(Request $request)
	{
		$validator = Validator::make($request->all(), [
			'plan_date'                  => ['required', 'date'],
			'status'                     => ['required', 'integer'],
			'plan_details'               => ['required', 'array'],
			'plan_details.*.project_id'  => ['required', 'integer'],
			'plan_details.*.customer_id' => ['required', 'integer'],
			'plan_details.*.charge_id'   => ['required', 'integer'],
			'plan_details.*.type'        => ['required', 'integer'],
			'plan_details.*.user_ids'    => ['required', 'array']
		]);
		
		if ($validator->fails()) {
			return response()->json(['errors' => $validator->errors()], 403);
		}
		
		$params = $request->all();
		
		// Generate plan code
		$dateCode = date('Ymd', strtotime($params['plan_date']));
		$lastPlan = Plan::where('plan_date', $params['plan_date'])
			->where('is_deleted', 0)
			->orderBy('id', 'desc')
			->first();
		$sequence = $lastPlan ? (intval(substr($lastPlan->code, -3)) + 1) : 1;
		$code = 'PLAN' . $dateCode . sprintf('%03d', $sequence);
		
		// Create plan
		$plan = Plan::create([
			'code'         => $code,
			'plan_date'    => $params['plan_date'],
			'status'       => $params['status'],
			'user_id'      => auth()->id(),
			'is_activated' => 1,
			'is_deleted'   => 0,
			'created_at'   => date('Y-m-d H:i:s'),
			'updated_at'   => date('Y-m-d H:i:s')
		]);
		
		// Create plan details
		foreach ($params['plan_details'] as $detail) {
			$planDetail = PlanDetail::create([
				'plan_id'     => $plan->id,
				'project_id'  => $detail['project_id'],
				'customer_id' => $detail['customer_id'],
				'charge_id'   => $detail['charge_id'],
				'type'        => $detail['type'],
				'time_start'  => $detail['time_start'] ?? null,
				'time_end'    => $detail['time_end'] ?? null,
				'time_range'  => $detail['time_range'] ?? null,
				'created_at'  => date('Y-m-d H:i:s'),
				'updated_at'  => date('Y-m-d H:i:s')
			]);
			
			// Attach users to plan detail
			if (isset($detail['user_ids']) && is_array($detail['user_ids'])) {
				$planDetail->users()->attach($detail['user_ids']);
			}
		}
		
		return new PlanResource($plan->load(['planDetails.project', 'planDetails.customer', 'planDetails.charge', 'planDetails.users']));
	}
	
	/**
	 * Update the specified plan
	 *
	 * @param Request $request
	 * @param int $id
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function update(Request $request, $id = 0)
	{
		$validator = Validator::make($request->all(), [
			'plan_date'                  => ['required', 'date'],
			'status'                     => ['required', 'integer'],
			'plan_details'               => ['required', 'array'],
			'plan_details.*.project_id'  => ['required', 'integer'],
			'plan_details.*.customer_id' => ['required', 'integer'],
			'plan_details.*.charge_id'   => ['required', 'integer'],
			'plan_details.*.type'        => ['required', 'integer'],
			'plan_details.*.user_ids'    => ['required', 'array']
		]);
		
		if ($validator->fails()) {
			return response()->json(['errors' => $validator->errors()], 403);
		}
		
		$plan = Plan::where('is_deleted', 0)->where('id', $id)->first();
		if (!isset($plan)) {
			return response()->json(['errors' => 'Plan is not valid'], 403);
		}
		
		$params = $request->all();
		
		// Update plan
		$plan->update([
			'plan_date'  => $params['plan_date'],
			'status'     => $params['status'],
			'updated_at' => date('Y-m-d H:i:s')
		]);
		
		// Delete existing plan details and recreate
		foreach ($plan->planDetails as $detail) {
			$detail->users()->detach();
		}
		$plan->planDetails()->delete();
		
		// Create new plan details
		foreach ($params['plan_details'] as $detail) {
			$planDetail = PlanDetail::create([
				'plan_id'     => $plan->id,
				'project_id'  => $detail['project_id'],
				'customer_id' => $detail['customer_id'],
				'charge_id'   => $detail['charge_id'],
				'type'        => $detail['type'],
				'time_start'  => $detail['time_start'] ?? null,
				'time_end'    => $detail['time_end'] ?? null,
				'time_range'  => $detail['time_range'] ?? null,
				'created_at'  => date('Y-m-d H:i:s'),
				'updated_at'  => date('Y-m-d H:i:s')
			]);
			
			// Attach users to plan detail
			if (isset($detail['user_ids']) && is_array($detail['user_ids'])) {
				$planDetail->users()->attach($detail['user_ids']);
			}
		}
		
		return response()->json(null, 204);
	}
	
	/**
	 * Remove the specified plan
	 *
	 * @param int $id
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function destroy($id = 0)
	{
		$plan = Plan::where('is_deleted', 0)->where('id', $id)->first();
		if (!isset($plan)) {
			return response()->json(['error' => 'Plan not found'], 403);
		}
		
		try {
			$plan->update([
				'is_deleted' => 1,
				'updated_at' => date('Y-m-d H:i:s')
			]);
		} catch (\Exception $ex) {
			return response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	/**
	 * Remove multiple plans
	 *
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	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', []);
		$plans = Plan::where('is_deleted', 0)->whereIn('id', $listIds)->get();
		if ($plans->count() <= 0) {
			return response()->json(['error' => 'Plans are not valid.'], 403);
		}
		
		try {
			Plan::where('is_deleted', 0)->whereIn('id', $listIds)->update([
				'is_deleted' => 1,
				'updated_at' => date('Y-m-d H:i:s')
			]);
		} catch (\Exception $ex) {
			return response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	/**
	 * Activate multiple plans
	 *
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	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', []);
		$plans = Plan::where('is_deleted', 0)->whereIn('id', $listIds)->get();
		if ($plans->count() <= 0) {
			return response()->json(['error' => 'Plans are not valid.'], 403);
		}
		
		try {
			Plan::where('is_deleted', 0)->whereIn('id', $listIds)->update([
				'is_activated' => 1,
				'updated_at'   => date('Y-m-d H:i:s')
			]);
		} catch (\Exception $ex) {
			return response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	/**
	 * Deactivate multiple plans
	 *
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	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', []);
		$plans = Plan::where('is_deleted', 0)->whereIn('id', $listIds)->get();
		if ($plans->count() <= 0) {
			return response()->json(['error' => 'Plans are not valid.'], 403);
		}
		
		try {
			Plan::where('is_deleted', 0)->whereIn('id', $listIds)->update([
				'is_activated' => 0,
				'updated_at'   => date('Y-m-d H:i:s')
			]);
		} catch (\Exception $ex) {
			return response()->json(['error' => $ex->getMessage()], 403);
		}
		
		return response()->json(null, 204);
	}
	
	/**
	 * Get all plans for dropdown
	 *
	 * @param Request $request
	 * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
	 */
	public function all(Request $request)
	{
		$searchParams = $request->all();
		$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
		$list = Plan::select('id', 'code', 'plan_date', 'status')
			->where('is_deleted', 0)
			->where('is_activated', 1)
			->orderBy('plan_date', 'desc');
		
		return PlanResource::collection($list->paginate($limit));
	}
	
	/**
	 * Get helper data for forms
	 *
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function getFormData()
	{
		$customers = Customer::select('id', 'name', 'first_name', 'last_name')
			->where('is_deleted', 0)
			->where('is_activated', 1)
			->orderBy('name')
			->get();
		
		$charges = Charge::select('id', 'name', 'first_name', 'last_name')
			->where('is_deleted', 0)
			->where('is_activated', 1)
			->orderBy('name')
			->get();
		
		$users = User::select('id', 'name', 'full_name')
			->where('is_deleted', 0)
			->where('is_activated', 1)
			->orderBy('full_name')
			->get();
		
		$statusOptions = [
			['value' => Plan::STATUS_DRAFT, 'label' => 'Draft'],
			['value' => Plan::STATUS_ACTIVE, 'label' => 'Active'],
			['value' => Plan::STATUS_COMPLETED, 'label' => 'Completed'],
			['value' => Plan::STATUS_CANCELLED, 'label' => 'Cancelled']
		];
		
		$typeOptions = [];
		for ($i = 0; $i <= 10; $i++) {
			$typeOptions[] = [
				'value' => $i,
				'label' => 'Type ' . $i
			];
		}
		
		return response()->json([
			'customers'      => $customers,
			'charges'        => $charges,
			'users'          => $users,
			'status_options' => $statusOptions,
			'type_options'   => $typeOptions
		]);
	}
}