<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\ApplicationDeviation;
use App\ApplicationDeviationLog;
use Carbon\Carbon;
use App\Comments;
use App\ConsumerApplication;
use App\DeviationType;
use App\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;

class ApplicationDeviationController extends Controller{

    public function saveDeviation(Request $request) {

        if ($request->filled('id')) {
            $validated = $request->validate([
                'id' => 'nullable|integer', // Add ID validation
                'consumer_application_id' => 'required|integer',
                'application_details' => 'nullable|string',
                'maker_deviation_notes' => 'nullable|string',
                'checker_id' => 'nullable|integer',
                'checker_comment' => 'nullable|string', // Allow comment update
                'status' => 'nullable|string', // Allow status update
            ]);
            $deviation = ApplicationDeviation::findOrFail($request->id);

            // capture old values for logging
            $old_status = $deviation->status;
            $old_application_details = $deviation->application_details;
            $old_checker_comment = $deviation->checker_comment ?? '';

            $deviation->fill($validated);

            // Only update status if explicitly provided in the edit form
            if($request->has('status')){
                $deviation->status = $request->status;
            }

            $deviation->save();

            // determine values for log
            $event = 'update';
            $logDetails = $request->filled('application_details') ? $request->application_details : $old_application_details;
            $logStatus = $request->has('status') ? $request->status : $deviation->status;
            $logNotes = $request->filled('maker_deviation_notes') ? $request->maker_deviation_notes : ($deviation->maker_deviation_notes ?? '');
            $logComment = $request->filled('checker_comment') ? $request->checker_comment : $old_checker_comment;

        } else {
            $validated = $request->validate([
                'id' => 'nullable|integer', 
                'consumer_application_id' => 'required|integer',
                'deviation_type_id' => 'required|integer',
                'application_details' => 'nullable|string',
                'maker_deviation_notes' => 'nullable|string',
                'checker_id' => 'nullable|integer',
                'checker_comment' => 'nullable|string', 
                'status' => 'nullable|string', 
            ]);

            $deviation = new ApplicationDeviation();
            $deviation->fill($validated);
            $deviation->maker_id = Auth::id(); // Maker is set only on creation
            $deviation->status = 'Pending';
            $deviation->save();

            $this->sendNotification(
                $request->checker_id,
                $request->consumer_application_id,
                Auth::id()
            );

            $old_status = null;
            $event = 'create';
            $logDetails = $request->filled('application_details') ? $request->application_details : $deviation->application_details;
            $logStatus = $request->has('status') ? $request->status : $deviation->status;
            $logNotes = $request->filled('maker_deviation_notes') ? $request->maker_deviation_notes : ($deviation->maker_deviation_notes ?? '');
            $logComment = $request->filled('checker_comment') ? $request->checker_comment : ($deviation->checker_comment ?? '');
        }

        $checker_id_for_log = $request->filled('checker_id') 
            ? $request->checker_id 
            : null;

        $this->logDeviationHistory(
            $deviation->id,
            $event,
            $old_status,
            $logStatus,
            $logDetails,
            $checker_id_for_log,
            $logNotes,
            $logComment
        );

        $deviation->load(['maker', 'checker', 'deviationType']);

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

    public function updateStatus(Request $request, $id){
        $deviation = ApplicationDeviation::findOrFail($id);

        // capture old values
        $old_status = $deviation->status;
        $old_application_details = $deviation->application_details;
        $old_checker_comment = $deviation->checker_comment ?? '';

        // update fields
        $checker_name = $request->checker_name;
        $deviation->status = $request->status;
        if($request->has('checker_comment')){
            $deviation->checker_comment = $request->checker_comment;
        }
        $deviation->save();

        if ($old_status != $request->status) {
            
            // Define variables for the string
            $deviation_on = $request->deviation_name; 
            $comment_text = "Deviation: {$request->status} on {$deviation_on} by {$checker_name}";

            Comments::insert([
                'application_id' => $deviation->consumer_application_id, // Assuming deviation has application_id
                'user_id'        => Auth::id(),
                'comment'        => $comment_text,
                'show_consumer'  => 0,
                'show_merchant'  => 0,
                'created_at'     => Carbon::now()->toDateTimeString(),
                'updated_at'     => Carbon::now()->toDateTimeString(),
                'type'           => 'consumer',
            ]);
        }

        $logDetails = $request->filled('application_details') ? $request->application_details : $old_application_details;
        $logChecker = $request->filled('checker_id') ? $request->checker_id : $deviation->checker_id;
        $logNotes   = $deviation->maker_deviation_notes ?? '';
        $logComment = $request->has('checker_comment') ? $request->checker_comment : $old_checker_comment;

        // Centralized Logging
        $this->logDeviationHistory(
            $deviation->id,
            'update',
            $old_status,
            $request->status,
            $logDetails,
            $logChecker,
            $logNotes,
            $logComment
        );

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

    public function deleteDeviation($id){
        $deviation = ApplicationDeviation::findOrFail($id);

        $this->logDeviationHistory(
            $deviation->id,
            'delete',
            $deviation->status,            // Old Status
            $deviation->status,            // Current Status (Same on delete)
            $deviation->application_details,
            $deviation->checker_id,
            $deviation->maker_deviation_notes ?? '',
            $deviation->checker_comment ?? ''
        );

        $deviation->delete();

        return response()->json(['success' => true]);
    }

    private function logDeviationHistory($deviationId, $event, $oldStatus, $currentStatus, $details, $checkerId, $notes, $comment) {
        ApplicationDeviationLog::create([
            'application_deviation_id' => $deviationId,
            'application_details'      => $details,
            'action_by_id'             => Auth::id(),
            'checker_id'               => $checkerId,
            'remark'                   => json_encode([
                                            'notes'   => $notes,
                                            'comment' => $comment
                                          ]),
            'old_status'               => $oldStatus,
            'current_status'           => $currentStatus,
            'event'                    => $event,
            'created_at'               => now()
        ]);
    }

    public function getDeviationsByApplication($application_id){
        $deviations = ApplicationDeviation::with(['maker', 'checker', 'deviationType']) 
            ->where('consumer_application_id', $application_id)
            ->orderBy('created_at', 'desc')
            ->get();

        return response()->json(['deviations' => $deviations]);
    }

    public function getTypes(){
        // Eloquent: Fetch all types that are not soft-deleted
        $types = DeviationType::where('is_active', 1)
            ->orderBy('created_at', 'asc')->get();

        return response()->json($types);
    }

    public function deleteType(Request $request) {
        $request->validate([
            'id' => 'required|integer'
        ]);

        $type = DeviationType::find($request->id);

        if($type) {
            // Soft delete logic: set is_active to 0
            $type->is_active = 0; 
            $type->save();
            
            return response()->json(['success' => true, 'message' => 'Type deleted successfully']);
        }
        return response()->json(['success' => false, 'message' => 'Type not found'], 404);
    }

    public function storeType(Request $request){
        $request->validate(['name' => 'required|string|max:191']);

        $type = DeviationType::create([
            'name'       => $request->name,
            'is_active'  => 1,
            'created_by' => Auth::id(),
        ]);

        return response()->json([
            'success' => true, 
            'id'      => $type->id, 
            'name'    => $type->name 
        ]);
    }

    public function getLogs(Request $request){
        $applicationId = $request->application_id;

        $deviationIds = ApplicationDeviation::withTrashed()
            ->where('consumer_application_id', $applicationId)
            ->pluck('id');

        // eager load applicationDeviation -> deviationType and the actionBy user
        $logs = ApplicationDeviationLog::with([
                'applicationDeviation' => function ($q) {
                    $q->withTrashed()->with(['deviationType' => function ($q2) {
                        if (method_exists($q2->getModel(), 'trashed')) {
                            // If DeviationType also uses SoftDeletes, include trashed
                            $q2->withTrashed();
                        }
                    }]);
                },
                'actionBy'
            ])
            ->whereIn('application_deviation_id', $deviationIds)
            ->orderBy('created_at', 'desc')
            ->get();

        $result = $logs->map(function ($log) {
            return [
                'id' => $log->id,
                'application_deviation_id' => $log->application_deviation_id,
                'application_details' => $log->application_details,
                'deviation_type' => optional($log->applicationDeviation->deviationType)->name, // null-safe
                'action_by_name' => optional($log->actionBy)->name,
                'checker_name'  =>  optional($log->checker)->name,
                'remark' => $log->remark,
                'event' => $log->event,
                'old_status' => $log->old_status,
                'current_status' => $log->current_status,
                'created_at' => $log->created_at ? $log->created_at->format('Y-m-d H:i:s') : '',
            ];
        });

        return response()->json($result);
    }

    protected function sendNotification(int $checkerId, int $consumerApplicationId, int $makerId){
        $checker = User::find($checkerId);
        $maker = User::find($makerId);
        $application = ConsumerApplication::with('activeMerchant')
            ->find($consumerApplicationId);

        if (!$checker || empty($checker->email)) {
            return; 
        }

        $losHost = rtrim(env('APP_URL'), '/');
        $approvalLink = $losHost . '/admin/consumer-applications/edit/' . $consumerApplicationId . '#nav-application-deviation';

        $mailData = [
            'name' => $checker->name,
            'application_id' => $consumerApplicationId,
            'link' => $approvalLink,
            'customer_name' => $application->name,
            'merchant_name' => $application->activeMerchant->merchant_name,
            'creator_name'  => $maker->name,
            'status' => Str::ucfirst($application->state),
            'logo_url'        => env('LENDER_KMGCP_LOGO')
        ];
        $fromEmail = env('GLOBAL_EMAIL_REPLY_TO');
        Mail::send('admin.consumer-application.sections.deviation-mail', $mailData, function ($message) use ($checker, $fromEmail) {
            $message->to($checker->email)
                    ->from($fromEmail, 'Credit Fair')
                    ->replyTo($fromEmail)
                    ->subject('New Deviation Created – Approval Required');
        });
    }
}