<?php

namespace App\Http\Controllers\API\v1;

use App\Http\Controllers\Controller;
use App\Jobs\ImportTimelogsJob;
use App\Models\Company;
use App\Models\Dealership;
use App\Models\Department;
use App\Models\Division;
use App\Models\Employee;
use App\Models\Group;
use App\Models\Import;
use App\Models\JobClassification;
use App\Models\JobTitle;
use App\Models\PayrollOldRecords;
use App\Models\Section;
use App\Models\Timelog;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;
use Throwable;

class ImportController extends Controller
{
    public function import_timelogs(Request $request)
    {
        $timelogs = $request->input('data');
        $formData = $request->input('formData');

        $attachmentName = "";

        try {
            if (isset($formData['attachment']['preview'])) {
                $fileData = $formData['attachment']['preview'];

                if (preg_match('/^data:\w+\/\w+;base64,/', $fileData)) {
                    $fileData = base64_decode(substr($fileData, strpos($fileData, ',') + 1));
                } else {
                    $fileData = $fileData;
                }

                // Generate a unique name and store the file
                $attachmentName = time() . '_imported_file.dat';
                $path = "import-timelogs/" . $attachmentName;

                // Save file content
                Storage::disk('local')->put($path, $fileData);
            }

            // Save main record in the database
            $status = Import::create([
                'name' => $formData['name'],
                'attachment' => $attachmentName,
                'uploaded_by' => $formData['uploaded_by'],
            ]);

            DB::commit();

            ImportTimelogsJob::dispatch($timelogs); // Dispatch job with timelogs

            return response()->json([
                'message' => 'Records are being processed.',
                'status' => 'success',
            ], 201);

        } catch (Throwable $e) {
            DB::rollBack();
            return response()->json([
                'status' => false,
                'message' => 'Unable to process request. Please try again.',
                'data' => $e->getMessage()
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function import_employees(Request $request)
    {
        $employees = $request->input('data');
        $formData = $request->input('formData');

        // dd($employees);
        $attachmentName = "";

        try {
            if (isset($formData['attachment']['preview'])) {
                $fileData = $formData['attachment']['preview'];
        
                if (preg_match('/^data:\w+\/\w+;base64,/', $fileData)) {
                    $fileData = base64_decode(substr($fileData, strpos($fileData, ',') + 1));
                }
        
                // Generate a unique name and store the file
                $attachmentName = time() . '_imported_file.xlsx';
                $path = "import-employees/" . $attachmentName;
        
                // Save file content
                Storage::disk('local')->put($path, $fileData);
            }
        
            DB::beginTransaction(); // Begin transaction
        
            // Save main record in the database
            $import = Import::create([
                'name' => $formData['name'],
                'attachment' => $attachmentName,
                'uploaded_by' => $formData['uploaded_by'],
            ]);
        
            foreach ($employees as $log) {
                if(Employee::where('employee_id', $log['employee_id'])->exists()){
                    return response()->json([
                        'status' => false,
                        'message' => 'Unable to process request. Please try again.',
                        'data' => 'Employee ID: '. $log['employee_id'] .' Already Exists. Re-check the Employee ID or Add Company Code Before the Employee ID.'
                    ], Response::HTTP_IM_USED);
                }
            }

            foreach ($employees as $log) {
                $fullname_explode = explode(',', $log['fullname']);
                $lastname = $fullname_explode[0] ?? null;
                $firstname = $fullname_explode[1] ?? null;

                $company_id = Company::where('name', $log['company'])->orWhere('code', $log['company'])->pluck('id')->first();
                $dealer_id = Dealership::where('name', $log['dealer'])->orWhere('code', $log['dealer'])->pluck('id')->first();

                if(empty($dealer_id))
                {
                    
                    $dealer = Dealership::create([
                        'company_id' => $company_id ?? '',
                        'code' => $log['dealer'],
                        'name' => $log['dealer'],
                    ]);
                    // dd($dealer);
                    $dealer_id = $dealer->id;
                }

                // dd('sadsadasdadd');

                $group_id = Group::where('name', $log['group'] ?? '0')->orWhere('code', $log['group'] ?? '0')->pluck('id')->first();
                $division_id = Division::where('name', $log['division'] ?? '0')->orWhere('code', $log['division'] ?? '0')->pluck('id')->first();
                $department_id = Department::where('name', $log['department'] ?? '0')->orWhere('code', $log['department'] ?? '0')->pluck('id')->first();
                $section_id = Section::where('name', $log['section'] ?? '0')->orWhere('code', $log['section'] ?? '0')->pluck('id')->first();
                $classification_id = JobClassification::where('name', $log['classification'] ?? '0')->orWhere('code', $log['classification'] ?? '0')->pluck('id')->first();
                $position_id = JobTitle::where('name', $log['position'] ?? '0')->pluck('id')->first();
                
                Employee::create([
                    "employee_id" => $log['employee_id'],
                    "firstname" => $firstname,
                    "lastname" => $lastname,
                    "company_id" => $company_id,
                    "dealer_id" => $dealer_id,
                    "group_id" => $group_id ?? '0',
                    "division_id" => $division_id ?? '0',
                    "department_id" => $department_id ?? '0',
                    "section_id" => $section_id ?? '0',
                    "classification_id" => $classification_id ?? '0',
                    "position_id" => $position_id ?? '0',
                    "time_keeping_id" => $log['time_keeping'] ?? 'N/A',
                    "email" => $log['email'] ?? 'N/A',
                    "mobile" => $log['mobile'] ?? 'N/A'
                ]);

                $firstnameForUser = str_replace(' ', '', $firstname);
                $getFirstLetter = str_split($firstnameForUser)[0];
                $username = strtolower($getFirstLetter.str_replace(' ', '', ($lastname)));

                $baseUsername = $username; // Store the original username
                $count = 1;

                // Check if the original username exists
                if (User::where('username', $username)->exists()) {
                    do {
                        $newUsername = $baseUsername . $count;
                        $count++;
                    } while (User::where('username', $newUsername)->exists());

                    $username = $newUsername; // Assign the unique username
                }

                $user = User::create([
                    'employee_id' => $log['employee_id'],
                    'first_name'  =>  $firstname,
                    'last_name'   => $lastname,
                    'name'        => $firstname . ' ' . $lastname,
                    'username'    => strtolower($username),
                    'email'       => $log['email'] ?? 'N/A',
                    'password'    => Hash::make('password'),
                ]);
            }
            
            DB::commit(); // Commit transaction
        
            return response()->json([
                'message' => 'Records have been successfully processed.',
                'status' => 'success',
            ], 201);
        
        } catch (Throwable $e) {
            DB::rollBack();
            return response()->json([
                'status' => false,
                'message' => 'Unable to process request. Please try again.',
                'data' => $e->getMessage()
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function import_old_payroll(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'data.company_id' => 'required|integer',
            'data.dealer_id' => 'required|integer',
            'data.start_date' => 'required|date',
            'data.end_date' => 'required|date',
            'data.employees' => 'required|array|min:1',
            'data.employees.*.emp_no' => 'required|string|max:50',
            'data.employees.*.name' => 'required|string|max:255',
            'formData.name' => 'required|string|max:255',
            'formData.uploaded_by' => 'nullable|string|max:255',
        ]);


        if ($validator->fails()) {
            return response()->json([
                'status' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        DB::beginTransaction();

        try {
            $data = $request->input('data');

            // These are outside employees array, so store separately
            $companyId = $data['company_id'] ?? null;
            $dealerId = $data['dealer_id'] ?? null;
            $startDate = $data['start_date'] ?? null;
            $endDate = $data['end_date'] ?? null;

            // This is the actual employee list
            $employees = $data['employees'] ?? [];

            $formData = $request->input('formData');
            $attachmentName = "";

            // Handle file attachment if present
            if (isset($formData['attachment']['preview'])) {
                $fileData = $formData['attachment']['preview'];
                
                if (preg_match('/^data:\w+\/\w+;base64,/', $fileData)) {
                    $fileData = base64_decode(substr($fileData, strpos($fileData, ',') + 1));
                }
                
                // Generate unique filename
                $attachmentName = time() . '_payroll_import.' . ($request->input('file_extension', 'csv'));
                $path = "import-payroll/" . $attachmentName;
                
                // Save file to storage
                Storage::disk('local')->put($path, $fileData);
            }

            // Process payroll data - ensure numeric fields are properly formatted
            $processedData = array_map(function ($record) use ($companyId, $dealerId, $startDate, $endDate) {
                return [
                    'company_id' => $companyId,
                    'dealer_id' => $dealerId,
                    'start_date' => $startDate,
                    'end_date' => $endDate,
                    'employee_id' => $record['emp_no'],
                    'name' => $record['name'],
                    'basic_pay' => (float) ($record['basic_pay'] ?? 0),
                    'cola' => (float) ($record['cola'] ?? 0),
                    'ot' => (float) ($record['ot'] ?? 0),
                    'cdo' => (float) ($record['cdo'] ?? 0),
                    'hol' => (float) ($record['hol'] ?? 0),
                    'n_diff' => (float) ($record['n_diff'] ?? 0),
                    'tardines' => (float) ($record['tardines'] ?? 0),
                    'absent' => (float) ($record['absent'] ?? 0),
                    'pay_adj' => (float) ($record['pay_adj'] ?? 0),
                    'benefit' => (float) ($record['benefit'] ?? 0),
                    'deduc' => (float) ($record['deduc'] ?? 0),
                    'loan' => (float) ($record['loan'] ?? 0),
                    'sss' => (float) ($record['sss'] ?? 0),
                    'p_ibig' => (float) ($record['p_ibig'] ?? 0),
                    'p_health' => (float) ($record['p_health'] ?? 0),
                    'w_tax' => (float) ($record['w_tax'] ?? 0),
                    'net_pay' => (float) ($record['net_pay'] ?? 0),
                    'tax' => (float) ($record['tax'] ?? 0),
                    'sss_p' => (float) ($record['sss_p'] ?? 0),
                    'p_ibig_p' => (float) ($record['p_ibig_p'] ?? 0),
                    'p_health_p' => (float) ($record['p_health_p'] ?? 0),
                    'final_net' => (float) ($record['final_net'] ?? 0),
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }, $employees);

            // Create import record
            $importRecord = Import::create([
                'name' => $formData['name'],
                'attachment' => $attachmentName,
                'uploaded_by' => $formData['uploaded_by'] ?? Auth::user()->employee_id ?? 'System',
                'import_type' => 'payroll',
                'status' => 'processing',
                'total_records' => count($processedData),
                'processed_records' => 0,
                'failed_records' => 0,
            ]);

            // Process payroll data directly - insert records into database
            $successCount = 0;
            $failedCount = 0;
            $errors = [];

            foreach ($processedData as $index => $record) {
                try {
                    // Insert into payroll_records table (adjust table name as needed)
                    PayrollOldRecords::create($record);
                    $successCount++;
                } catch (\Exception $e) {
                    $failedCount++;
                    $errors[] = [
                        'row' => $index + 1,
                        'emp_no' => $record['emp_no'],
                        'name' => $record['name'],
                        'error' => $e->getMessage()
                    ];
                }
            }

            // Update import record with final counts
            $importRecord->update([
                'status' => $failedCount > 0 ? 'completed_with_errors' : 'completed',
                'processed_records' => $successCount,
                'failed_records' => $failedCount,
                'error_details' => $failedCount > 0 ? json_encode($errors) : null,
            ]);

            DB::commit();

            return response()->json([
                'message' => $failedCount > 0 
                    ? "Payroll import completed with {$successCount} successful and {$failedCount} failed records."
                    : "Payroll import completed successfully. {$successCount} records processed.",
                'status' => 'success',
                'import_id' => $importRecord->id,
                'total_records' => count($processedData),
                'success_count' => $successCount,
                'failed_count' => $failedCount,
                'errors' => $failedCount > 0 ? $errors : null
            ], 201);

        } catch (Throwable $e) {
            DB::rollBack();
            
            Log::error('Payroll import failed: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString(),
                'user_id' => Auth::user()->id,
                'request_data' => $request->except(['formData.attachment'])
            ]);

            return response()->json([
                'status' => false,
                'message' => 'Unable to process payroll import. Please try again.',
                'data' => $e->getMessage()
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

}
