<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Employee;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class EmployeeRecordController extends Controller
{
    // ── LEAVES ────────────────────────────────────────────────────
    public function getLeaves(Request $request, $employeeId)
    {
        $user     = $request->user();
        $employee = Employee::findOrFail($employeeId);
        if (!$user->isSuperAdmin() && !$user->canAccessCompany($employee->company_id)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }
        $leaves = DB::table('employee_leaves')
            ->where('employee_id', $employeeId)
            ->orderByDesc('start_date')
            ->get();
        return response()->json(['data' => $leaves]);
    }

    public function addLeave(Request $request, $employeeId)
    {
        $user     = $request->user();
        $employee = Employee::findOrFail($employeeId);
        if (!$user->isSuperAdmin() && !$user->canAccessCompany($employee->company_id)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $validated = $request->validate([
            'type'       => 'required|in:annual,sick,maternity,paternity,unpaid,other',
            'start_date' => 'required|date',
            'end_date'   => 'required|date|after_or_equal:start_date',
            'reason'     => 'nullable|string|max:1000',
            'status'     => 'nullable|in:pending,approved,rejected',
            'notes'      => 'nullable|string|max:1000',
        ]);

        $start = \Carbon\Carbon::parse($validated['start_date']);
        $end   = \Carbon\Carbon::parse($validated['end_date']);
        $days  = $start->diffInWeekdays($end) + 1;

        $id = DB::table('employee_leaves')->insertGetId([
            'employee_id' => $employeeId,
            'type'        => $validated['type'],
            'start_date'  => $validated['start_date'],
            'end_date'    => $validated['end_date'],
            'days'        => $days,
            'reason'      => $validated['reason'] ?? null,
            'status'      => $validated['status'] ?? 'approved',
            'approved_by' => $user->id,
            'notes'       => $validated['notes'] ?? null,
            'created_at'  => now(),
            'updated_at'  => now(),
        ]);

        // If approved + type is sick/maternity etc, update employee status
        if (($validated['status'] ?? 'approved') === 'approved') {
            $employee->update(['status' => 'on-leave']);
        }

        try {
            activity()->causedBy($user)->performedOn($employee)
                ->withProperties(['type' => $validated['type'], 'days' => $days, 'ip_address' => $request->ip()])
                ->log('Employee leave recorded');
        } catch (\Exception $e) {}

        return response()->json(['data' => DB::table('employee_leaves')->find($id), 'message' => 'Leave recorded'], 201);
    }

    // ── SALARY HISTORY ────────────────────────────────────────────
    public function getSalaryHistory(Request $request, $employeeId)
    {
        $user     = $request->user();
        $employee = Employee::findOrFail($employeeId);
        if (!$user->isSuperAdmin() && !$user->canAccessCompany($employee->company_id)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }
        $history = DB::table('employee_salary_history')
            ->where('employee_id', $employeeId)
            ->orderByDesc('effective_date')
            ->get();
        return response()->json(['data' => $history, 'current_salary' => $employee->salary]);
    }

    public function addSalaryChange(Request $request, $employeeId)
    {
        $user     = $request->user();
        $employee = Employee::findOrFail($employeeId);
        if (!$user->isSuperAdmin() && !$user->canAccessCompany($employee->company_id)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $validated = $request->validate([
            'type'           => 'required|in:raise,reduction,fine,bonus,adjustment',
            'new_salary'     => 'nullable|numeric|min:0',
            'amount_change'  => 'nullable|numeric',
            'effective_date' => 'required|date',
            'reason'         => 'nullable|string|max:1000',
        ]);

        $oldSalary = (float) $employee->salary;

        // Determine new salary
        if (!empty($validated['new_salary'])) {
            $newSalary = (float) $validated['new_salary'];
        } elseif (!empty($validated['amount_change'])) {
            $delta     = (float) $validated['amount_change'];
            $newSalary = in_array($validated['type'], ['fine', 'reduction'])
                ? max(0, $oldSalary - abs($delta))
                : $oldSalary + $delta;
        } else {
            return response()->json(['message' => 'Provide new_salary or amount_change'], 422);
        }

        $amountChange = $newSalary - $oldSalary;

        DB::table('employee_salary_history')->insert([
            'employee_id'    => $employeeId,
            'type'           => $validated['type'],
            'old_salary'     => $oldSalary,
            'new_salary'     => $newSalary,
            'amount_change'  => $amountChange,
            'effective_date' => $validated['effective_date'],
            'reason'         => $validated['reason'] ?? null,
            'recorded_by'    => $user->id,
            'created_at'     => now(),
            'updated_at'     => now(),
        ]);

        $employee->update(['salary' => $newSalary]);

        try {
            activity()->causedBy($user)->performedOn($employee)
                ->withProperties(['type' => $validated['type'], 'old' => $oldSalary, 'new' => $newSalary, 'ip_address' => $request->ip()])
                ->log('Employee salary updated');
        } catch (\Exception $e) {}

        return response()->json(['message' => 'Salary updated', 'new_salary' => $newSalary, 'change' => $amountChange], 201);
    }

    // ── EVENTS (awards, reviews, fines, dept changes, notes) ──────
    public function getEvents(Request $request, $employeeId)
    {
        $user     = $request->user();
        $employee = Employee::findOrFail($employeeId);
        if (!$user->isSuperAdmin() && !$user->canAccessCompany($employee->company_id)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }
        $events = DB::table('employee_events')
            ->where('employee_id', $employeeId)
            ->orderByDesc('event_date')
            ->get();
        return response()->json(['data' => $events]);
    }

    public function addEvent(Request $request, $employeeId)
    {
        $user     = $request->user();
        $employee = Employee::findOrFail($employeeId);
        if (!$user->isSuperAdmin() && !$user->canAccessCompany($employee->company_id)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $validated = $request->validate([
            'type'        => 'required|in:award,review,fine,department_change,status_change,note,termination',
            'title'       => 'required|string|max:255',
            'description' => 'nullable|string|max:2000',
            'amount'      => 'nullable|numeric',
            'event_date'  => 'required|date',
            'old_value'   => 'nullable|string|max:255',
            'new_value'   => 'nullable|string|max:255',
        ]);

        // Handle specific event side effects
        if ($validated['type'] === 'status_change' && !empty($validated['new_value'])) {
            $allowedStatuses = ['active', 'on-leave', 'terminated', 'resigned'];
            if (in_array($validated['new_value'], $allowedStatuses)) {
                $validated['old_value'] = $employee->status;
                $employee->update(['status' => $validated['new_value']]);
            }
        }

        if ($validated['type'] === 'department_change' && !empty($validated['new_value'])) {
            $validated['old_value'] = $employee->department?->name ?? $employee->department_id;
            $dept = \App\Models\Department::where('name', $validated['new_value'])
                ->where('company_id', $employee->company_id)
                ->first();
            if ($dept) $employee->update(['department_id' => $dept->id]);
        }

        if ($validated['type'] === 'termination') {
            $employee->update(['status' => 'terminated']);
        }

        // If it's a fine, apply to salary
        if ($validated['type'] === 'fine' && !empty($validated['amount'])) {
            $oldSal = (float) $employee->salary;
            $newSal = max(0, $oldSal - abs((float)$validated['amount']));
            $employee->update(['salary' => $newSal]);
            DB::table('employee_salary_history')->insert([
                'employee_id'    => $employeeId,
                'type'           => 'fine',
                'old_salary'     => $oldSal,
                'new_salary'     => $newSal,
                'amount_change'  => $newSal - $oldSal,
                'effective_date' => $validated['event_date'],
                'reason'         => $validated['title'],
                'recorded_by'    => $user->id,
                'created_at'     => now(),
                'updated_at'     => now(),
            ]);
        }

        $id = DB::table('employee_events')->insertGetId([
            'employee_id' => $employeeId,
            'type'        => $validated['type'],
            'title'       => $validated['title'],
            'description' => $validated['description'] ?? null,
            'amount'      => $validated['amount'] ?? null,
            'event_date'  => $validated['event_date'],
            'old_value'   => $validated['old_value'] ?? null,
            'new_value'   => $validated['new_value'] ?? null,
            'recorded_by' => $user->id,
            'created_at'  => now(),
            'updated_at'  => now(),
        ]);

        try {
            activity()->causedBy($user)->performedOn($employee)
                ->withProperties(['type' => $validated['type'], 'title' => $validated['title'], 'ip_address' => $request->ip()])
                ->log('Employee event recorded: ' . $validated['type']);
        } catch (\Exception $e) {}

        return response()->json(['data' => DB::table('employee_events')->find($id), 'message' => 'Event recorded'], 201);
    }

    // ── COMPANY FINANCIALS ─────────────────────────────────────────
    public function updateCompanyFinancials(Request $request)
    {
        $user    = $request->user();
        $company = \App\Models\Company::find($user->company_id)?->fresh();
        if (!$company) return response()->json(['message' => 'No company associated with your account'], 403);

        $validated = $request->validate([
            'revenue'           => 'nullable|numeric|min:0',
            'cash_balance'      => 'nullable|numeric|min:0',
            'total_assets'      => 'nullable|numeric|min:0',
            'total_liabilities' => 'nullable|numeric|min:0',
            'credit_score'      => 'nullable|integer|min:300|max:850',
            'runway_days'       => 'nullable|integer|min:0',
            'expenses_manual'   => 'nullable|numeric|min:0',
            'notes'             => 'nullable|string|max:500',
            'report_period'     => 'nullable|in:monthly,quarterly,annual',
        ]);

        $ip              = $request->ip();
        $hasReportPeriod = \Illuminate\Support\Facades\Schema::hasColumn('company_financial_logs', 'report_period');

        // ── Build the SET clause: ADD to existing values instead of replacing ──
        $incrementalFields = ['revenue','cash_balance','total_assets','total_liabilities','expenses_manual'];
        $directFields      = ['credit_score','runway_days'];
        $currentFin        = \DB::table('companies')->where('id', $company->id)->first();

        $updateData = ['updated_at' => now()];
        foreach ($incrementalFields as $field) {
            if (isset($validated[$field]) && $validated[$field] !== null
                && \Illuminate\Support\Facades\Schema::hasColumn('companies', $field)) {
                $existing = isset($currentFin->$field) && $currentFin->$field !== null ? (float)$currentFin->$field : 0;
                $updateData[$field] = $existing + (float)$validated[$field];
            }
        }
        foreach ($directFields as $field) {
            if (isset($validated[$field]) && $validated[$field] !== null
                && \Illuminate\Support\Facades\Schema::hasColumn('companies', $field)) {
                $updateData[$field] = $validated[$field];
            }
        }

        // ── Write audit logs before update (so we capture old → new) ──────────────
        $loggableFields = ['revenue','cash_balance','total_assets','total_liabilities','expenses_manual'];
        foreach ($loggableFields as $field) {
            if (!array_key_exists($field, $updateData)) continue;
            $oldVal = isset($currentFin->$field) && $currentFin->$field !== null ? (float)$currentFin->$field : 0;
            $newVal = (float)$updateData[$field];
            if ($oldVal !== $newVal) {
                $row = [
                    'company_id'      => $company->id,
                    'field_name'      => $field,
                    'old_value'       => $oldVal,
                    'new_value'       => $newVal,
                    'changed_by'      => $user->id,
                    'changed_by_name' => $user->name,
                    'ip_address'      => $ip,
                    'country'         => null,
                    'notes'           => $validated['notes'] ?? null,
                    'created_at'      => now(),
                    'updated_at'      => now(),
                ];
                if ($hasReportPeriod) $row['report_period'] = $validated['report_period'] ?? 'monthly';
                \DB::table('company_financial_logs')->insert($row);
            }
        }

        // ── Perform the update directly via DB::table (no Eloquent casting issues) ─
        \DB::table('companies')->where('id', $company->id)->update($updateData);

        try {
            activity()->causedBy($user)->performedOn($company)
                ->withProperties(array_merge($validated, ['ip_address' => $ip]))
                ->log('Company financials updated');
        } catch (\Exception $e) {}

        // Return fresh data so the frontend can confirm what was saved
        $fresh = \DB::table('companies')->where('id', $company->id)->first();
        return response()->json([
            'message' => 'Financials updated',
            'data'    => $fresh,
        ]);
    }

    public function financialLogs(Request $request)
    {
        $user    = $request->user();
        $company = \App\Models\Company::find($user->company_id);
        if (!$company) return response()->json(['data' => []]);

        $field = $request->get('field');
        $query = \DB::table('company_financial_logs')
            ->where('company_id', $company->id);
        if ($field) $query->where('field_name', $field);

        $logs = $query->orderByDesc('created_at')->limit(50)->get();
        return response()->json(['data' => $logs]);
    }
}
