<?php

namespace App\Http\Controllers\PhoneBook;

use App\Http\Controllers\Controller;
use App\Models\Group;
use App\Models\Number;
use App\Helpers\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class NumberController extends Controller
{
    use Helper;

    public function __construct()
    {
        $this->model = new Number();
    }

    public function index()
    {
        if (!can('number_list_view')) {
            return $this->notPermitted();
        }

        try {
            $userId = auth()->user()->id;
            $keyword = request()->input('keyword') ?: request()->input('number') ?: request()->input('phone');
            $groupId = request()->input('group_id');
            $perPage = (int) request()->input('perPage', 20);

            $data = $this->model
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->when($groupId !== null && $groupId !== '', function ($query) use ($groupId) {
                    if ((int) $groupId === 0) {
                        $query->where(function ($q) {
                            $q->whereNull('group_id')->orWhere('group_id', 0);
                        });
                    } else {
                        $query->where('group_id', (int) $groupId);
                    }
                })
                ->when($keyword, function ($query) use ($keyword) {
                    $query->where(function ($q) use ($keyword) {
                        $q->where('number', 'LIKE', "%{$keyword}%")
                          ->orWhere('name', 'LIKE', "%{$keyword}%")
                          ->orWhere('notes', 'LIKE', "%{$keyword}%");
                    });
                })
                ->with('group')
                ->orderBy('id', 'desc')
                ->paginate($perPage);

            return returnData(2000, $data);
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), $exception->getMessage());
        }
    }

    public function create()
    {
        //
    }

    public function store(Request $request)
    {
        if (!can('number_list_add')) {
            return $this->notPermitted();
        }

        try {
            $userId = auth()->user()->id;
            $groupId = (int) $request->input('group_id', 0);
            $notes = $request->input('notes');

            // Check if bulk numbers provided
            $isBulk = $request->boolean('is_bulk', false) || $request->filled('bulk_numbers');
            $bulkRaw = $request->input('bulk_numbers') ?: $request->input('total_number');

            if ($isBulk && !empty($bulkRaw)) {
                $lines = preg_split('/[\r\n,]+/', (string) $bulkRaw);
                $inserted = [];
                $count = 0;

                foreach ($lines as $line) {
                    $cleaned = preg_replace('/[^\d+]/', '', trim($line));
                    if (!empty($cleaned)) {
                        $inserted[] = [
                            'user_id' => $userId,
                            'group_id' => $groupId,
                            'name' => null,
                            'number' => $cleaned,
                            'notes' => $notes ? trim((string) $notes) : null,
                            'created_at' => now(),
                            'updated_at' => now(),
                        ];
                        $count++;
                    }
                }

                if (empty($inserted)) {
                    return returnData(3000, ['bulk_numbers' => ['No valid phone numbers found in input.']], 'Validation Failed');
                }

                // Chunk insertions to protect memory
                foreach (array_chunk($inserted, 500) as $batch) {
                    Number::insert($batch);
                }

                return returnData(2000, ['count' => $count], "Successfully added {$count} phone number(s)");
            }

            // Single number
            $rawNumber = $request->input('number') ?: $request->input('phone');
            $cleanNumber = preg_replace('/[^\d+]/', '', trim((string) $rawNumber));

            if (empty($cleanNumber)) {
                return returnData(3000, ['number' => ['The phone number is required.']], 'Validation Failed');
            }

            $name = $request->input('name');

            $number = Number::create([
                'user_id' => $userId,
                'group_id' => $groupId,
                'name' => $name ? trim((string) $name) : null,
                'number' => $cleanNumber,
                'notes' => $notes ? trim((string) $notes) : null,
            ]);

            return returnData(2000, $number->load('group'), 'Phone number added successfully');
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), $exception->getMessage());
        }
    }

    public function show($id)
    {
        try {
            $userId = auth()->user()->id;
            $number = Number::with('group')
                ->where('id', $id)
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->first();

            if (!$number) {
                return returnData(5000, null, 'Phone number not found');
            }

            return returnData(2000, $number);
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), $exception->getMessage());
        }
    }

    public function edit($id)
    {
        //
    }

    public function update(Request $request, $id)
    {
        if (!can('number_list_update')) {
            return $this->notPermitted();
        }

        try {
            $userId = auth()->user()->id;
            $number = Number::where('id', $id)
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->first();

            if (!$number) {
                return returnData(5000, null, 'Phone number not found');
            }

            $rawNumber = $request->input('number') ?: $request->input('phone');
            $cleanNumber = preg_replace('/[^\d+]/', '', trim((string) $rawNumber));

            if (empty($cleanNumber)) {
                return returnData(3000, ['number' => ['The phone number is required.']], 'Validation Failed');
            }

            $number->number = $cleanNumber;
            if ($request->has('name')) {
                $number->name = $request->input('name') ? trim((string) $request->input('name')) : null;
            }
            if ($request->has('group_id')) {
                $number->group_id = (int) $request->input('group_id', 0);
            }
            if ($request->has('notes')) {
                $number->notes = $request->input('notes') ? trim((string) $request->input('notes')) : null;
            }
            $number->save();

            return returnData(2000, $number->load('group'), 'Phone number updated successfully');
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), $exception->getMessage());
        }
    }

    public function destroy($id)
    {
        if (!can('number_list_delete')) {
            return $this->notPermitted();
        }

        try {
            $userId = auth()->user()->id;
            $number = Number::where('id', $id)
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->first();

            if (!$number) {
                return returnData(5000, null, 'Phone number not found');
            }

            $number->delete();

            return returnData(2000, null, 'Phone number deleted successfully');
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), 'Whoops, Something Went Wrong..!!');
        }
    }

    public function bulkDelete(Request $request)
    {
        if (!can('number_list_delete')) {
            return $this->notPermitted();
        }

        try {
            $userId = auth()->user()->id;
            $ids = $request->input('ids', []);

            if (!is_array($ids) || empty($ids)) {
                return returnData(3000, null, 'No numbers selected for deletion');
            }

            $deleted = Number::whereIn('id', $ids)
                ->where(function ($q) use ($userId) {
                    $q->where('user_id', $userId)->orWhere('user_id', 0);
                })
                ->delete();

            return returnData(2000, ['deleted' => $deleted], "Successfully deleted {$deleted} phone number(s)");
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), 'Whoops, Something Went Wrong..!!');
        }
    }

    public function bulkImport(Request $request)
    {
        if (!can('number_list_add')) {
            return $this->notPermitted();
        }

        try {
            $userId = auth()->user()->id;
            $groupId = (int) $request->input('group_id', 0);
            $rawText = (string) $request->input('numbers_text', '');
            $notes = $request->input('notes');

            $lines = preg_split('/[\r\n,]+/', $rawText);
            $inserted = [];
            $count = 0;

            foreach ($lines as $line) {
                $cleaned = preg_replace('/[^\d+]/', '', trim($line));
                if (!empty($cleaned)) {
                    $inserted[] = [
                        'user_id' => $userId,
                        'group_id' => $groupId,
                        'name' => null,
                        'number' => $cleaned,
                        'notes' => $notes ? trim((string) $notes) : null,
                        'created_at' => now(),
                        'updated_at' => now(),
                    ];
                    $count++;
                }
            }

            if (empty($inserted)) {
                return returnData(3000, null, 'No valid phone numbers found to import');
            }

            foreach (array_chunk($inserted, 500) as $batch) {
                Number::insert($batch);
            }

            return returnData(2000, ['count' => $count], "Successfully imported {$count} numbers");
        } catch (\Exception $exception) {
            return returnData(5000, $exception->getMessage(), 'Whoops, Something Went Wrong..!!');
        }
    }
}
