<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Http\Requests\CallCenterRequest;
use App\Http\Requests\ChatbotRequest;
use App\Models\AppointmentRequest;
use App\Models\CallCenter;
use App\Models\CallCenterSourcePdf;
use App\Models\CallCenterSourceQA;
use App\Models\CallCenterSourceSummary;
use App\Models\CallCenterSourceUrl;
use App\Models\ChatbotConversations;
use App\Models\ChatbotSourcePdf;
use App\Models\ChatbotSourceQa;
use App\Models\ChatbotSourceSummary;
use App\Models\ChatbotSourceUrl;
use App\Models\CreditConfiguration;
use App\Models\OpenAiConfiguration;
use App\Models\Subscriber;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use App\Models\Chatbot;
use App\Models\ChatbotLeads;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Mockery\Exception;
use Smalot\PdfParser\Parser;


class CallCenterController extends Controller
{
    public function callCenterSearch(Request $request)
    {
        try {
            $searchContent = $request->get('search_content');
            $data['searchData'] = CallCenter::where('callcenter_name', 'LIKE', '%' . $searchContent . '%')->get();
            $renderSearchData = view('user.callcenter.partial.search-data-render', $data)->render();
            return response()->json(['status' => 'success', 'message' => __("Data Fetch Successful"), 'data' => $renderSearchData], 200);
        } catch (\Exception $exception) {
            Log::info($exception->getMessage());
            return response()->json(['status' => 'error', 'message' => __("Something went wrong"), 'data' => []], 500);
        }

    }

    public function create(Request $request, $callcenter_id = null)
    {

//        if ($request->ajax()) {
//            if (isset($request->option) && $request->option === "appointment"){
//                return $this->appointmentsList($request);
//            }else{
//                return $this->leadsList($request);
//            }
////            return $this->appointmentsList($request);
//        }
        try {
            $data['callcenterData'] = null;
            $data['previousPageTitle'] = __("Dashboard");
            $data['pageTitle'] = __("Create Call Center");
            $data['chatLog'] = [];
            $data['source'] = null;
            if ($callcenter_id != null) {
                $callcenter = decrypt($callcenter_id);
                $data['callcenterData'] = CallCenter::with(['sourceUrls', 'sourcePdf', 'sourceSummary', 'sourceQA'])->find($callcenter);
//                dd($data['callcenterData']);

//                $data['chatLog'] = ChatbotConversations::where(['user_id' => Auth::id(), 'chatbot_id' => $chatbot])->paginate(10);
                $data['callCenterId'] = $data['callcenterData']->callcenter_id;

                $urlLength = 0;
                $urlCount = 0;
                if (isset($data['callcenterData']->sourceUrls)) {
                    foreach ($data['callcenterData']->sourceUrls as $url) {
                        $urlLength = $urlLength + $url->length;
                        $urlCount++;
                    }
                }

                $pdfLength = 0;
                $pdfCount = 0;
                if (isset($data['callcenterData']->sourcePdf)) {
                    foreach ($data['callcenterData']->sourcePdf as $pdf) {
                        $pdfLength = $pdfLength + $pdf->length;
                        $pdfCount++;
                    }
                }

                $summaryCount = 0;
                $summaryLength = 0;
                if (isset($data['callcenterData']->sourceSummary)) {
                    $summaryLength = $data['callcenterData']->sourceSummary->length;
                    $summaryCount++;
                }

                $qaLength = 0;
                $qaCount = 0;
                if (isset($data['callcenterData']->sourceQA)) {
                    foreach ($data['callcenterData']->sourceQA as $qa) {
                        $qaLength = $qaLength + $qa->length;
                        $qaCount++;
                    }
                }

                $data['source'] = [
                    'url_count' => $urlCount,
                    'url_length' => $urlLength,
                    'pdf_count' => $pdfCount,
                    'pdf_length' => $pdfLength,
                    'summary_length' => $summaryLength,
                    'summary_count' => $summaryCount,
                    'qa_count' => $qaCount,
                    'qa_length' => $qaLength,
                    'totalChar' => $urlLength + $pdfLength + $summaryLength + $qaLength,
                ];
            } else {
                $data['callCenterId'] = chatBotIdGenerator();
            }
            $openAiConfiguration = OpenAiConfiguration::first(['character_limit']);
            $data['character_limit'] = isset($openAiConfiguration['character_limit']) ? $openAiConfiguration['character_limit'] : 0;
            $data['embed_key'] = encrypt([$data['callCenterId'], auth()->id(), request()->root()]);
//            $data['embed_code'] = request()->root() . '/embed/js/chatbot.js?embed_key=' . $data['embed_key'] . '&site_key=abcdefghijklmnopqrstwxyz';
//            $data['embed_init_code'] = '<script src="' . request()->root() . '/embed/js/chatbot.js?embed_key=' . $data['embed_key'] . '&site_key=abcdefghijklmnopqrstwxyz"></script>';

            return view('user.callcenter.create', $data);
        } catch (Exception $e) {
            return redirect()->back()->with('error', $e->errors())->withInput();
        }
    }

    public function store(CallCenterRequest $request)
    {
        if ($request->ajax()) {
            DB::beginTransaction();
            try {
                $callCenterId = decrypt($request->callcenter_id);
                $dataObj = CallCenter::where('callcenter_id', $callCenterId)->first();
                $msg = __("Update Successfully");
                if (empty($dataObj)) {
                    $dataObj = new CallCenter();
                    $msg = __("Created Successfully");
                }
                $dataObj->user_id = auth()->id();
                $dataObj->callcenter_id = $callCenterId;
                $dataObj->callcenter_name = $request->callcenter_name;
                $dataObj->twilio_sid = $request->twilio_sid;
                $dataObj->twilio_token = $request->twilio_token;
                $dataObj->twilio_agent_number = $request->twilio_agent_number;
                $dataObj->save();


                if (!is_null($request->source_url)) {
                    CallCenterSourceUrl::where(['user_id' => $dataObj->user_id, 'callcenter_id' => $dataObj->callcenter_id])->delete();
                    foreach ($request->source_url as $url) {

                        $callcenterSourceUrl = new CallCenterSourceUrl();
                        $callcenterSourceUrl->user_id = $dataObj->user_id;
                        $callcenterSourceUrl->url = $url['url'];
                        $callcenterSourceUrl->length = $url['length'];
                        $callcenterSourceUrl->callcenter_id = $dataObj->callcenter_id;
                        $callcenterSourceUrl->status = ACTIVE;
                        $callcenterSourceUrl->save();
                    }
                }


                if (!is_null($request->source_content)) {
                    $sourceContent = CallCenterSourceSummary::where(['user_id' => $dataObj->user_id, 'callcenter_id' => $dataObj->callcenter_id])->first();
                    if (empty($sourceContent)) {
                        $sourceContent = new CallCenterSourceSummary();
                    }
                    $sourceContent->user_id = $dataObj->user_id;
                    $sourceContent->callcenter_id = $dataObj->callcenter_id;
                    $sourceContent->content = $request->source_content;
                    $sourceContent->length = strlen($request->source_content);
                    $sourceContent->save();
                }


                if (!is_null($request->qas_list)) {
                    CallCenterSourceQA::where(['user_id' => $dataObj->user_id, 'callcenter_id' => $dataObj->callcenter_id])->delete();
                    if ($request->has('qas_list')) {
                        foreach ($request->qas_list as $item) {
                            $callcenterSourceQas = new CallCenterSourceQA();
                            $callcenterSourceQas->user_id = $dataObj->user_id;
                            $callcenterSourceQas->callcenter_id = $dataObj->callcenter_id;
                            $callcenterSourceQas->question = $item['question'];
                            $callcenterSourceQas->answer = $item['answer'];
                            $callcenterSourceQas->status = ACTIVE;
                            $callcenterSourceQas->length = strlen($item['question']) + strlen($item['answer']);;
                            $callcenterSourceQas->save();
                        }
                    }
                }

                if ($request->hasFile('source_pdf')) {
                    $fileName = 'uploads/user/callcenter/source_pdf/' . $dataObj->user_id . '-' . $dataObj->callcenter_id . '-' . time() . '.' . $request->source_pdf->getClientOriginalExtension();
                    $request->source_pdf->move(public_path('uploads/user/callcenter/source_pdf/'), $fileName);
                    $sourcePdf = new CallCenterSourcePdf();
                    $sourcePdf->user_id = $dataObj->user_id;
                    $sourcePdf->callcenter_id = $callCenterId;
                    $sourcePdf->pdf_path = $fileName;
                    $sourcePdf->file_name = $request->source_pdf->getClientOriginalName();
                    $sourcePdf->length = strlen(sourcePdfReader($fileName));
                    $sourcePdf->status = ACTIVE;
                    $sourcePdf->save();
                }

//                if ($request->remove_branding == 1){
//                    creditMinus(CREDIT_PERPUS_CHATBOT_BRANDING, auth()->id());
//                }

                DB::commit();
                return response()->json(['status' => 'success', 'message' => $msg, 'data' => []], 200);

            } catch (\Exception $exception) {
                DB::rollBack();
                dd($exception->getMessage());
                return response()->json(['status' => 'error', 'message' => 'Something Went Wrong', 'data' => []], 500);
            }
        }
    }

    public function appointmentsList($request)
    {
            $data = AppointmentRequest::where(['user_id' => auth()->id(), 'chatbot_id' => decrypt($request->chatbot_id)])->orderBy('id','DESC');

            return datatables($data)
                ->addIndexColumn()
                ->addColumn('name', function ($data) {
                    return $data->name;
                })
                ->addColumn('email', function ($data) {
                    return $data->email;
                })
                ->addColumn('phone', function ($data) {
                    return $data->phone;
                })
                ->addColumn('date_time', function ($data) {
                    return $data->date_time;
                })
                ->addColumn('created_at', function ($data) {
                    return $data->created_at;
                })
                ->rawColumns(['name', 'email', 'phone', 'created_at'])
                ->make(true);

    }


    public function leadsList($request)
    {
        $data = ChatbotLeads::where(['user_id' => auth()->id(), 'chatbot_id' => $request->chatbot_id]);
        return datatables($data)
            ->addIndexColumn()
            ->addColumn('name', function ($data) {
                return $data->name;
            })
            ->addColumn('email', function ($data) {
                return $data->email;
            })
            ->addColumn('phone', function ($data) {
                return $data->phone;
            })
            ->addColumn('created_at', function ($data) {
                return $data->created_at;
            })
            ->rawColumns(['name', 'email', 'phone', 'created_at'])
            ->make(true);
    }

    public function getDailyChartData($id = null)
    {
        $endDate = now();
        $startDate = $endDate->copy()->subDays(7);
        $chatBotConversations = ChatbotConversations::select('country', 'country_code')
            ->selectRaw('COUNT(*) as user_count')
            ->where('chatbot_id', decrypt($id))
            ->where('user_id', auth()->id())
            ->whereBetween('created_at', [$startDate, $endDate])
            ->groupBy('country', 'country_code')
            ->get()
            ->map(function ($item) {
                return [
                    'name' => $item->country,
                    'id' => $item->country_code,
                    'user_count' => $item->user_count
                ];
            });
        return response()->json($chatBotConversations);
    }

    public function getMonthlyChartData($id = null)
    {
        $currentDate = now();
        $startDate = $currentDate->copy()->subMonths(12)->startOfMonth();
        $chatBotConversations = ChatbotConversations::selectRaw('YEAR(created_at) as year, MONTH(created_at) as month, COUNT(DISTINCT session_id) as count')
            ->where('chatbot_id', decrypt($id))
            ->where('user_id', \auth()->id())
            ->where('created_at', '>=', $startDate)
            ->groupBy('year', 'month')
            ->orderBy('year')
            ->orderBy('month')
            ->get();

        return response()->json($chatBotConversations);
    }

    public function getWeeklyConversationData($id = null)
    {
        $endDate = now(); // Current date and time
        $startDate = $endDate->copy()->subDays(6)->startOfDay();

        $chatBotWeeklyConversations = ChatbotConversations::selectRaw('DATE(created_at) as date, COUNT(*) as count')
            ->where('chatbot_id', decrypt($id))
            ->where('user_id', \auth()->id())
            ->where('conversations_type', 'bot')
            ->whereBetween('created_at', [$startDate, $endDate])
            ->groupBy('date')
            ->orderBy('date', 'asc')
            ->get();

        return response()->json($chatBotWeeklyConversations);
    }

    public function getMonthlyLeadData($id = null)
    {
        $currentDate = now();
        $startDate = $currentDate->copy()->subMonths(12)->startOfMonth();

        // Retrieve and group leads by year and month
        $chatBotLeads = ChatbotLeads::selectRaw('YEAR(created_at) as year, MONTH(created_at) as month, COUNT(*) as count')
            ->where('chatbot_id', decrypt($id))
            ->where('user_id', \auth()->id())
            ->where('created_at', '>=', $startDate)
            ->groupBy('year', 'month')
            ->orderBy('year')
            ->orderBy('month')
            ->get();

        return response()->json($chatBotLeads);
    }

    public function chatLogSearch(Request $request)
    {
        $chatBotId = decrypt($request->chatbotId);
        $fromDate = null;
        $toDate = null;
        $query = null;
        $result = null;

        if ($request->type == 'date') {
            $dateArray = explode(' to ', $request->search_content);
            $fromDate = isset($dateArray[1]) ? $dateArray[0] : date('Y-m-d');
            $toDate = isset($dateArray[1]) ? $dateArray[1] : $dateArray[0];
        } else {
            $query = $request->search_content;
        }

        $dataQuery = ChatbotConversations::where('chatbot_id', $chatBotId);

        if (!is_null($query)) {
            $result['searchData'] = $dataQuery->where(function ($queryBuilder) use ($query) {
                $queryBuilder->where('message_user', 'LIKE', '%' . $query . '%')
                    ->orWhere('conversations_type', 'LIKE', '%' . $query . '%')
                    ->orWhere('message_content', 'LIKE', '%' . $query . '%');
            });
        }

        if (!is_null($fromDate) || !is_null($toDate)) {
            $dataQuery->whereBetween('created_at', [$fromDate, $toDate]);
            $data = $dataQuery->get();
            $result['searchData'] = $data->map(function ($item) {
                return [
                    'message_user' => $item->message_user,
                    'created_at' => $item->created_at->diffForHumans(),
                    'conversations_type' => $item->conversations_type,
                    'message_content' => $item->message_content
                ];
            });
        }


        $renderSearchData = view('user.chatbot.partial.chat-log-search-render', $result)->render();
        return response()->json(['status' => 'success', 'message' => __("Data Fetch Successful"), 'data' => $renderSearchData], 200);
    }

    public function sourceCount(Request $request)
    {
        try {
            if ($request->type == 'url') {
                $urlText = fetchUrlText($request->source);
                $textCount = count($urlText);

                if (!isset($urlText['characterCount'])){
                    return response()->json(['status' => 'error', 'message' => __("Reading content from this URL is not permitted.."), 'data' => []], 500);
                }


                $itemContent = '';
                if ($textCount != 0) {
                    $itemContent = '<li class="d-flex gap-3 align-items-center  bda-mb-20 url-delete-section single-url-box">
                            <input type="hidden" value="' . $urlText['characterCount'] . '" class="count-text source-url-length" name="source_url[][length]">
                            <button type="button" class="bda-delete-btu-acton url-delete">
                                <img src="' . asset('assets/images/icon/Delete.svg') . '" alt="">
                            </button>
                            <span>' . $request->source . '</span>
                            <input type="hidden" value="' . $request->source . '" name="source_url[][url]" class="source-url-url">
                        </li>';
                }

                $responseData = [
                    'item' => $itemContent,
                    'textCount' => $urlText['characterCount'],
                ];

                return response()->json(['status' => 'success', 'message' => __("Data Fetch Successful"), 'data' => $responseData], 200);
            }
        } catch (\Exception $exception) {
            return response()->json(['status' => 'error', 'message' => __("Something went wrong"), 'data' => []], 500);
        }
    }

    public function pdfSourceCount(Request $request)
    {
        try {
            $request->validate([
                'source_pdf' => 'required|mimes:pdf|max:2048',
            ]);

            $pdf = $request->file('source_pdf');
            $pdfContent = file_get_contents($pdf->getRealPath());
            $pdfPath = storage_path('app/temp.pdf');
            file_put_contents($pdfPath, $pdfContent);
            $parser = new Parser();
            $pdf = $parser->parseFile($pdfPath);
            $pages = $pdf->getPages();
            $characterCounts = [];
            foreach ($pages as $page) {
                $characterCounts[] = $page->getText();
            }
            $text = implode(" ", $characterCounts);
            unlink($pdfPath);
            $totalContentLength = strlen($text);

            $responseData = [
                'item' => null,
                'textCount' => $totalContentLength,
            ];

            return response()->json(['status' => 'success', 'message' => __("Data Fetch Successful"), 'data' => $responseData], 200);

        } catch (\Exception $exception) {
//            dd($exception->getMessage());
            return response()->json(['status' => 'error', 'message' => __("Something went wrong"), 'data' => []], 500);
        }
    }

    public function delete($id)
    {
        try {
            $chatbotId = decrypt($id);
            $chatbot = CallCenter::where('callcenter_id', $chatbotId)->first();

            if (!$chatbot) {
                return redirect()->route('user.dashboard')->with('error', __("Call Center not found."));
            }

            $chatbot->delete();
            return redirect()->route('user.dashboard')->with('success', __('Call Center deleted successfully.'));
        } catch (\Exception $exception) {
            Log::error('Call Center Deletion Error: ' . $exception->getMessage());
            return redirect()->route('user.dashboard')->with('error', __('Something went wrong. Please try again.'));
        }
    }

    function trainChatbot(Request $request)
    {
//        dd($request->all());
        try {

            $limitChack = OpenAiConfiguration::first(['character_limit']);

            if (is_null($limitChack)) {
                return response()->json(['status' => 'error', 'message' => __('Open AI configuration is not setup, Contact with admin!'), 'data' => []], 500);
            }

            if ($limitChack['character_limit'] < $request->totalChar) {
                return response()->json(['status' => 'error', 'message' => __('The training data is too large'), 'data' => []], 500);
            }

            $dataObj = CallCenter::where('callcenter_id', decrypt($request->callCenterId))->first();
            $dataObj = $dataObj->load(['sourceUrls', 'sourcePdf', 'sourceSummary', 'sourceQA']);

            // Check if all sources are empty
            $hasData = ($dataObj->sourceUrls ?? collect())->isNotEmpty() ||
                ($dataObj->sourcePdf ?? collect())->isNotEmpty() ||
                !empty($dataObj->sourceSummary) ||
                ($dataObj->sourceQA ?? collect())->isNotEmpty();

            if (!$hasData) {
                return response()->json(['status' => 'error', 'message' => 'Training data is empty'], 422);
            }

                $getActivePackage = Subscriber::where(['user_id' => \auth()->id(), 'status' => ACTIVE])->first();
                if (is_null($getActivePackage)) {
                    return response()->json(['status' => 'error', 'message' => __('You have no active package!'), 'data' => []], 500);
                }

            //credit distribution start
                $urlCount = count($dataObj->sourceUrls);
                $pdfCount = count($dataObj->sourcePdf);
                $havePlainTest = $dataObj->sourceSummary != null ? 1 : 0;
                $qaCount = count($dataObj->sourceQA);


                $creditConfigureData = CreditConfiguration::first();
                $chatbot_url_training_credit = $creditConfigureData->chatbot_url_training_credit ?? 1;
                $chatbot_pdf_training_credit = $creditConfigureData->chatbot_pdf_training_credit ?? 1;
                $chatbot_plain_text_training_credit = $creditConfigureData->chatbot_plain_text_training_credit ?? 1;
                $chatbot_qa_training_credit = $creditConfigureData->chatbot_qa_training_credit ?? 1;

                $chatbot_url_training_credit = $chatbot_url_training_credit * $urlCount;
                $chatbot_pdf_training_credit = $chatbot_pdf_training_credit * $pdfCount;
                $chatbot_plain_text_training_credit = $chatbot_plain_text_training_credit * $havePlainTest;
                $chatbot_qa_training_credit = $chatbot_qa_training_credit * $qaCount;

                $total = $chatbot_url_training_credit + $chatbot_pdf_training_credit + $chatbot_plain_text_training_credit + $chatbot_qa_training_credit;


                $haveblance = (($getActivePackage->credit - $getActivePackage->use_credit) >= $total) ? true : false;;

                if (!$haveblance) {
                    return response()->json(['success' => false, 'message' => 'You don\'t have enough credit'], 500);
                }

                creditMinus(CREDIT_PERPUS_CHATBOT_TRAINING, auth()->id(), $total);

            //credit distribution end

            // Define file path and name
            $fileName = 'uploads/user/callcenter/train_files/' . Auth::user()->id . '-' . $dataObj->callcenter_id . '.txt';
            $fullFilePath = public_path($fileName);

            // Create directory if it doesn't exist
            if (!File::exists(public_path('uploads/user/callcenter/train_files/'))) {
                File::makeDirectory(public_path('uploads/user/callcenter/train_files/'), 0755, true);
            }

            // Remove existing file if it exists
            if ($dataObj->sources_file_path != null) {
                $publicPath = public_path($dataObj->sources_file_path);
                if (File::exists($publicPath)) {
                    unlink($publicPath);
                }
            }

            // Initialize text content

            $textContent = '';

            // Append text content from sourceUrls
            if ($dataObj->sourceUrls->isNotEmpty()) {
                foreach ($dataObj->sourceUrls as $source_url) {
                    $content = fetchUrlText($source_url->url);
                    $textContent .= $content['textContent'] . "\n";
                }
            }

            // Append text content from chatbotSourcePdf
            if ($dataObj->sourcePdf->isNotEmpty()) {
                foreach ($dataObj->sourcePdf as $source_pdf) {
                    $pdfText = sourcePdfReader($source_pdf->pdf_path);
                    $textContent .= $pdfText . "\n";
                }
            }

            // Append text content from chatbotText
            if ($dataObj->sourceSummary) {
                $textContent .= $dataObj->sourceSummary . "\n";
            }

            // Append formatted Q&A
            if ($dataObj->sourceQA->isNotEmpty()) {
                $questionIndex = 1;
                foreach ($dataObj->sourceQA as $source_Qas) {
                    $textContent .= "Question $questionIndex: " . $source_Qas->question . "\n";
                    $textContent .= "Answer: " . $source_Qas->answer . "\n\n";
                    $questionIndex++;
                }
            }

            // Write the content to the file
            File::put($fullFilePath, $textContent);

            // Update data object with new file path
            $dataObj->sources_file_path = $fileName;
            $dataObj->save();
            return response()->json(['status' => 'success', 'message' => 'Trained Successfully'], 200);
        } catch (ValidationException $e) {
            $errors = $e->errors();
            $firstErrorMessage = reset($errors)[0];
            return response()->json(['status' => 'success', 'message' => $firstErrorMessage], 500);
        }
    }


    public function handleIncomingCall(Request $request){

        dd($request->all());
        $callCenterId = $request->get('cid');

        $response = new \Twilio\TwiML\VoiceResponse();

        $response->record([
            'action' => url('/call-center/recording/webhook') . '?cid=' . $callCenterId,
            'method' => 'POST',
            'maxLength' => 30,
            'playBeep' => true,
            'timeout' => 5
        ]);

        return response($response, 200)->header('Content-Type', 'text/xml');
    }


    public function handleRecording(Request $request){

        $recordingUrl = $request->input('RecordingUrl');
        $callCenterId = $request->query('cid');
        $callerNumber = $request->input('From');

        dd($recordingUrl, $callCenterId, $callerNumber);

    }


}
