<?php

namespace App\Http\Controllers;

use App\Events\NotifyEvent;
use App\Http\Resources\ReportDetailResource;
use App\Notify;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Http\Resources\ReportResource;
use App\Report;
use App\ReportDetail;
use Validator;
use DB;

class ReportController extends Controller
{
    const ITEM_PER_PAGE = 25;

    private $_user = null;

    public function __construct()
    {
        $this->_user = auth('api')->user();
    }

    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', '');
        $list = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('is_record', false);

        $keyword = str_replace("#", "", $keyword);
        $keyword = str_replace("-", "", $keyword);
        if (!empty($keyword)) {
            $list->where(function ($query) use ($keyword) {
                $query->where('id', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('code', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('report_date', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('site_name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('project_name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('customer_name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('contact_name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('primary_member', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('second_member', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('notice', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('request', 'LIKE', '%' . $keyword . '%');
            });
        }

        if ($status != '') {
            $list->where('is_activated', $status);
        }

        $list->orderBy('id', 'DESC');

        return ReportResource::collection($list->paginate($limit));
    }

    public function statistic(Request $request)
    {

        $total = Report::notDeleted()->where('is_record', false)->where('user_id', $this->_user->id)->count();
        $waiting = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('is_activated', 0)
            ->where('is_record', false)
            ->count();
        $progressing = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('is_activated', 1)
            ->where('is_record', false)
            ->count();
        $done = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('is_activated', 2)
            ->where('is_record', false)
            ->count();
        $fail = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('is_activated', 3)
            ->where('is_record', false)
            ->count();

        return response()->json([
            'status' => 'success',
            'data'   => [
                'total'       => $total,
                'waiting'     => $waiting,
                'progressing' => $progressing,
                'done'        => $done,
                'fail'        => $fail,
            ],
        ], 200);
    }

    public function top(Request $request)
    {
        $searchParams = $request->all();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $list = Report::notDeleted()->select('*')->where('is_record', false)->orderBy('id', 'DESC');

        return ReportResource::collection($list->paginate($limit));
    }

    public function slug($slug = '')
    {
        $report = Report::select('*')
            ->notDeleted()
            ->where('slug', $slug)
            ->where('is_record', false)
            ->first();

        return new ReportResource($report);
    }

    public function show($id = '')
    {
        $report = Report::notDeleted()
            ->select('*')
            ->where('user_id', $this->_user->id)
            ->where('id', $id)
            ->where('is_record', false)
            ->first();

        if (!$report) return response()->json([ 'status' => 'error', 'message' => 'Report does not exist.' ], 200);

        return new ReportDetailResource($report);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'report_date'     => [ 'required' ],
        ]);
        if ($validator->fails()) return response()->json([ 'errors' => $validator->errors() ], 403);
        $params = $request->all();

        $report = Report::notDeleted()
            ->where('report_date', $params['report_date'])
            ->where('user_id', $this->_user->id)
            ->first();

        if (!$report) return response()->json([ 'errors' => '新しい稼働日を宣言していないため、レポートを作成できません。' ], 403);

        $hasUpdatedItem = 0;
        if ($report->is_record == 1) {
            $report->update([
                'primary_member'     => $params['primary_member'],
                'second_member'      => $params['second_member'],
                'car'                => $params['car'],
                'notice'             => $params['notice'],
                'request'            => $params['request'],
                'on_site_cost'       => $params['on_site_cost'],
                'has_estimated'      => ($params['has_estimated'] === true) ? 1 : 0,
                'is_finished'        => ($params['is_finished'] === true) ? 1 : 0,
                'estimated_workload' => $params['estimated_workload'],
                'reporter_id'        => $this->_user->id,
                'is_record'          => 0,
                'is_new'             => 1,
                'is_activated'       => 1,
                'updated_at'         => date('Y-m-d H:i:s')
            ]);

            if (!isset($params['details']) || count($params['details']) <= 0) {
                $params['details'][] = [ 'working_zone' => '', 'piping' => '', 'temperature_keeping' => '', 'size' => '', 'length' => '', 'elbow' => '', 'note' => '' ];
            }

            foreach ($params['details'] as $item) {
                ReportDetail::create([
                    'report_id'           => $report->id,
                    'working_zone'        => $item['working_zone'],
                    'piping'              => $item['piping'],
                    'temperature_keeping' => $item['temperature_keeping'],
                    'size'                => $item['size'],
                    'length'              => $item['length'],
                    'elbow'               => $item['elbow'],
                    'note'                => $item['note'],
                    'created_at'          => date('Y-m-d H:i:s'),
                    'updated_at'          => date('Y-m-d H:i:s')
                ]);
            }

            $hasUpdatedItem++;
        }

        if (isset($params['members'])) {
            foreach ($params['members'] as $item) {

                $reportItem = Report::notDeleted()
                    ->where('report_date', $params['report_date'])
                    ->where('user_id', $item)
                    ->first();

                if ($reportItem && $reportItem->is_record == 1) {
                    $reportItem->update([
                        'primary_member'     => $params['primary_member'],
                        'second_member'      => $params['second_member'],
                        'car'                => $params['car'],
                        'notice'             => $params['notice'],
                        'request'            => $params['request'],
                        'on_site_cost'       => $params['on_site_cost'],
                        'has_estimated'      => ($params['has_estimated'] === true) ? 1 : 0,
                        'is_finished'        => ($params['is_finished'] === true) ? 1 : 0,
                        'estimated_workload' => $params['estimated_workload'],
                        'reporter_id'        => $this->_user->id,
                        'is_record'          => 0,
                        'is_new'             => 1,
                        'is_activated'       => 1,
                        'updated_at'         => date('Y-m-d H:i:s')
                    ]);

                    if (!isset($params['details']) || count($params['details']) <= 0) {
                        $params['details'][] = [ 'working_zone' => '', 'piping' => '', 'temperature_keeping' => '', 'size' => '', 'length' => '', 'elbow' => '', 'note' => '' ];
                    }

                    foreach ($params['details'] as $dItem) {
                        ReportDetail::create([
                            'report_id'           => $reportItem->id,
                            'working_zone'        => $dItem['working_zone'],
                            'piping'              => $dItem['piping'],
                            'temperature_keeping' => $dItem['temperature_keeping'],
                            'size'                => $dItem['size'],
                            'length'              => $dItem['length'],
                            'elbow'               => $dItem['elbow'],
                            'note'                => $dItem['note'],
                            'created_at'          => date('Y-m-d H:i:s'),
                            'updated_at'          => date('Y-m-d H:i:s')
                        ]);
                    }

                    $hasUpdatedItem++;
                }
            }
        }

        //Notify
        if ($hasUpdatedItem > 0) {
            $data = [ 'id' => $report->id, 'code' => $report->code ];
            Notify::create([
                'content'      => "[" . $this->_user->full_name . "] レポート#" . $report->code . "を送信しました。",
                'module'       => 'report',
                'item_id'      => $report->id,
                'item_content' => json_encode($data),
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s'),
            ]);
            event(new NotifyEvent());
        }

        return new ReportResource($report);
    }

    public function update(Request $request, $id = 0)
    {
        $validator = Validator::make($request->all(), [ 'site_name' => [ 'required' ], 'customer_name' => [ 'required' ], 'contact_name' => [ 'required' ] ]);
        if ($validator->fails()) return response()->json([ 'errors' => $validator->errors() ], 403);
        $report = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('id', $id)
            ->first();

        if (!isset($report)) return response()->json([ 'errors' => 'Report does not exist.' ], 403);
        if ($report && $report->is_activated != 0) return response()->json([ 'errors' => '処理レポートを更新できません。' ], 403);
        $params = $request->all();

        $report->update([
            'primary_member'     => $params['primary_member'],
            'second_member'      => $params['second_member'],
            'car'                => $params['car'],
            'notice'             => $params['notice'],
            'request'            => $params['request'],
            'on_site_cost'       => $params['on_site_cost'],
            'has_estimated'      => ($params['has_estimated'] === true) ? 1 : 0,
            'is_finished'        => ($params['is_finished'] === true) ? 1 : 0,
            'estimated_workload' => $params['estimated_workload'],
            'updated_at'         => date('Y-m-d H:i:s')
        ]);

        ReportDetail::where('report_id', $report->id)->delete();
        if (!isset($params['details']) || count($params['details']) <= 0) {
            $params['details'][] = [ 'working_zone' => '', 'piping' => '', 'temperature_keeping' => '', 'size' => '', 'length' => '', 'elbow' => '', 'note' => '' ];
        }
        foreach ($params['details'] as $item) {
            ReportDetail::create([
                'report_id'           => $report->id,
                'working_zone'        => $item['working_zone'],
                'piping'              => $item['piping'],
                'temperature_keeping' => $item['temperature_keeping'],
                'size'                => $item['size'],
                'length'              => $item['length'],
                'elbow'               => $item['elbow'],
                'note'                => $item['note'],
                'created_at'          => date('Y-m-d H:i:s'),
                'updated_at'          => date('Y-m-d H:i:s')
            ]);
        }

        if (isset($params['members'])) {
            foreach ($params['members'] as $item) {
                $reportItem = Report::notDeleted()
                    ->where('report_date', $report->report_date)
                    ->where('user_id', $item)
                    ->where('reporter_id', $this->_user->id)
                    ->where('is_activated', 0)
                    ->first();

                if ($reportItem) {
                    $reportItem->update([
                        'primary_member'     => $params['primary_member'],
                        'second_member'      => $params['second_member'],
                        'car'                => $params['car'],
                        'notice'             => $params['notice'],
                        'request'            => $params['request'],
                        'on_site_cost'       => $params['on_site_cost'],
                        'has_estimated'      => ($params['has_estimated'] === true) ? 1 : 0,
                        'is_finished'        => ($params['is_finished'] === true) ? 1 : 0,
                        'estimated_workload' => $params['estimated_workload'],
                        'updated_at'         => date('Y-m-d H:i:s')
                    ]);

                    if (!isset($params['details']) || count($params['details']) <= 0) {
                        $params['details'][] = [ 'working_zone' => '', 'piping' => '', 'temperature_keeping' => '', 'size' => '', 'length' => '', 'elbow' => '', 'note' => '' ];
                    }

                    foreach ($params['details'] as $dItem) {
                        ReportDetail::create([
                            'report_id'           => $reportItem->id,
                            'working_zone'        => $dItem['working_zone'],
                            'piping'              => $dItem['piping'],
                            'temperature_keeping' => $dItem['temperature_keeping'],
                            'size'                => $dItem['size'],
                            'length'              => $dItem['length'],
                            'elbow'               => $dItem['elbow'],
                            'note'                => $dItem['note'],
                            'created_at'          => date('Y-m-d H:i:s'),
                            'updated_at'          => date('Y-m-d H:i:s')
                        ]);
                    }
                }
            }
        }

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

    public function destroy($id = 0)
    {
        $report = Report::notDeleted()
            ->where('user_id', $this->_user->id)
            ->where('id', $id)
            ->where('is_record', false)
            ->first();
        if (!isset($report)) response()->json([ 'error' => 'Ehhh! Can not delete this report' ], 403);

        try {
            $report->update([ 'is_deleted' => true ]);
        } catch (\Exception $ex) {
            response()->json([ 'error' => $ex->getMessage() ], 403);
        }

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

    public function check(Request $request)
    {
        $params = $request->all();
        $date = Arr::get($params, 'date', '');

        $report = Report::notDeleted()
            ->select('*')
            ->where('user_id', $this->_user->id)
            ->where('report_date', $date)
            ->first();

        if (!$report) {
            return response()->json([ 'status' => 'error', 'type' => 'record', 'id' => null, 'message' => 'Record does not exist.' ], 200);
        } else {
            if ($report->is_record == 1) {
                return response()->json([ 'status' => 'error', 'type' => 'report', 'id' => null, 'message' => 'Report has not been created yet.' ], 200);
            }
        }

        return response()->json([ 'status' => 'success', 'type' => null, 'id' => $report->id, 'message' => '' ], 200);
    }

    public function record(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'report_date' => [ 'required' ],
        ]);

        if ($validator->fails()) return response()->json([ 'errors' => $validator->errors() ], 403);
        $params = $request->all();
	    $records = $params['records'];
        $createdCount = 0;
        $today = str_replace("-", "", $params['report_date']);
        $countItems = Report::where('code', 'like', $today . '%')->count();

	    do {
		    $countItems++;
		    $code = $today . str_pad($countItems, 5, "0", STR_PAD_LEFT);
		    $checkExist = Report::where('code', $code)->count();
	    } while ($checkExist > 0);

	    $report = Report::notDeleted()
		    ->where('report_date', $params['report_date'])
		    ->where('customer_id', $records[0]['customer_id'])
		    ->where('charge_id', $records[0]['charge_id'])
		    ->where('user_id', $this->_user->id)
		    ->first();

        if (!$report) {
            $report = Report::create([
                'code'         => $code,
                'report_date'  => $params['report_date'],
                'customer_id'  => $records[0]['customer_id'],
                'charge_id'    => $records[0]['charge_id'],
                'user_id'      => $this->_user->id,
                'is_new'       => 1,
                'is_record'    => 1,
                'is_activated' => 0,
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s')
            ]);

            $createdCount++;
        }

        $notify = "[" . $this->_user->full_name . "]が新しい営業日を宣言しました。";
        foreach ($records as $record) {
	        if (isset($record['members']) && $this->_user->is_leader == 1 && $this->_user->is_allowed_record_group == 1) {
		        $insertData = [];
		        foreach ($record['members'] as $item) {
			        $reportItem = Report::notDeleted()
				        ->where('report_date', $params['report_date'])
				        ->where('customer_id', $record['customer_id'])
				        ->where('charge_id', $record['charge_id'])
				        ->where('user_id', $item)
				        ->first();

			        if (!$reportItem) {
				        do {
					        $countItems++;
					        $code = $today . str_pad($countItems, 5, "0", STR_PAD_LEFT);
					        $checkExist = Report::where('code', $code)->count();
				        } while ($checkExist > 0);

				        $insertData[] = [
					        'code'         => $code,
					        'report_date'  => $params['report_date'],
					        'customer_id'  => $record['customer_id'],
					        'charge_id'    => $record['charge_id'],
					        'user_id'      => $item,
					        'leader_id'    => $this->_user->id,
					        'is_new'       => 1,
					        'is_record'    => 1,
					        'is_activated' => 0,
					        'created_at'   => date('Y-m-d H:i:s'),
					        'updated_at'   => date('Y-m-d H:i:s')
				        ];
			        }
		        }

		        if (count($insertData) > 0) {
			        Report::insert($insertData);
			        $notify = "[" . $this->_user->full_name . "]は新しい勤務日のメンバー" . (count($insertData) + $createdCount) . "名を宣言しました。";
			        $createdCount += count($insertData);
		        }
	        }
        }

        //Notify
        if ($createdCount > 0) {
            $data = [ 'id' => $report->id, 'code' => $report->code ];
            Notify::create([
                'content'      => $notify,
                'module'       => 'report',
                'item_id'      => $report->id,
                'item_content' => json_encode($data),
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s'),
            ]);
            event(new NotifyEvent());
        }

        return new ReportResource($report);
    }

    public function currentMember(Request $request)
    {
        $params = $request->all();
        $date = Arr::get($params, 'date', '');

        $report = Report::notDeleted()
            ->select('id', 'code', 'report_date', 'customer_id', 'charge_id', 'is_record')
            ->where('user_id', $this->_user->id)
            ->where('report_date', $date)
            ->first();

        if (!$report) return response()->json([ 'status' => 'error', 'message' => 'Report does not exist.' ], 200);

        $userIds = DB::table('user_projects')
            ->join('user_project_members', 'user_projects.id', '=', 'user_project_members.user_project_id')
            ->select('user_project_members.user_id')
            ->where('user_projects.user_id', $this->_user->id)
            ->where('user_projects.project_id', $report->customer->project_id)
            ->pluck('user_id')
            ->toArray();

        $listUser = User::select('id', 'first_name', 'last_name', 'full_name', 'furigana_name', 'furigana_first_name', 'furigana_last_name')
            ->where('is_deleted', false)
            ->where('is_activated', true)
            ->where('is_leader', 0)
            ->whereIn('id', $userIds)
            ->orderBy('id')
            ->get();

        return response()->json([ 'status' => 'success', 'report' => $report, 'members' => $listUser], 200);
    }
}
