<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;

class ClientsController extends Controller
{
    public function index(){
        $countries     = Models\Country::pluck('en_short_name', 'en_short_name');
        $service_type  = Models\Service::pluck('name', 'name');
        $staff_members  = Models\StaffMember::pluck('name', 'id');
        // dd($staff_members);

        $data = [
            'page_title' => 'Dashboard', 
            'service_types' => $service_type,
            'countries' => $countries,
            'staff_members' => $staff_members
        ];
        return view('clients.index', $data);
    }
    

    public function show(int $id)
    {
        $showclient = Models\Client::with([
            'service_info',
            'country_flag_info',
            'auth_user_info',
            'short_code_info',
        ])->findOrFail($id);

        $progress_indicators = Models\ClientIndicator::pluck('name', 'name');
        $service_type = Models\Service::pluck('name', 'id');
        $service_type_names = Models\Service::pluck('name', 'name');
        $show_services = Models\ClientCategory::where('client_id', $id)->get();

        $country_networks = DB::table('network_operators')
            ->selectRaw('id, CONCAT(name, " (", country, ")") AS network')
            ->orderBy('network')
            ->pluck('network', 'network');

        $auth_users = Models\SystemUser::orderBy('name')->pluck('name', 'id');

        $networks_raw = [
            'AirtelTigo GH',
            'MTN GH',
            'Airtel MW',
            'Airtel Zambia',
            'TNM MW',
            'Safaricom Kenya',
            'Airtel Kenya',
            'Telkom Kenya',
            'Orange Kenya',
        ];

        $show_notes_query = Models\ClientNote::with(['created_by_info', 'client_info'])
            ->where('client_id', $id)
            ->latest();

        $show_notes = $show_notes_query->take(20)->get();
        $show_notes_highlight = (clone $show_notes_query)
            ->where('highlight', 'YES')
            ->take(1)
            ->get();

        $voice_codes = Models\ClientShortCode::where('client_id', $id)
            ->where('code_type', 'voice')
            ->get();

        $sms_codes = Models\ClientShortCode::where('client_id', $id)
            ->where('code_type', 'sms')
            ->get();

        $ussd_codes = Models\ClientShortCode::where('client_id', $id)
            ->where('code_type', 'ussd')
            ->get();

        $recent_payments = Models\ClientPayment::where('client_id', $id)
            ->latest('id')
            ->get();

        $countries = Models\Country::pluck('en_short_name', 'en_short_name');
        $networks = Models\NetworkOps::pluck('name', 'id');

        $support_fees = Models\ClientSupportFees::where('client_id', $id)
            ->latest('id')
            ->get();

        $showdocuments = Models\ClientFile::where('client_id', $id)->get();

        $status_bg = match ($showclient->status) {
            'Live' => 'info',
            'Prospective' => 'warning',
            default => 'danger',
        };

        $progress_status_bg = match (true) {
            $showclient->progress_indicator_score >= 70 => 'success',
            $showclient->progress_indicator_score >= 50 => 'warning',
            default => 'danger',
        };

        [$renewal_due, $highlight_colour] = $this->getRenewalDue(
            $showclient->contract_validity
        );

        $recurring_arr = [
            'NO' => 'NO',
            'Monthly' => 'Monthly',
            'Quarterly' => 'Quarterly',
            'Semiannual' => 'Semiannual',
            'Yearly' => 'Yearly',
        ];

        $sender_id_statuses = [
            'Pending' => 'Pending',
            'Inactive' => 'Inactive',
            'Approved' => 'Approved',
        ];

        $change_account_mgr_permission = Config::get('permissions.CHANGE_ACCOUNT_MANAGERS');
        // dump($change_account_mgr_permission);
        $change_account_mgr_permission = $this->hasAnyAccess([$change_account_mgr_permission]) ? 'YES' : 'NO';
        // dd($change_account_mgr_permission);
        return view('clients.show', [
            'page_title' => 'Client Profile',
            'showclient' => $showclient,
            'show_services' => $show_services,
            'service_type' => $service_type,
            'service_type_names' => $service_type_names,
            'show_notes' => $show_notes,
            'show_notes_highlight' => $show_notes_highlight,
            'status_bg' => $status_bg,
            'progress_status_bg' => $progress_status_bg,
            'voice_codes' => $voice_codes,
            'sms_codes' => $sms_codes,
            'ussd_codes' => $ussd_codes,
            'countries' => $countries,
            'networks' => $networks,
            'progress_indicators' => $progress_indicators,
            'networks_raw' => array_combine($networks_raw, $networks_raw),
            'renewal_due' => $renewal_due,
            'recent_payments' => $recent_payments,
            'highlight_colour' => $highlight_colour,
            'showdocuments' => $showdocuments,
            'support_fees' => $support_fees,
            'recurring_arr' => $recurring_arr,
            'sender_id_statuses' => $sender_id_statuses,
            'change_account_mgr_permisson' => $change_account_mgr_permission,
            'am_list_arr' => $auth_users,
            'country_network_arr' => $country_networks,
            'mnos_arr' => ['' => '-- Select Country first --'],
        ]);
    }

    private function getRenewalDue(?string $contractValidity): array
    {
        if (blank($contractValidity)) {
            return ['N/A', 'none'];
        }

        $expiryDate = Carbon::parse($contractValidity)->startOfDay();
        $today = now()->startOfDay();

        if ($expiryDate->greaterThanOrEqualTo($today)) {
            $days = $today->diffInDays($expiryDate);

            return match (true) {
                $days > 365 => ['In ' . floor($days / 365) . ' year(s)', 'none'],
                $days > 31 => ['In ' . floor($days / 31) . ' month(s)', 'none'],
                default => ['In ' . $days . ' day(s)', 'none'],
            };
        }

        $days = $expiryDate->diffInDays($today);

        return match (true) {
            $days > 365 => ['Contract expired ' . floor($days / 365) . ' year(s) ago', 'warning'],
            $days > 31 => ['Contract expired ' . floor($days / 31) . ' month(s) ago', 'warning'],
            default => ['Contract expired ' . $days . ' day(s) ago', 'warning'],
        };
    }

    

    private function buildFilteredQuery(Request $request)
    {
        $query = Models\Client::query();

        if ($request->filled('search')) {
            $searchTerm = $request->search;
            $query->where(function ($q) use ($searchTerm) {
                $q->where('name', 'like', "%{$searchTerm}%")
                  ->orWhere('email', 'like', "%{$searchTerm}%")
                  ->orWhere('contact_person', 'like', "%{$searchTerm}%");
            });
        }

        if ($request->filled('service')) {
            $query->whereJsonContains('services', strtoupper($request->service));
        }

        if ($request->filled('billing')) {
            $query->where('pay_mode', $request->billing);
        }
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        // return $query->orderBy('created_at', 'desc');
        return $query->orderBy('name', 'asc');
    }

    /**
     * Your existing AJAX fetch method (Refactored to use the new builder)
     */
    public function fetchData(Request $request)
    {
        if (!auth()->check()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }
        $clients = $this->buildFilteredQuery($request)->paginate(30);
        return response()->json($clients);
    }

    /**
     * Handle the Export Request
     */
    public function export(Request $request)
    {
        // Get the filtered data but execute get() instead of paginate()
        $clients = $this->buildFilteredQuery($request)->get();
        $format = $request->input('format', 'csv');

        if ($format === 'pdf') {
            return $this->exportToPdf($clients);
        }

        return $this->exportToCsv($clients);
    }

    /**
     * Generate Native CSV (Opens perfectly in Excel without massive dependencies)
     */
    private function exportToCsv($clients)
    {
        $fileName = 'clients_export_' . date('Y-m-d_H-i') . '.csv';

        $headers = [
            "Content-type"        => "text/csv",
            "Content-Disposition" => "attachment; filename=$fileName",
            "Pragma"              => "no-cache",
            "Cache-Control"       => "must-revalidate, post-check=0, pre-check=0",
            "Expires"             => "0"
        ];

        $columns = ['ID', 'Company Name', 'Contact Person', 'Email', 'Phone', 'Country', 'Pay Mode', 'Status'];

        $callback = function() use($clients, $columns) {
            $file = fopen('php://output', 'w');
            fputcsv($file, $columns);

            foreach ($clients as $client) {
                $row['ID']  = $client->id;
                $row['Company Name']    = $client->name;
                $row['Contact Person']  = $client->contact_person;
                $row['Email']  = $client->email;
                $row['Phone']  = $client->phone;
                $row['Country']  = $client->country;
                $row['Pay Mode']  = $client->pay_mode;
                $row['Status']  = $client->status;

                fputcsv($file, array_values($row));
            }

            fclose($file);
        };

        return new StreamedResponse($callback, 200, $headers);
    }

    /**
     * Generate PDF
     */
    private function exportToPdf($clients)
    {
        // You will need to create a simple blade view for the PDF layout: resources/views/exports/clients_pdf.blade.php
        $pdf = Pdf::loadView('exports.clients_pdf', ['clients' => $clients])
                  ->setPaper('a4', 'landscape');
        
        return $pdf->download('clients_export_' . date('Y-m-d_H-i') . '.pdf');
    }

    public function store(Request $request): JsonResponse|RedirectResponse
    {

        $request->validate([
            'name'         => 'required|unique:clients,name',
            'email'        => 'required|email',
            'services'     => 'required|array',
            'country'      => 'required',
            'status'       => 'required',
            'payment_mode' => 'required',
            'currency'     => 'required',
            'company_type' => 'required',
            'industry'     => 'required',
            'account_manager' => 'required',
        ]);

        $onboarding_stages = Models\ClientOnboardingMainStage::orderBy('stage_id')->get();
        $client_current_stages = [];

        foreach ($onboarding_stages as $value) {
            $client_current_stages[$value->stage] = "PENDING";
        }

        $client_arr = [
            'name'                      => $request->name,
            'email'                     => $request->email,
            'country'                   => $request->country,
            'status'                    => $request->status,
            'pay_mode'                  => $request->payment_mode,
            'currency'                  => $request->currency,
            'auth_user_id'              => $request->auth_user_id,
            'created_by'                => Auth::user()->id,
            'last_modified_by'          => Auth::user()->id,
            'progress_indicator_score'  => 10,
            'progress_indicator'        => $onboarding_stages[0]->stage,
            'onboarding_progress_stage' => json_encode($client_current_stages),
            'notes'                     => $request->notes,
            'services'                  => json_encode($request->services),
            'phone'                     => $request->phone,
            'skype_name'                => $request->skype_name,
            'linkedin_name'             => $request->linkedin_name,
            'contact_person'            => $request->contact_person,
            'company_type'              => $request->company_type,
            'industry'                  => $request->industry,
        ];
        $result = Models\Client::create(array_filter($client_arr)); 


        $get_stage_subs_items = Models\ClientOnboardingSubItem::get();
        foreach ($get_stage_subs_items as $value) {
            Models\ClientOnboardingProgress::create([
                'stage_id'  => $value->stage_id,
                'client_id' => $result->id,
                'name'      => $value->name,
                'status'    => 'PENDING'
            ]);
        }

        if (in_array('USSD', $request->services)) {
            Log::info('ussd client detected');
            Models\UssdClientPayment::create([
                'client_id'           => $result->id,
                'last_modified_by_id' => session('current_user.id')
            ]);
        }

        Models\UserActivity::create([
            'type'       => 'staff',
            'content'    => session('current_user.name') . " added a new client ({$result->name}) successfully!",
            'user_id'    => session('current_user.id'),
            'ip_address' => request()->ip(),
            'device'     => $request->header('User-Agent')
        ]);

        if ($request->ajax() || $request->wantsJson()) {
            return response()->json([
                'success' => true,
                'message' => 'Client successfully added',
                'data'    => $result
            ]);
        }

        Session::flash('success_message', 'Client successfully added');
        return redirect('clients');
    }


    
    
    public function storeFiles(AddFilesRequest $request){
        $document_arr = $request->except('document');
        if ($request->hasFile('document')) {
           if ($request->file('document')->isValid()) {
                $filename = "erp_" . time() . "." . $request->document->extension();
                $request->document->storeAs('client_files', $filename, 'public');
                $document_arr['document'] = json_encode([$filename]);
            }
        }
        $client = Models\Client::find($request->client_id);
        $document_arr['file_extension'] = $request->document->extension();
        $document_arr['file_reff'] = time() . uniqid();
        $document_arr['last_modified_by'] = session('current_user.id');

        $result = Models\ClientFile::create($document_arr);

        if ($result) {
            $data = ['code' => 1, 'msg' => 'Document successfully uploaded'];
        }
        else{
            $data = ['code' => 3, 'msg' => 'Your request could not be handled at this time'];
        }
        $user_id = session('current_user.id');
        $username = session('current_user.name');
        $content  = "User ID : " . $user_id . " (" . $username . ") Document successfully uploaded for " . $client->name;
        $this->logUsersActivity($type = 'staff', $content);
        return response()->json($data, 200);

    }
    public function getClientFile($id){
        $client_file = Models\ClientFile::with('client_info')->findOrFail($id);
        $file = public_path('documents/client_files/') .  $client_file->file_path;

        $headers = []; 
        $filename = $client_file->client_info->name . "_" . $client_file->name;
        $filename = $this->cleanStr($filename);
        $filename = $filename  . "." . $client_file->file_extension;
        return \Response::download($file, $filename, $headers);
    }
    public function paymentsStore(Request $request){
        $request->validate([
            'client_id' => 'required',
            'services' => 'required',
            'invoice_number' => 'required',
            'invoice_amount' => 'required|numeric',
            'invoice_date' => 'required',
            'invoice_status' => 'required',
        ]);
        $auth_user = session('current_user');
        
        if ($request->short_code !== null) {
            $check = is_numeric($request->short_code);
            if ($check == false) {
              $data = ['code' => 3, 'msg' => 'Short Code must be a number'];
              return response()->json($data, 200);
            }
        }
        
        $finance_arr = [
          'invoice_number' => $request->invoice_number,
          'invoice_amount' => $request->invoice_amount,
          'invoice_date' => $request->invoice_date,
          'invoice_status' => $request->invoice_status,
          'short_code' => ($request->short_code) ? $request->short_code : "",
          'services' => implode(',', $request->services),
          'user_id' => $auth_user['id'],
          'client_id' => $request->client_id
        ];
        if ($request->has('remarks')) {
            $finance_arr['remarks'] = $request->remarks;
        }
        $client = Models\Client::find($request->client_id);
        $result = Models\ClientPayment::updateOrCreate(['invoice_number' =>  $request->invoice_number, 'client_id' => $request->client_id, ], $finance_arr);
        if ($request->has('short_code')) {
            $short_code_list = Models\ClientShortCode::where('client_id', $request->client_id)->get();
            $client = Models\Client::find($request->client_id);
            $message_body = $auth_user['name'] . " has added a new Short Code ($request->short_code) Payment entry for " . $client->name;
            
            dispatch(new SendShortCodeListToFinance($short_code_list, $message_body, $finance_arr));
        }

        #$payments = Models\ClientPayment::with('client_info', 'created_by_info')->find($result->id);
        if ($result) {
            $data = ['code' => 1, 'msg' => 'Payment Details successfully added'];
        }
        else{
            $data = ['code' => 3, 'msg' => 'Your request could not be handled at this time'];
        }
        $user_id = session('current_user.id');
        $username = session('current_user.name');
        $content  = "User ID : " . $user_id . " (" . $username . ") Added a payment record for : " . $client->name;
        $this->logUsersActivity($type = 'staff', $content);
        return response()->json($data, 200);
    }
    public function financeUpdate(Request $request){
        $request->validate([
            'payment_id' => 'required',
            'client_id' => 'required',
            'services' => 'required',
            'invoice_number' => 'required',
            'invoice_amount' => 'required|numeric',
            'invoice_date' => 'required',
            'invoice_status' => 'required'
        ]);
        
        $auth_user = session('current_user');
        $payment = Models\ClientPayment::findOrFail($request->payment_id);

        $payment->invoice_number = $request->invoice_number;
        $payment->invoice_amount = $request->invoice_amount;
        $payment->invoice_date = $request->invoice_date;
        $payment->invoice_status = $request->invoice_status;
        $payment->short_code = ($request->short_code) ? $request->short_code : "";

        $payment->services = implode(',', $request->services);
        $result = $payment->save();
        $client = Models\Client::find($request->client_id);
        if ($request->has('short_code')) {
            $short_code_list = Models\ClientShortCode::where('client_id', $request->client_id)->get();
            
            $finance_arr = [
              'invoice_number' => $request->invoice_number,
              'invoice_amount' => $request->invoice_amount,
              'invoice_date' => $request->invoice_date,
              'invoice_status' => $request->invoice_status,
              'short_code' => ($request->short_code) ? $request->short_code : "",
              'services' => implode(',', $request->services),
              'user_id' => $auth_user['id'],
              'client_id' => $request->client_id
            ];
            if ($request->has('remarks')) {
                $finance_arr['remarks'] = $request->remarks;
            }
            $message_body = $auth_user['name'] . " has updated a Short Code ($request->short_code) Payment entry for " . $client->name;
            #dispatch(new SendShortCodeListToFinance($short_code_list, $message_body, $finance_arr));
        }
        
        if ($result) {
            $data = ['code' => 1, 'msg' => 'Payment Details successfully updated'];
        }
        else{
            $data = ['code' => 3, 'msg' => 'Your request could not be handled at this time'];
        }
        $user_id = session('current_user.id');
        $username = session('current_user.name');
        $content  = "User ID : " . $user_id . " (" . $username . ") updated an existing payment record for " . $client->name;
        $this->logUsersActivity($type = 'staff', $content);


        
        return response()->json($data, 200);
    }
    public function shortcodeStore(Request $request){
        $request->validate([
            'client_id' => 'required',
            'network' => 'required',
            'shortcode' => 'required',
            'code_type' => 'required',
            'toll_free' => 'required',
            'status' => 'required',
            'remarks' => 'required',
            'launch_date' => 'required',
            'expiry_date' => 'required',
            'monthly_fee' => 'sometimes'
        ]);
        $auth_user = session('current_user');
        
        $shortcode_arr = [
          'name' => $request->name,
          'client_id' => $request->client_id,
          'network' => $request->network,
          // 'country' => $mnoCountry, //$network->country,
          'shortcode' => $request->shortcode,
          'code_type' => $request->code_type,
          'toll_free' => $request->toll_free,
          'last_updated_by' => $auth_user['id'],
          'launch_date' => $request->launch_date,
          'expiry_date' => $request->expiry_date,
          'status' => $request->status

        ];

        // dd($shortcode_arr);
        if ($request->has('remarks')) {
            $shortcode_arr['remarks'] = $request->remarks;
        }
        if ($request->has('monthly_fee')) {
            $shortcode_arr['monthly_fee'] = $request->monthly_fee;
        }
        
        $result = Models\ClientShortCode::create($shortcode_arr);
        $client = Models\Client::find($request->client_id);
        if ($result) {
            $data = ['code' => 1, 'msg' => 'ShortCode Details successfully added'];
        }
        else{
            $data = ['code' => 3, 'msg' => 'Your request could not be handled at this time'];
        }
        $user_id = session('current_user.id');
        $username = session('current_user.name');
        $content  = "User ID : " . $user_id . " (" . $username . ") Added new short code for " . $client->name;
        $this->logUsersActivity($type = 'staff', $content);
        return response()->json($data, 200);
    }
    public function shortCodeUpdate(Request $request){
        $request->validate([
            'client_id' => 'required',
            'network' => 'required',
            'shortcode' => 'required',
            'code_type' => 'required',
            'toll_free' => 'required',
            'monthly_fee' => 'sometimes',
            'status' => 'required',
            'remarks' => 'required',
            'launch_date' => 'required',
            'expiry_date' => 'required'
        ]);
        $auth_user = session('current_user');
        $mnoCountry = $this->getMnoCountry($request->network);
        if ($mnoCountry == false) {
          $data = ['code' => 3, 'msg' => 'Your request could not be handled at this time'];
          return response()->json($data, 200);
          // code...
        }
        $shortcode_arr = [
          'name' => $request->name,
          'client_id' => $request->client_id,
          'network' => $request->network,
          'country' => $mnoCountry, 
          'shortcode' => $request->shortcode,
          'code_type' => $request->code_type,
          'toll_free' => $request->toll_free,
          'last_updated_by' => $auth_user['id'],
          'launch_date' => $request->launch_date,
          'expiry_date' => $request->expiry_date,
          'status' => $request->status
        ];
        if ($request->has('remarks')) {
            $shortcode_arr['remarks'] = $request->remarks;
        }
        if ($request->has('monthly_fee')) {
            $shortcode_arr['monthly_fee'] = $request->monthly_fee;
        }
        $result = Models\ClientShortCode::where('id', $request->shortcode_id)->update($shortcode_arr);

        if ($result) {
            $data = ['code' => 1, 'msg' => 'Short Code Details successfully updated'];
        }
        else{
            $data = ['code' => 3, 'msg' => 'Your request could not be handled at this time'];
        }
        $user_id = session('current_user.id');
        $username = session('current_user.name');
        $content  = "User ID : " . $user_id . " (" . $username . ") updated short code enty for " . $request->short_code;
        $this->logUsersActivity($type = 'staff', $content);
        return response()->json($data, 200);
    }
    
}
