<?php

namespace Modules\User\Controllers\Employee;

use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use Modules\ContactList\Enums\ContactStatusEnum;
use Modules\ContactList\Services\ContactListService;
use Modules\DailyLog\Enums\DailyLogTypeEnum;
use Modules\DailyLog\Services\DailyLogService;
use Modules\Deal\Enums\DealStatusEnum;
use Modules\Deal\Services\DealService;
use Modules\Sector\Services\SectorService;
use Modules\Target\Services\TargetService;
use Modules\User\Enums\UserRoleEnum;
use Modules\User\Services\ModuleService;
use Modules\User\Services\UserService;

class DashboardController extends Controller
{

    public function __construct(
        private ModuleService $moduleService,
        private UserService $userService,
        private SectorService $sectorService,
        private ContactListService $contactListService,
        private TargetService $targetService,
        private DealService $dealService,
        private DailyLogService $dailyLogService,
    ){}
    public function stats(Request $request)
    {
        $request->merge(['employee_id'=>Auth::id()]);
        $months_num = [];
        $months = [];
        if($request->dates)
        {
            $dates = explode('//',$request->dates);
            $request->merge(['date_from'=>$dates[0],'date_to'=>$dates[1]]);
            $start = Carbon::parse($dates[0]);
            $end = Carbon::parse($dates[1]);
            $end->endOfMonth();
            $period = CarbonPeriod::create($start->startOfMonth(), '1 month', $end);
            foreach ($period as $date)
            {
                $months[] = $date->format('F');
                $months_num[] = $date->format('m');
            }
        }
        elseif($request->period)
        {
            if($request->period == 'week')
            {
                $months[] = date('F');
                $months_num[] = date('m');
                $startOfWeek = date('Y-m-d', strtotime('monday this week'));
                $endOfWeek = date('Y-m-d', strtotime('sunday this week'));
                $request->merge(['date_from'=>$startOfWeek,'date_to'=>$endOfWeek]);
            }
            elseif($request->period == 'month')
            {
                $months[] = date('F');
                $months_num[] = date('m');
                $request->merge(['date_from'=>date('Y-m').'-01' , 'date_to'=>date('Y-m-t')]);
            }
            elseif($request->period == 'quarter')
            {
                $today = date('Y-m-d');
                $month = date('n');
                $year = date('Y');
                $quarter = ceil($month / 3);
                $startMonth = ($quarter - 1) * 3 + 1;
                $startOfQuarter = date('Y-m-d', strtotime("$year-$startMonth-01"));
                $endMonth = $startMonth + 2;
                $endOfQuarter = date('Y-m-t', strtotime("$year-$endMonth-01"));
                $request->merge(['date_from'=>$startOfQuarter,'date_to'=>$endOfQuarter]);

                $start = Carbon::parse($startOfQuarter);
                $end = Carbon::parse($endOfQuarter);
                $end->endOfMonth();
                $period = CarbonPeriod::create($start->startOfMonth(), '1 month', $end);
                foreach ($period as $date)
                {
                    $months[] = $date->format('F');
                    $months_num[] = $date->format('m');
                }
            }
            elseif($request->period == 'year')
            {
                $request->merge(['date_from'=>date('Y').'01-01']);
                $months = range(1, 12);
                $months_num = $months;
                $months = array_map(fn($m) => date('F', mktime(0, 0, 0, $m, 1)), range(1, 12));

            }
        }
        else
        {
            $months = range(1, 12);
            $months_num = $months;
            $months = array_map(fn($m) => date('F', mktime(0, 0, 0, $m, 1)), range(1, 12));
        }

        $data = $request->all();
        $new_leads_count = $this->getNewLeads($data);
        $dataMonth  =
            [
                ...$data,
                'months'=>$months_num
            ];
        $sales_towards_target = $this->getSalesTowardsTarget($dataMonth);

        $target_sales = $sales_towards_target['target_sales'];

        $achieved_sales = $sales_towards_target['achieved_sales'];

        $max_target = max($target_sales);
        $max_achieved = max($achieved_sales);

        $maxSalesTowardsTarget = max($max_target, $max_achieved);
        $maxSalesTowardsTarget = $maxSalesTowardsTarget + $maxSalesTowardsTarget*.25;

        $lead_rates = $this->getLeadRate($dataMonth);

        $won_lost_deals = $this->getWonLostDeals($dataMonth);

        $won_deals = $won_lost_deals['won_deals'];
        $lost_deals = $won_lost_deals['lost_deals'];

        $logs_types = array_map(function($type) {
            return __('daily_logs.types.'.$type);
        }, DailyLogTypeEnum::values());

        $logs_statuses = $this->getDailyLogs($dataMonth);
        $phones = $logs_statuses['PHONE_CALL'];
        $zooms = $logs_statuses['ZOOM_MEETING'];
        $emails = $logs_statuses['EMAIL'];
        $linkedins = $logs_statuses['LINKEDIN_MSG'];
        $acqs = $logs_statuses['ACQUAINTANCE'];
        $faces = $logs_statuses['FACE_TO_FACE'];
        $totals = $logs_statuses['total'];


        $in_progress_deals = $this->getPiplineValue($dataMonth);

        $averageTime = $this->getAverageTime($dataMonth);

        $best_communication = $this->getBestCommunication($dataMonth);

        $employeesCommunications = $this->employeesCommunication($dataMonth);
        $communication_ways = DailyLogTypeEnum::values();

        return view('admin.stats',get_defined_vars());
    }

    private function employeesCommunication(array $request)
    {
        $request['groupBy'] = 'employeesCommunication';
        return $this->dailyLogService->get($request);
    }
    private function getBestCommunication(array $request)
    {
        $request['groupBy'] = 'type';
        $daily = $this->dailyLogService->get($request);

        return array_key_first($daily);
    }

    private function getAverageTime(array $request)
    {
        $request['typeStatus'] = DealStatusEnum::Confirmed->value;
        $deals = $this->dealService->get($request);
        $count = count($deals);
        if($count == 0)
        {
            return "N/A";
        }
        $days = 0;
        foreach($deals as $row)
        {
            $confimed = $this->dealService->confirmedDeal($row->id);
            if($confimed)
            {
                $start = Carbon::parse($row->created_at);
                $end   = Carbon::parse($confimed->created_at);

                $days += abs($start->diffInDays($end));
            }
        }
        return number_format($days / $count,2);
    }

    private function getPiplineValue(array $request)
    {
        $request['typeStatus'] = DealStatusEnum::Brief_Submitted->value;
        $request['count'] = true;

        return $this->dealService->get($request);
    }

    private function getNewLeads(array $request)
    {
        $request['count'] = true;
        $request['added_by'] = $request['employee_id'];
        $request['employee_id'] = null;
        return $this->contactListService->get($request);
    }

    private function getSalesTowardsTarget(array $request)
    {
        $request['groupBy'] = 'month';
        $data_target = $this->targetService->get($request);
        $target_sales = [];
        $achieved_sales = [];
        foreach ($request['months'] as $month)
        {
            if (isset($data_target[$month]))
            {
                $target_sales[$month] = $data_target[$month]['total_target'];
            }
            else
            {
                $target_sales[$month] = 0;
            }
        }

        $request['typeStatus'] = DealStatusEnum::Payment_Received->value;
        $data_achieved = $this->dealService->get($request);

        foreach ($request['months'] as $month)
        {
            if (isset($data_achieved[$month]))
            {
                $achieved_sales[$month] = $data_achieved[$month]['total_deals'];
            }
            else
            {
                $achieved_sales[$month] = 0;
            }
        }

        return
            [
                'target_sales' => $target_sales,
                'achieved_sales' => $achieved_sales,
            ];
    }

    private function getLeadRate(array $request)
    {
        $request['groupBy'] = 'month';
        $data_leads = $this->contactListService->get($request);
        $leads = [];
        $won_leads = [];
        foreach ($request['months'] as $month)
        {
            if (isset($data_leads[$month]))
            {
                $leads[$month] = $data_leads[$month]['count'];
            }
            else
            {
                $leads[$month] = 0;
            }
        }
        $request['type'] = ContactStatusEnum::PROJECT_WON->value;
        $data_won = $this->contactListService->get($request);

        foreach ($request['months'] as $month)
        {
            if (isset($data_won[$month]))
            {
                $won_leads[$month] = $data_won[$month]['count'];
            }
            else
            {
                $won_leads[$month] = 0;
            }
        }

        $percentages = array_map(function($a, $b) {
            return $b == 0 ? 0 : number_format($a / $b,2) *100;
        }, $won_leads, $leads);

        return $percentages;
    }

    private function getWonLostDeals(array $request)
    {
        $won_deals = [];
        $lost_deals = [];

        $request['groupBy'] = 'closed_at';
        $request['typeStatus'] = DealStatusEnum::Confirmed->value;
        $won_data = $this->dealService->get($request);

        $request['typeStatus'] = DealStatusEnum::Rejected->value;
        $lost_data = $this->dealService->get($request);

        foreach ($request['months'] as $month)
        {
            if (isset($won_data[$month]))
            {
                $won_deals[$month] = $won_data[$month]['count'];
            }
            else
            {
                $won_deals[$month] = 0;
            }
        }
        foreach ($request['months'] as $month)
        {
            if (isset($lost_data[$month]))
            {
                $lost_deals[$month] = $lost_data[$month]['count'];
            }
            else
            {
                $lost_deals[$month] = 0;
            }
        }
        return
            [
                'won_deals'=>$won_deals,
                'lost_deals'=>$lost_deals
            ];
    }

    private function getDailyLogs(array $request)
    {
        $phone = [];
        $zoom = [];
        $email = [];
        $linkedin = [];
        $acq = [];
        $face = [];

        $request['groupBy'] = 'month';
        $request['type'] = DailyLogTypeEnum::PHONE_CALL->value;
        $data = $this->dailyLogService->get($request);


        foreach ($request['months'] as $month)
        {
            if (isset($data[$month]))
            {
                $phone[$month] = $data[$month]['count'];
            }
            else
            {
                $phone[$month] = 0;
            }
        }

        $request['groupBy'] = 'month';
        $request['type'] = DailyLogTypeEnum::ZOOM_MEETING->value;
        $data = $this->dailyLogService->get($request);


        foreach ($request['months'] as $month)
        {
            if (isset($data[$month]))
            {
                $zoom[$month] = $data[$month]['count'];
            }
            else
            {
                $zoom[$month] = 0;
            }
        }

        $request['groupBy'] = 'month';
        $request['type'] = DailyLogTypeEnum::EMAIL->value;
        $data = $this->dailyLogService->get($request);


        foreach ($request['months'] as $month)
        {
            if (isset($data[$month]))
            {
                $email[$month] = $data[$month]['count'];
            }
            else
            {
                $email[$month] = 0;
            }
        }

        $request['groupBy'] = 'month';
        $request['type'] = DailyLogTypeEnum::LINKEDIN_MSG->value;
        $data = $this->dailyLogService->get($request);


        foreach ($request['months'] as $month)
        {
            if (isset($data[$month]))
            {
                $linkedin[$month] = $data[$month]['count'];
            }
            else
            {
                $linkedin[$month] = 0;
            }
        }

        $request['groupBy'] = 'month';
        $request['type'] = DailyLogTypeEnum::ACQUAINTANCE->value;
        $data = $this->dailyLogService->get($request);


        foreach ($request['months'] as $month)
        {
            if (isset($data[$month]))
            {
                $acq[$month] = $data[$month]['count'];
            }
            else
            {
                $acq[$month] = 0;
            }
        }

        $request['groupBy'] = 'month';
        $request['type'] = DailyLogTypeEnum::FACE_TO_FACE->value;
        $data = $this->dailyLogService->get($request);


        foreach ($request['months'] as $month)
        {
            if (isset($data[$month]))
            {
                $face[$month] = $data[$month]['count'];
            }
            else
            {
                $face[$month] = 0;
            }
        }

        $total = array_map(function($phone, $zoom, $email,$linkedin,$acq,$face) {
            return $phone+ $zoom+ $email+$linkedin+$acq+$face;
        }, $phone, $zoom, $email,$linkedin,$acq,$face);



        return
            [
                'PHONE_CALL'=>$phone,
                'ZOOM_MEETING'=>$zoom,
                'EMAIL'=>$email,
                'LINKEDIN_MSG'=>$linkedin,
                'ACQUAINTANCE'=>$acq,
                'FACE_TO_FACE'=>$face,
                'total'=>$total,
            ];
    }

    public function index(Request $request) :View
    {
        $employees = $this->userService->get(['roles'=>UserRoleEnum::employees()]);
        $sectors = $this->sectorService->get();


        return view('employee.index',get_defined_vars());
    }
    public function modules(Request $request) :View
    {
        $modules = $this->moduleService->get(['dashboard'=>'employee','group'=>true,'user_id'=>Auth::id(),'title'=>$request->title,'sidebar'=>true]);
        return view('employee.layouts.modules',get_defined_vars());
    }

}
