<?php

namespace App\Http\Controllers;

use App\Helpers\Formatter;
use App\Helpers\Helpers;
// Removed unknown Module import
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\TransactionExport;
use App\Http\Controllers\SendmsgController;
use App\Models\Device;
use App\Models\Package;
use App\Models\Subscriber;
use App\Models\Transaction;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules;

class UserController extends Controller
{
  public function list(Request $request)
  {
    $users = User::latest()->search($request->search)->paginate()->appends($request->all());
    $totalUsers = User::count();
    $unverifiedUsers = User::where('email_verified_at', null)->count();
    $verifiedUsers = $totalUsers - $unverifiedUsers;
    $currentSent = User::sum('current_sent');
    $totalSent = User::sum('total_sent');
    $totalDevices = Device::count();
    $onlineDevices = Device::where('status', '=', 'ONLINE')->count();
    $offlineDevices = $totalDevices - $onlineDevices;
    $totalSubscribers = Subscriber::count();
    $subSubscribers = Subscriber::where('status', '=', 1)->count();
    $unsubSubscribers = $totalSubscribers - $subSubscribers;
    $packages = Package::all();
    $intervals = ['monthly'];
    return view('/user-list', compact('users', 'totalUsers', 'verifiedUsers', 'unverifiedUsers', 'currentSent', 'totalSent', 'totalDevices', 'onlineDevices', 'offlineDevices', 'totalSubscribers', 'subSubscribers', 'unsubSubscribers', 'packages', 'intervals'));
  }

  public function show(Request $request)
  {
    $user_id = $request->user_id ?? auth()->user()->id;
    if (auth()->user()->id != $user_id && auth()->user()->role !== 'admin') {
      return redirect()->back()->with(['danger_alert' => __('You are not allowed to show User')]);
    }
    $status = 'Loading...';
    if (empty(Helpers::setting('currencyCode'))) {
      $currencyCode = 'USD';
    } else {
      $currencyCode = Helpers::setting('currencyCode');
    }
    $adminSender = Device::where('user_id', 1)->where('status', '=', 'ONLINE')->value('sender');
    $adminUsers = User::where('role', '=', 'admin')->get();
    $userUsers = User::where('role', '=', 'user')->get();
    $user = User::where('id', '=', $user_id)->first();
    $packages = Package::where('name', '<>', 'super')
      ->where('hidden', 0)
      ->where('name', '<>', 'trial')
      ->where('id', '<>', $user->package?->id)
      ->get();
    $daysTotal = Carbon::parse($user->billing_start)->diffInSeconds($user->billing_end, false) / 86400;
    $daysUsed = Carbon::parse($user->billing_start)->diffInseconds(now()) / 86400;
    $daysRemaining = Carbon::now()->diffInseconds($user->billing_end, false) / 86400;
    if ($daysTotal <= 0) {
      $percentUsed = 100;
    } else {
      $percentUsed = round(($daysUsed / $daysTotal) * 100, 2);
    }
    if ($daysRemaining > 0 || $user->role === 'admin' || !Helpers::isEx()) {
      $status = 'ACTIVE';
    } else {
      $status = 'EXPIRED';
    }
  $modules = [];
    // Get active payment gateways
    $paymentGateways = \App\Models\PaymentGateway::where('is_active', true)
        ->orderBy('sort_order', 'asc')
        ->get();
    $topupValues = array_map('intval', explode(',', Helpers::setting('topupValues')));
    $intervals = ['monthly'];
    $walletBalance = $user->transactions()->sum('amount');
    return view('/user-show', compact('adminSender', 'adminUsers', 'userUsers', 'user', 'packages', 'daysTotal', 'daysUsed', 'daysRemaining', 'percentUsed', 'status', 'currencyCode', 'modules', 'paymentGateways', 'topupValues', 'intervals', 'walletBalance'));
    // $paygates = json_decode(file_get_contents(storage_path('app/paygates.json')));
    // $gateways = [];
    // foreach ($paygates as $key => $value) {
    //   foreach ($value as $k => $v) {
    //     if (is_bool($v) && $v == true) array_push($gateways, $key);
    //   }
    // }
    // return view('/user-show', compact('adminSender', 'adminUsers', 'userUsers', 'user', 'packages', 'daysTotal', 'daysUsed', 'daysRemaining', 'percentUsed', 'status', 'currencyCode', 'modules', 'topupValues', 'intervals', 'walletBalance', 'gateways'));
  }

  public function store(Request $request)
  {
    if (filter_var(Helpers::setting('requireStrongPassword'), FILTER_VALIDATE_BOOLEAN)) {
      $request->validate([
        'name' => ['required', 'string', 'min:6', 'max:255', Rule::unique('users','name')],
        'email' => ['required', 'string', 'lowercase', 'email', 'max:255', Rule::unique('users','email')],
        'phone' => ['required', 'string', 'min:10', 'max:50', Rule::unique('users','phone')],
        'password' => ['required', 'confirmed', Rules\Password::defaults()->mixedCase()->numbers()->symbols()],
      ]);
    } else {
      $request->validate([
        'name' => ['required', 'string', 'min:6', 'max:255', Rule::unique('users','name')],
        'email' => ['required', 'string', 'lowercase', 'email', 'max:255', Rule::unique('users','email')],
        'phone' => ['required', 'string', 'min:10', 'max:50', Rule::unique('users','phone')],
        'password' => ['required', 'confirmed', Rules\Password::defaults()],
      ]);
    }

    $email = $request->input('email') ?? null;
    $username = str_replace(' ', '_', strtolower($request->input('name') ?? $email));
    $password = $request->input('password') ?? null;
    $phone = $request->input('phone') ?? null;
    $role = $request->input('role') ?? 'user';
    $package_id = $request->input('package_id') ?? 2;
    $billing_interval = $request->input('billing_interval') ?? 'monthly';
    if (empty($email) || empty($password) || empty($phone)) {
      echo __('Email') . ', ' . __('Password') . ', ' . __('Phone') . ': ' . __('Required');
      return redirect()
        ->back()
        ->with(['danger_alert' => __('Email') . ', ' . __('Password') . ', ' . __('Phone') . ': ' . __('Required')]);
    }
    if (User::where('name', 'like', "%-$username")->count() > 0) {
      echo __('Duplicate found. Failed to add') . ': ' . $email;
      return redirect()
        ->back()
        ->with(['danger_alert' => __('Duplicate found. Failed to add') . ': ' . $username]);
    }
    if (User::where('email', 'like', "%-$email")->count() > 0) {
      echo __('Duplicate found. Failed to add') . ': ' . $email;
      return redirect()
        ->back()
        ->with(['danger_alert' => __('Duplicate found. Failed to add') . ': ' . $email]);
    }
    $user = new User();
    $user->name = $username;
    $user->password = Hash::make($password);
    $user->email = $email;
    $user->phone = Formatter::pf($phone);
    $user->role = $role;
    $user->lang = config('app.locale');
    $user->theme = config('app.theme');
    $user->package_id = $package_id;
    $user->billing_interval = $billing_interval;
    $user->billing_start = Carbon::now()->startOfMonth();
    $user->billing_end = Carbon::now()->endOfMonth();
    $user->save();

    $num = rand(1, 28);
    $path = public_path('users/' . $user->id);
    $source = public_path('app-assets/images/avatars/' . $num . '.png');
    $target = $path . '/avatar.png';
    if (!File::exists($path)) {
      File::makeDirectory($path, 0755, true);
    }
    File::copy($source, $target);
    return redirect()
      ->back()
      ->with(['success_alert' => __('Successfully add') . ': ' . $user->name]);
  }

  public function update(Request $request)
  {
    if (filter_var(Helpers::setting('requireStrongPassword'), FILTER_VALIDATE_BOOLEAN) && !empty($request->input('password'))) {
      $request->validate([
        'password' => ['required', Rules\Password::defaults()->mixedCase()->numbers()->symbols()],
      ]);
    } else if (!empty($request->input('password'))) {
      $request->validate([
        'password' => ['required', Rules\Password::defaults()],
      ]);
    }
    if (!empty(config('app.DEMO')) && $request->input('user_id') <= 2) {
      return redirect()
        ->back()
        ->with(['danger_alert' => __('You are not allowed to update User')]);
    }
    if (auth()->user()->id != $request->input('user_id') && auth()->user()->role !== 'admin') {
      return redirect()
        ->back()
        ->with(['danger_alert' => __('You are not allowed to update User')]);
    }
    $username = str_replace(' ', '_', strtolower($request->input('name')));
    $userphone = Formatter::pf($request->input('phone'));
    $user = User::where('id', '=', $request->input('user_id'))->first();
    // Validate OTP if WA verification is enabled and adminSender is provided
    if (filter_var(Helpers::setting('waVerification'), FILTER_VALIDATE_BOOLEAN) && auth()->user()->role !== 'admin' && !empty($request->input('adminSender'))) {
      if ($user->otp !== $request->input('otp')) {
        $user->otp = Str::random(20);
        $user->save();
        return redirect()
          ->back()
          ->with(['danger_alert' => __('OTP code is invalid.')]);
      }
    }
    $checkDups = User::where('name', '=', $username)->get();
    foreach ($checkDups as $checkDup) {
      if ($user->id !== $checkDup->id) {
        return redirect()
          ->back()
          ->with(['danger_alert' => __('Duplicate found. Failed to edit') . ': ' . $request->input('name')]);
      }
    }
    $checkDups = User::where('phone', '=', $userphone)->get();
    foreach ($checkDups as $checkDup) {
      if ($user->id !== $checkDup->id) {
        return redirect()
          ->back()
          ->with(['danger_alert' => __('Duplicate found. Failed to edit') . ': ' . $request->input('phone')]);
      }
    }
    if (!empty($request->input('password'))) {
      if (strlen($request->input('password')) > 5) {
        $user->password = Hash::make($request->input('password'));
      } else {
        return redirect()
          ->back()
          ->with(['danger_alert' => __('Password minimum 6 characters')]);
      }
    }
    $user->name = $username;
    $user->email = $request->input('email');
    $user->phone = $userphone;
    $user->rtl = $request->input('rtl');
    $user->theme = $request->input('theme');
    if (auth()->user()->role === 'admin') {
      if (!empty($request->input('package_id'))) {
        $user->package_id = $request->input('package_id');
      }
      if (!empty($request->input('role'))) {
        $user->role = $request->input('role');
      }
      if (null !== $request->input('banned')) {
        $user->banned = $request->input('banned');
      }
      if (null !== $request->input('billing_end')) {
        $user->billing_end = $request->input('billing_end');
      }
      if (null !== $request->input('verified_at')) {
        $user->email_verified_at = $request->input('verified_at');
      }
    }
    $user->otp = Str::random(20);
    $user->save();
    return redirect()->back()->with(['success_alert' => __('Successfully update User') . ': ' . $user->name]);
  }

  public function updateAvatar(Request $request)
  {
    $user = User::find($request->input('user_id'));
    if (auth()->user()->id != $user->id && auth()->user()->role !== 'admin') return redirect()->back()->with(['danger_alert' => __('You are not allowed to update User')]);
    if (!empty($request->avatarPicture)) {
      $ext = $request->avatarPicture->getClientOriginalExtension();
      if ($ext !== 'jpg' && $ext !== 'jpeg' && $ext !== 'png') return redirect()->back()->with(['danger_alert' => __('Only JPG/JPEG/PNG allowed')]);
      $path = public_path('users/' . $user->id);
      if (!File::exists($path)) {
        File::makeDirectory($path, 0755, true);
      }
      $media_upload = $request->avatarPicture->move($path, 'avatar.png');
      return redirect()->back()->with(['success_alert' => __('Successfully update Avatar') . ': ' . $user->name]);
    } else return redirect()->back();
  }

  public function otpSend(Request $request)
  {
    $otp = rand(1111, 9999);
    $authUser = auth()->user();

    // Determine destination phone: for device add OTP, send to current user's phone
    $msgKey = $request->msgOtp;
    if ($msgKey === '_MsgOtpAdd') {
      $phone = Formatter::pf($authUser->phone);
    } else {
      $phone = Formatter::pf($request->phone);
    }

    // Build message using the authenticated user's name
    $msgtext = str_ireplace(
      ['{otp}', '{name}', '{appurl}', '{appname}'],
      [$otp, ($authUser->name ?? $request->name), rtrim(config('app.url'), '/'), config('app.name')],
      __($msgKey)
    );

    // Persist OTP on the authenticated user to match validation during device add
    if ($authUser) {
      $authUser->otp = $otp;
      $authUser->save();
    } else if (!empty($request->name)) {
      // Fallback to update by name if auth not available
      User::where('name', '=', $request->name)->update(['otp' => $otp]);
    }

    // Attempt to send the OTP message (do not gate saving OTP on delivery success)
    $response = SendmsgController::sendMessage($phone, $msgtext, $request->adminSender);
    $res = is_string($response) ? json_decode($response) : $response;
    // Optionally return a simple JSON for frontend if needed
    return response()->json([
      'sent' => (!empty($res->success) && $res->success == true),
      'to' => $phone,
    ]);
  }

  public function otpRegister(Request $request)
  {
    $phone = Formatter::pf($request->phone);
    $otp = rand(1111, 9999);
    $msgtext = str_ireplace(['{otp}', '{name}', '{appurl}', '{appname}'], [$otp, $request->name, rtrim(config('app.url'), '/'), config('app.name')], __('_MsgOtpRegister'));
    $response = SendmsgController::sendMessage($phone, $msgtext, $request->adminSender);
  $res = is_string($response) ? json_decode($response) : $response;
    if (!empty($res->success) && $res->success == true) {
      User::where('name', '=', $request->name)->update(['phone' => $phone, 'otp' => $otp]);
    }
  }

  public function banUnban(Request $request)
  {
    $user = User::where('id', '=', $request->user_id)->first();
    $user->banned = $user->banned ? 0 : 1;
    $user->save();
    return redirect()->back();
  }

  public function verify()
  {
    $adminSender = Device::where('user_id', 1)->where('status', '=', 'ONLINE')->value('sender');
    $user = auth()->user();
    if (empty($user->email_verified_at)) {
      return view('/user-verify', compact('adminSender', 'user'));
    } else {
      return redirect()->route('dashboard');
    }
  }

  public function verifyOtp(Request $request)
  {
    if (empty($request->input('email_verified_at'))) {
      $user = User::where('id', '=', $request->input('user_id'))->first();
      if (filter_var(Helpers::setting('waVerification'), FILTER_VALIDATE_BOOLEAN) && $user->role !== 'admin' && $user->otp !== $request->input('otp')) {
        $user->otp = Str::random(20);
        $user->save();
        return redirect()
          ->back()
          ->with(['danger_alert' => __('OTP code is invalid.')]);
      }
      $user->otp = Str::random(20);
      $user->email_verified_at = date('Y-m-d H:i:s');
      $user->save();

      Device::updateOrInsert(
        ['sender' => $user->phone], // Matching condition
        [
          'user_id' => $user->id,
          'name' => $user->name,
          'token' => Str::random(20),
          'subscribe_keyword' => 'Subscribe',
          'unsubscribe_keyword' => 'Unsubscribe',
          'subscribe_message' => 'Thank you *{name}* for subscribing to our channel. We will make sure you will receive our best offer.',
          'unsubscribe_message' => 'Hi *{name}*, we are very sad to see you go. Please type _*Subscribe*_ if you want to join back. Thank you!',
          'welcome_cust' => '[]',
          'openai' => json_encode([
            'apikey' => '',
            'contain' => $user->name . ',',
            'model' => 'gpt-3.5-turbo',
            'image_contain' => __('Generate image'),
            'image_model' => 'dall-e-3',
            'max_tokens' => 2048,
            'save_chats' => 0,
            'persona' => "Your name is $user->name. You are a smart, polite, and gentle assistant",
          ]),
          'webhook' => url('/api/webhook'),
          'ext_webhook' => json_encode([
            'url' => '',
            'data' => [],
          ]),
        ]
      );
      return redirect()->route('dashboard')->with(['success_alert' => __('Successfully verify') . ': ' . $user->name]);
    }
    return redirect()->route('dashboard');
  }

  public function reset(Request $request)
  {
    $user = User::where('id', '=', $request->input('user_id'))->first();
    if ($request->input('code') === mb_substr($user->password, -10)) {
      $user->password = Hash::make($request->input('password'));
      $user->save();
      return redirect()
        ->route('dashboard')
        ->with(['success_alert' => __('Successfully reset') . ': ' . $user->name]);
    }
  }

  public function resetNow($id, $code)
  {
    $user = User::where('id', '=', $id)->first();
    if (base64_decode($code) === mb_substr($user->password, -10)) {
      return view('/user-reset', compact('user'));
    }
    return redirect()
      ->route('dashboard')
      ->with(['success_alert' => __('Successfully reset') . ': ' . $user->name]);
  }

  public function banned()
  {
    return view('/user-banned');
  }

  public function deleted()
  {
    return view('/user-deleted');
  }

  public function expired()
  {
    return view('/user-expired');
  }

  public function impersonate(User $user)
  {
    auth()
      ->user()
      ->impersonate($user);
    return redirect()->route('dashboard');
  }

  public function leaveImpersonate()
  {
    auth()
      ->user()
      ->leaveImpersonation();
    return redirect()->route('user.list');
  }

  public function locale(Request $request)
  {
    $locale = $request->input('locale');
    if (!$locale) {
        return redirect()->back()->with(['danger_alert' => __('Locale is required')]);
    }
    session()->put('locale', $locale);
    $user = auth()->user();
    $user->update(['lang' => $locale]);
    return redirect()
      ->back()
      ->with(['success_alert' => __('Successfully change language to') . ': ' . $locale]);
  }

  public function exportTransaction()
  {
    return Excel::download(new TransactionExport(), 'transactions.xlsx');
  }

  private function delAuth($device)
  {
    $url = rtrim(config('app.node_url'), '/') . '/delauth';
    $data = ['token' => $device->token, 'logout' => true];
    $response = Helpers::curlPost($url, $data);
    $awg_orderId = Helpers::setting('awg_orderId');
    if (file_exists(public_path("users/{$device->user_id}/assets/wh_{$device->sender}_{$awg_orderId}.php"))) {
      unlink(public_path("users/{$device->user_id}/assets/wh_{$device->sender}_{$awg_orderId}.php"));
    }
  }

  public function destroySoft(Request $request)
  {
    $user = User::where('id', '=', $request->user_id)->first();
    if (auth()->user()->id !== $user->id && auth()->user()->role !== 'admin') {
      return redirect()
        ->back()
        ->with(['danger_alert' => __('You are not allowed to delete User')]);
    }
    if ($user->id <= 2) {
      return redirect()
        ->back()
        ->with(['danger_alert' => __('You are not allowed to delete super_admin and bank account')]);
    }
    $devices = $user->devices()->get();
    foreach ($devices as $device) {
      $device->contact_groups()->delete();
      $this->delAuth($device);
    }
    $user->autoreplies()->delete();
    $user->captures()->delete();
    $user->capture_items()->delete();
    $user->devices()->delete();
    $user->outboxes()->delete();
    $user->phonebooks()->delete();
    $user->subscribers()->delete();
    $prefix = Str::random(3);
    $user->name = $prefix . '-' . $user->name;
    $user->email = $prefix . '-' . $user->email;
    $user->phone = $prefix . '-' . $user->phone;
    $user->save();
    if (file_exists(public_path("users/$request->user_id"))) {
      File::deleteDirectory(public_path("users/$request->user_id"));
    }
    if (auth()->user()->role === 'admin') {
      return redirect()
        ->back()
        ->with(['success_alert' => __('Successfully delete User')]);
    } else {
      auth()
        ->guard('web')
        ->logout();
      $request->session()->invalidate();
      $request->session()->regenerateToken();
      return redirect('/');
    }
  }

  public function destroy(Request $request)
  {
    $user = User::where('id', '=', $request->user_id)->first();
    if ($user->id <= 2) {
      return redirect()
        ->back()
        ->with(['danger_alert' => __('You are not allowed to delete super_admin and bank account')]);
    }
    $devices = $user->devices()->get();
    foreach ($devices as $device) {
      $device->contact_groups()->delete();
      $this->delAuth($device);
    }
    $user->autoreplies()->delete();
    $user->captures()->delete();
    $user->capture_items()->delete();
    $user->devices()->delete();
    $user->outboxes()->delete();
    $user->phonebooks()->delete();
    $user->subscribers()->delete();
    $user->delete();
    if (file_exists(public_path("users/$request->user_id"))) {
      File::deleteDirectory(public_path("users/$request->user_id"));
    }
    return redirect()
      ->back()
      ->with(['success_alert' => __('Successfully delete User')]);
  }
}
