<?php


namespace App\Http\Controllers;

use App\Models\Fund;
use App\Models\Role;
use App\Models\User;
use App\Models\EmpType;
use App\Models\EmpAccess;
use App\Models\EmpPermit;
use App\Models\FundsMeta;
use App\General\MetaClass;
use App\Models\EmpDocuments;
use Illuminate\Http\Request;
use App\Models\EmpTeamsMember;
use App\Models\EmpListChangeCol;
use App\Models\RequiredDocument;
use App\Models\EmpCompanyDetails;
use App\Models\EmpPersonalDetails;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Validator;

class EmployeeController extends Controller
{
  // Employee type constants for better maintainability
  const EMPLOYEE_TYPE_INTERNAL = 0;
  const EMPLOYEE_TYPE_EXTERNAL = 1;

  public function index(Request $request)
  {
    $user = Auth::user();
    if (!$user) {
      return $this->error('Unauthorized', 401);
    }
    $query = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class);
    $query = $this->applyCustomerWorkspaceFilter($query);
    if ($request->filled('invited')) {
      $query->where('invited', $request->invited);
    }
    // Apply employee type filtering
    $this->applyEmployeeTypeFilter($query, $request);
    if ($request->filled('tierKyes')) {
      $query = $this->getTierEmployees($request->tierKyes, $query);
    }
    // Apply filters from request parameters
    $requestFilters = $request->only(['first_name', 'middle_name', 'last_name', 'employee_email', 'mobile', 'tax_file_no', 'access_role', 'status', 'completed', 'user_type', 'link_key', 'teams', 'streat_address', 'bank_name', 'account_number']);
    // Also support JSON-based filters for backward compatibility
    if ($request->filled('filter')) {
      $jsonFilters = json_decode($request->filter, true);
      $requestFilters = array_merge($requestFilters, $jsonFilters);
    }
    if ($request->filled('link_key')) {
      $query->where('user_type', 1);
    }
    // Apply all filters in one call
    $query = $this->filter($requestFilters, $query);
    $query->with([
      'empPersonalDetails',
      'empDocuments',
      'empEmergencyContacts',
      'empAccess',
      'accessRole',
      'empTeamsMembers',
      'empMetaData',
      'funds_meta'
    ]);
    $query->orderBy('id', 'desc');
    $users = $query;
    $array_filter = $request->filled('filter') ? json_decode($request->filter, true) : [];
    $filters = [
      'first_name'     => $array_filter['first_name'] ?? '',
      'middle_name'    => $array_filter['middle_name'] ?? '',
      'last_name'      => $array_filter['last_name'] ?? '',
      'employee_email' => $array_filter['employee_email'] ?? '',
      'completed'      => $array_filter['completed'] ?? '',
      'status'         => $array_filter['status'] ?? '',
      'access_role'    => $array_filter['access_role'] ?? '',
    ];
    $users_collection = $users->get();
    if ($request->filled('chat')) {
      $customer = $this->getCustomerForChat($users_collection);
      $response = [
        'message' => "success",
        'statusCode' => 200,
        'data' => $users_collection,
        'customer' => $customer,
      ];
      return response()->json($response, 200);
    }
    return $this->WithFilter($users_collection, $filters, 'Get Employees list Successfully');
  }

  public function getCustomerForChat($users_collection)
  {
    $ids = $this->getCustomerAndWorkspaceIds();
    // Get the customer user details
    $customer = User::find($ids['customer_id']);
    if ($customer) {
      $customer->type = 'customer'; // just add the extra property
    }
    return $customer;
  }

  public function filter($filters, $query)
  {

    foreach ($filters as $filterName => $filterValue) {
      if ($filterValue != null ||  $filterValue != "") {
        switch ($filterName) {
          case 'first_name':
            $query->whereHas('empPersonalDetails', function ($subquery) use ($filterValue) {
              $subquery->where('first_name', 'like', '%' . $filterValue . '%');
            });
            break;
          case 'middle_name':
            $query->whereHas('empPersonalDetails', function ($subquery) use ($filterValue) {
              $subquery->where('middle_name', 'like', '%' . $filterValue . '%');
            });
            break;
          case 'last_name':
            $query->whereHas('empPersonalDetails', function ($subquery) use ($filterValue) {
              $subquery->where('last_name', 'like', '%' . $filterValue . '%');
            });
            break;
          case 'employee_email':
            $query->where('employee_email', 'like', '%' . $filterValue . '%');
            break;
          case 'streat_address':
            $query->whereHas('empPersonalDetails', function ($subquery) use ($filterValue) {
              $subquery->where('streat_address', 'like', '%' . $filterValue . '%');
            });
            break;
          case 'mobile':
            $query->whereHas('empPersonalDetails', function ($subquery) use ($filterValue) {
              $subquery->where('mobile', 'like', '%' . $filterValue . '%');
            });
            break;
          case 'tax_file_no':
            $query->where('tax_file_no', 'like', '%' . $filterValue . '%');
            break;
          case 'bank_name':
            $query->whereHas('empMetaData', function ($subquery) use ($filterValue) {
              $subquery->where('option', 'bank_name')
                ->where('value', 'like', '%' . $filterValue . '%');
            });
            break;
          case 'account_number':
            $query->whereHas('empMetaData', function ($subquery) use ($filterValue) {
              $subquery->where('option', 'account_number')
                ->where('value', 'like', '%' . $filterValue . '%');
            });
            break;

          case 'teams':
            $emp_teams_members = EmpTeamsMember::where('team_id', $filterValue)->pluck('emp_id')->toArray();
            $query->whereIn('id', $emp_teams_members);
            break;
          case 'access_role':
            $query->where('access_role', 'like', '%' . $filterValue . '%');
            break;
          case 'completed':
            $filterValue =   $filterValue ? 1 : 0;
            $query->where('compeleted', 'like', '%' . $filterValue . '%');
            break;
          case 'status':
            $filterValue =   $filterValue ? 1 : 0;
            $query->where('status', 'like', '%' . $filterValue . '%');
            break;
          case 'user_type':
            $filterValue =   $filterValue ? 1 : 0;
            $query->where('user_type', 'like', '%' . $filterValue . '%');
            break;
          case 'link_key':
            $query->where('link_key', 'like', '%' . $filterValue . '%');
            break;
        }
      }
    }

    return $query;
  }

  public function empDownload(Request $request)
  {
    $query = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)->with(['empPersonalDetails', 'empDocuments', 'empEmergencyContacts', 'empAccess', 'accessRole', 'empTeamsMembers']);

    if ($request->filled('invited')) {
      $query->where('invited', $request->invited);
    }

    if ($request->filled('filter')) {
      $query = $this->filter(json_decode($request->filter, true), $query);
    }
    $userTable = $this->getUserTable();
    $auth_id = 0;
    $workspace_id = 0;
    if ($userTable === "customer") {
      $auth_id = Auth::user()->id;
      $workspace_id = Auth::user()->current_workspace_id;
      $authPersonalDetails = User::where('id', Auth::user()->id)->first();
    }
    if ($userTable === "emp") {
      $auth_id = auth()->user()->customer_id;
      $workspace_id = auth()->user()->workspace_id;
      $authPersonalDetails = EmpPersonalDetails::where('emp_id', Auth::user()->id)->first();
    }
    $query->where('customer_id', $auth_id);
    $query->where('workspace_id', $workspace_id);
    $query->where('del', '0');
    $query->orderBy('id', 'desc');
    $emps = $query->get();

    $cols = DB::table('emp_list_change_cols')->pluck('col')->toArray();

    $columns = [
      'First Name',
      'Middle Name',
      'Last Name',
      'Employee Email',
      'Teams',
      'Role',
      'Mobile',
      'Address',
      'Tax File No',
      'Account Number',
      'BSB',
      'Registration',
      'Status',
      'Type',
    ];

    $col_list[] = "Employee Id";
    $col_list[] = "External Id";
    $indexs = [];
    $i = 2;
    foreach ($columns as $column) {
      if (in_array($column, $cols)) {
        $col_list[] = $column;
      } else {
        $indexs[] = $i;
      }
      $i++;
    }

    $csvData[] = $col_list;

    $data_list  = [];

    foreach ($emps as $emp) {
      $team_list = "";
      foreach ($emp->empTeamsMembers as $et) {
        $team_list .= $et->empTeamsList->title . ",";
      }

      $team_list = rtrim($team_list, ',');

      $user_meta = DB::table('user_meta')
        ->where('emp_id', $emp->id)
        ->get();

      $data_list = [
        $emp->id,
        $this->searchInMeta($user_meta, 'employee_payroll_or_external_id'),
        $emp->empPersonalDetails ? $emp->empPersonalDetails->first_name : '',
        $emp->empPersonalDetails ? $emp->empPersonalDetails->middle_name : '',
        $emp->empPersonalDetails ? $emp->empPersonalDetails->last_name : '',
        $emp->employee_email,
        $team_list,
        $emp->accessRole ? $emp->accessRole->title : '',
        $emp->empPersonalDetails ? $emp->empPersonalDetails->mobile : '',
        $emp->empPersonalDetails ? $emp->empPersonalDetails->streat_address : '',
        $emp->tax_file_no,
        $this->searchInMeta($user_meta, 'account_number'),
        $this->searchInMeta($user_meta, 'bank_name'),
        $emp->registration == 0 ? 'InProcess' : 'Completed',
        $emp->status == 0 ? 'InActive' : 'Active',
        $emp->user_type == 0 ? 'Internal' : 'External'
      ];

      $csvData[] = array_values(array_diff_key($data_list, array_flip($indexs)));
    }
    $headers = [
      'Content-Type' => 'text/csv',
      'Content-Disposition' => 'attachment; filename="emp.csv"',
    ];


    $callback = function () use ($csvData) {
      $file = fopen('php://output', 'w');
      foreach ($csvData as $row) {
        fputcsv($file, $row);
      }
      fclose($file);
    };

    return Response::stream($callback, 200, $headers);
  }

  function searchInMeta($dataArray, $option)
  {
    $value = '';
    foreach ($dataArray as $element) {
      if ($element->option === $option) {
        $value = $element->value;
        break;
      }
    }
    return $value;
  }
  public function profile(Request $request)
  {
    // Check existence without global scope
    $exists = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)
      ->where('id', $request->id)
      ->exists();

    if (!$exists) {
      return $this->message('Employee not found');
    }

    $userTable = $this->getUserTable();

    // Get full employee record without global scope
    $employee = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)
      ->find($request->id);

    if (
      $userTable === "customer" &&
      ($employee->workspace_id != auth()->user()->current_workspace_id || $employee->customer_id != auth()->user()->id)
    ) {
      return $this->message('You do not have access to this Employee Profile', 403);
    }

    if (
      $userTable === "emp" &&
      ($employee->customer_id != auth()->user()->customer_id || $employee->workspace_id != auth()->user()->workspace_id)
    ) {
      return $this->message('You do not have access to this Employee Profile', 403);
    }

    // Build profile query without global scope
    $query = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)
      ->where('id', $request->id)
      ->with([
        'empPersonalDetails',
        'empEmergencyContacts',
        'empAccess',
        'empworkExperience',
        'workerType'
      ]);

    $query_result = $query->first();

    // Add related data
    $query_result['empType'] = EmpType::where('id', $query_result->employment_type)
      ->select('id', 'title')
      ->first();

    $query_result['empWorkPermit'] = EmpPermit::where('id', $query_result->work_permit_type)
      ->select('id', 'title')
      ->first();

    $query_result['empAccessRole'] = Role::where('code', $query_result->access_role)
      ->select('id', 'title', 'code')
      ->first();

    $data['profile'] = $query_result;

    // Funds
    $data['funds_meta'] = FundsMeta::with('fund')
      ->where('emp_id', $request->id)
      ->get();

    // Medical files
    $data['medicalAttachFiles'] = DB::table('medical_attach_files')
      ->where('emp_id', $request->id)
      ->get();

    // Employee documents
    $data['emp_documents'] = EmpDocuments::where('emp_id', $request->id)
      ->where('del', '0')
      ->get();
    if ($employee->user_type == 0) {
      $for_who = 'internal';
    } else {
      $for_who = 'external';
    }
    // Required documents
    $data['required_documents'] = RequiredDocument::with('requiredDocumentField')
      ->where('customer_id', $employee->customer_id)
      ->where('workspace_id', $employee->workspace_id)
      ->whereIn('for_who', [$for_who, 'both'])
      ->where('del', '0')
      ->get();

    // Meta
    $user_meta = DB::table('user_meta')
      ->where('emp_id', $request->id)
      ->get();

    $employee_payroll_or_external_id = MetaClass::getOptionValue('employee_payroll_or_external_id', $user_meta);
    $data['meta']['employee_payroll_or_external_id'] = $employee_payroll_or_external_id;

    // Get induction documents (signed and not signed) for this employee
    $data['induction_documents'] = $this->getEmployeeInductionDocuments($request->id);

    return $this->success($data, 'Get Profile Successfully');
  }


  public function show($id)
  {
    //
  }

  public function edit($id)
  {
    //
  }

  public function update(Request $request, $id)
  {
    //
  }

  public function store(Request $request)
  {
    //
  }

  public function employe_delete(Request $request)
  {
    $id = $request->id;
    $userTable = $this->getUserTable();
    $EmpCompanyDetails = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)->find($id);

    if ($userTable == "customer" && ($EmpCompanyDetails->workspace_id != auth()->user()->current_workspace_id || $EmpCompanyDetails->customer_id != auth()->user()->id)) {
      return $this->message('You do not have access to this Employee ', 403);
    }

    if ($userTable == "emp" && ($EmpCompanyDetails->customer_id != auth()->user()->customer_id || $EmpCompanyDetails->workspace_id != auth()->user()->workspace_id)) {
      return $this->message('You do not have access to this Employee ', 403);
    }
    $EmpCompanyDetails->del = '1';
    $EmpCompanyDetails->save();

    return $this->message('Employee  Deleted Successfully');
  }

  public function updateStatus(Request $request)
  {
    $id = $request->id;
    $userTable = $this->getUserTable();

    $emp = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)
      ->where('id', $id)
      ->first();

    if (!$emp) {
      return $this->message('Employee not found', 404);
    }

    if (
      ($userTable === "customer" &&
        ($emp->customer_id != auth()->user()->id || $emp->workspace_id != auth()->user()->current_workspace_id)) ||
      ($userTable === "emp" &&
        ($emp->customer_id != auth()->user()->customer_id || $emp->workspace_id != auth()->user()->workspace_id))
    ) {
      return $this->message('You do not have access to this Employee', 403);
    }

    // Fix 1: Initialize $status variable and handle edge cases
    $status = null;
    if ($emp->status == 1) {
      $status = 0;
    } elseif ($emp->status == 0) {
      $status = 1;
    } else {
      // Handle case where status is neither 0 nor 1
      $status = 1; // Default to active
    }

    // Fix 2: Use the same scope and add error handling
    try {
      $updated = EmpCompanyDetails::withoutGlobalScope(\App\Scopes\NotDeletedScope::class)
        ->where('id', $id)
        ->update(['status' => $status]);

      // Fix 3: Check if update was successful
      if ($updated === 0) {
        return $this->message('Failed to update employee status', 500);
      }

      return $this->success(['status' => $status], 'Employee status updated successfully');
    } catch (\Exception $e) {
      // Fix 4: Add error logging
      \Log::error('Failed to update employee status: ' . $e->getMessage());
      return $this->message('Failed to update employee status', 500);
    }
  }


  public function changeCol(Request $request)
  {
    $arr = [];
    $col = $request->col;
    if ($col) {
      DB::table('emp_list_change_cols')->delete();
      for ($i = 0; $i < count($col); $i++) {
        $arr[$i]['col'] = $col[$i];
      }
      EmpListChangeCol::insert($arr);
    }
    return back();
  }

  private function applyEmployeeTypeFilter($query, $request)
  {
    if ($request->has('employee_type')) {
      $employeeType = $request->employee_type;
      if (in_array($employeeType, [self::EMPLOYEE_TYPE_INTERNAL, self::EMPLOYEE_TYPE_EXTERNAL])) {
        $query->where('user_type', $employeeType);
      }
    } elseif ($request->filled('external')) {
      // Legacy support for external parameter
      $query->where('user_type', self::EMPLOYEE_TYPE_EXTERNAL);
    } elseif ($request->filled('internal')) {
      // Legacy support for internal parameter
      $query->where('user_type', self::EMPLOYEE_TYPE_INTERNAL);
    }
  }

  /**
   * Change employee password
   */
  public function changePassword(Request $request)
  {
    $validator = $this->adminResetPasswordValidationRequest($request);
    if ($validator->fails()) {
      return $this->handleValidationFailure($validator);
    }
    $employeeId = Auth::id();
    if (!$employeeId) {
      return $this->message('Employee not authenticated', 401);
    }
    $updated = EmpCompanyDetails::where('id', $employeeId)->update([
      'password' => Hash::make($request->input('password')),
    ]);
    if (!$updated) {
      return $this->message('Employee not found', 404);
    }
    return $this->message('Password changed successfully');
  }

  /**
   * Get employees for starting new chats
   */
  public function getEmployeesForChat(Request $request)
  {
    $user = $request->user();
    if (!$user) {
      return response()->json(['error' => 'Unauthorized'], 401);
    }

    $customerId = $user->customer_id ?? $user->id;
    $workspaceId = $user->workspace_id ?? $user->current_workspace_id;

    $employees = EmpCompanyDetails::where('customer_id', $customerId)
      ->where('workspace_id', $workspaceId)
      ->where('is_active', true)
      ->with(['empPersonalDetails', 'tierEmpPersonalDetail'])
      ->get()
      ->map(function ($emp) {
        $name = 'Unknown User';
        $image = null;

        // Get name from personal details
        if ($emp->empPersonalDetails) {
          $firstName = $emp->empPersonalDetails->first_name ?? '';
          $lastName = $emp->empPersonalDetails->last_name ?? '';
          $name = trim($firstName . ' ' . $lastName) ?: 'Unknown User';
        }

        // Get image from tier personal details
        if ($emp->tierEmpPersonalDetail) {
          $image = $emp->tierEmpPersonalDetail->image;
        }

        return [
          'id' => $emp->id,
          'name' => $name,
          'email' => $emp->employee_email,
          'image' => $image,
          'type' => 'emp'
        ];
      });

    return response()->json([
      'success' => true,
      'data' => $employees
    ]);
  }
}
