<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use App\Models\Term;
use App\Models\User;
use App\Models\LegalAct;
use \Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Http\Requests\UserCreate;
use Illuminate\Support\Facades\DB;
use App\Http\Requests\UserComplete;
use App\Http\Resources\UserResource;
use App\Http\Resources\CMS_API_UserResource;
use Illuminate\Validation\ValidationException;

class ApiUserController extends Controller
{
    public function get(Request $request)
    {
        $guid = $request->guid;
        $user = User::with('attempt')->where('guid', $guid)->first();

        if ($user) {
            $user = new UserResource($user);

            return api()->success()->data($user)->send();
        }

        return api()->error()->send();
    }

    public function create(UserCreate $request)
    {
        //There must be at least one term in database for the vouchers to be run
        $latestTerm = Term::orderByDesc('id')->first();
        if (!$latestTerm) {
            return api()->error()->send();
        }

        //Last term is considered currently active. The current date must be between last
        //terms start and end dates. Otherwise the vouchers cycle period has expired 
        //and the use can not register
        if (!\Carbon\Carbon::now('Europe/Skopje')->between($latestTerm->start_date, $latestTerm->end_date->endOfDay())) {
            return api()->error()->customMessage(__('general.term_expired'))->send();
        }

        //While the user hasn't started the assessment, he can freely change his details.
        //He can enter the application from different devices, the email uniqueness isn't required
        //Once the assessmnet has started, his email should be considered unique
        // $email = $request->email;
        // $user = User::where('email', $email)->where('term_id', $latestTerm->id)->first();
        $user = User::firstOrNew(['email' => $request->email, 'term_id' => $latestTerm->id]);
        if ($user && $user->attempt) {
            throw ValidationException::withMessages([
                'email' => [__('validation.custom.email.uniqueByTerm')]
            ]);
        }

        //Allow maximum 3 applications from the same IP address 
        // $clientIP = $this->getClientIP();
        // $applicationsFromSameIP = User::where('ip', $clientIP)->count();

        // if ($clientIP != null && $applicationsFromSameIP >= 10) {
        //     throw ValidationException::withMessages([
        //         'additional' => [__('general.too_many_applications')]
        //     ]);
        // }

        $user->name = $request->name;
        $user->surname = $request->surname ?? null;
        $user->referred_by = $request->referred_by ?? null;
        //with the change to bring the profile completion step at the end of the test
        //we now ask the users to only fill the year column. For that reason, we hardcode
        //month and day to 01, in order to avoid changing the database column from date to year.
        $user->birth_date = null;
        if ($request->has('year')) {
            $user->birth_date = \Carbon\Carbon::createFromDate(
                $request->birth_date['year'],
                $request->birth_date['month'] ?? 01,
                $request->birth_date['day'] ?? 01
            );
        }
        $user->highschool = $request->highschool ?? null;
        $user->phone = $request->phone ?? null;
        $user->highschool_year = $request->highschool_year ?? null;
        $user->token = $user->token != "" ? $user->token : Str::random(6);
        $user->guid = $user->guid ?? Str::random(60);
        // $user->ip = $clientIP;
        $user->query_string = $request->query_string ?? null;

        if ($user->save()) {
            $user->attempt()->create([
                'academy_id' => $request->academy_id
            ]);

            return api()->success()->data(['guid' => $user->guid])->send();
        }

        return api()->error()->send();
    }

    public function complete(UserComplete $request)
    {
        $user = User::where('guid', $request->guid)->first();

        if (!$user) {
            return api()->error()->send();
        }

        $user->name = $request->name;
        $user->surname = $request->surname ?? null;
        $user->birth_date = null;
        if ($request->has('year')) {
            $user->birth_date = \Carbon\Carbon::createFromDate(
                $request->birth_date['year'],
                $request->birth_date['month'] ?? 01,
                $request->birth_date['day'] ?? 01
            );
        }
        $user->highschool = $request->highschool ?? null;
        $user->phone = $request->phone ?? null;

        $user->save();

        return api()->success()->send();
    }

    public function getClientIp()
    {
        //get the IP from the client, but hence the app is running in Docker 
        //container the IP gets rewritten with the IP of the host os. 
        //We need to get it from the X_FORWARDED_BY (there can be many values there),
        //or if not there rely on the CloudFlare's client IP header

        //X-Forwarded-For vs Client-IP:
        //X-Forwarded-For: header might contain a complete track of the forwarding chain if more than one proxy was involved
        //Client-IP: header would contain the actual client IP
        if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
            $ips = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
            return $ips[0];
        } else if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER)) {
            return $_SERVER['HTTP_CF_CONNECTING_IP'];
        } else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) { //
            return $_SERVER["HTTP_CLIENT_IP"];
        }

        return null;
    }

    public function getLegalActs()
    {
        $acts = LegalAct::all()->pluck('value', 'option');

        return api()->success()->data($acts)->send();
    }

    public function getApplicants(Request $request)
    {
        $users = User::with(['attempt', 'questionAnswers']);

        if (!$request->has('term_id') && !($request->has('date_from') && $request->has('date_to'))) {
            return api()->error()->customMessage('A (term_id) or (date_from, date_to) parameters must be present')->send();
        }

        //First apply the term_param if present, then add the date_from and date_to
        if ($request->has('term_id')) {
            $users->where('term_id', $request->term_id);
        }

        if ($request->has('date_from') && $request->has('date_to')) {
            $startTime = Carbon::createFromFormat("Y-m-d", $request->input('date_from'))->startOfDay();
            $endTime = Carbon::createFromFormat("Y-m-d", $request->input('date_to'))->endOfDay();

            $users->whereBetween('created_at', [$startTime, $endTime]);
        }


        $users = $users->get();
        // $users->append('correctAnswers');
        $users = CMS_API_UserResource::collection($users);

        return api()->success()->data($users)->send();
    }
}
