<?php

namespace App\Http\Controllers\Warehouse\IndirectGoods;

use App\Http\Controllers\Controller;
use App\Models\Warehouse\IndirectGoods\IndirectGoodsRequest;
use App\Models\Warehouse\IndirectGoods\IndirectGoodsRequestItem;
use App\Models\Warehouse\IndirectGoods\IndirectGood;
use App\Models\Warehouse\Project;
use App\Models\Warehouse\ProjectDivision;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class IndirectGoodsRequestController extends Controller
{
    public function __construct()
    {
        $this->middleware('warehouse.access');
        $this->middleware('warehouse.permission:warehouse.indirect-requests.view')->only(['index', 'show', 'pendingApproval']);
        $this->middleware('warehouse.permission:warehouse.indirect-requests.create')->only(['create', 'store']);
        $this->middleware('warehouse.permission:warehouse.indirect-requests.approve')->only(['approve', 'reject']);
        $this->middleware('warehouse.permission:warehouse.indirect-requests.issue')->only(['issue']);
    }

    /**
     * Display a listing of indirect goods material requests.
     */
    public function index(Request $request)
    {
        if ($request->ajax() || $request->expectsJson()) {
            $query = IndirectGoodsRequest::with(['project', 'division', 'requester', 'items']);

            // Filter: status
            if ($request->filled('status') && $request->status !== 'all') {
                $query->where('status', $request->status);
            }

            // Filter: project
            if ($request->filled('project_id')) {
                $query->where('project_id', $request->project_id);
            }

            // Filter: date range
            if ($request->filled('date_from')) {
                $query->whereDate('request_date', '>=', $request->date_from);
            }
            if ($request->filled('date_to')) {
                $query->whereDate('request_date', '<=', $request->date_to);
            }

            // Search
            if ($request->filled('search.value') && $request->input('search.value') !== '') {
                $search = $request->input('search.value');
                $query->where(function ($q) use ($search) {
                    $q->where('request_number', 'LIKE', "%{$search}%")
                      ->orWhere('receiver_name', 'LIKE', "%{$search}%")
                      ->orWhere('notes', 'LIKE', "%{$search}%")
                      ->orWhereHas('project', function ($q2) use ($search) {
                          $q2->where('project_name', 'LIKE', "%{$search}%")
                             ->orWhere('project_number', 'LIKE', "%{$search}%");
                      })
                      ->orWhereHas('requester', function ($q2) use ($search) {
                          $q2->where('name', 'LIKE', "%{$search}%");
                      });
                });
            }

            $totalRecords = IndirectGoodsRequest::count();
            $filteredRecords = $query->count();

            // Sorting
            $orderColumn = $request->input('order.0.column', 0);
            $orderDir = $request->input('order.0.dir', 'desc');
            $columns = ['id', 'request_number', 'request_date', 'project_id', 'division_id', 'requested_by', 'id', 'status', 'id'];
            $orderBy = $columns[$orderColumn] ?? 'created_at';
            $query->orderBy($orderBy, $orderDir);

            $start = $request->input('start', 0);
            $length = $request->input('length', 10);
            $records = $query->skip($start)->take($length)->get();

            return response()->json([
                'draw' => intval($request->input('draw')),
                'recordsTotal' => $totalRecords,
                'recordsFiltered' => $filteredRecords,
                'data' => $records->map(function ($record, $index) use ($start) {
                    $statusLabels = [
                        'draft' => '<span class="badge badge-secondary">Draft</span>',
                        'pending_approval' => '<span class="badge badge-warning">Pending Approval</span>',
                        'approved' => '<span class="badge badge-info">Approved</span>',
                        'rejected' => '<span class="badge badge-danger">Rejected</span>',
                        'issued' => '<span class="badge badge-success">Issued</span>',
                        'partially_issued' => '<span class="badge badge-primary">Partially Issued</span>',
                        'cancelled' => '<span class="badge badge-dark">Cancelled</span>',
                    ];

                    // Build action buttons based on status
                    $actions = '<div class="btn-group" role="group">';
                    $actions .= '<a href="' . route('warehouse.indirect-goods.requests.show', $record->id) . '" class="btn btn-sm btn-outline-primary" title="View"><i class="material-icons" style="font-size:16px;">visibility</i></a>';

                    if ($record->status === 'pending_approval') {
                        $actions .= '<button type="button" class="btn btn-sm btn-outline-success approve-btn" data-id="' . $record->id . '" data-reference="' . e($record->request_number) . '" title="Approve"><i class="material-icons" style="font-size:16px;">check</i></button>';
                        $actions .= '<button type="button" class="btn btn-sm btn-outline-danger reject-btn" data-id="' . $record->id . '" data-reference="' . e($record->request_number) . '" title="Reject"><i class="material-icons" style="font-size:16px;">close</i></button>';
                    }

                    if ($record->status === 'approved') {
                        $actions .= '<form method="POST" action="' . route('warehouse.indirect-goods.requests.issue', $record->id) . '" style="display:inline;" onsubmit="return confirm(\'Issue materials for ' . e($record->request_number) . '?\');">' . csrf_field() . '<button type="submit" class="btn btn-sm btn-outline-info" title="Issue Materials"><i class="material-icons" style="font-size:16px;">local_shipping</i></button></form>';
                    }

                    $actions .= '</div>';

                    return [
                        'DT_RowIndex' => $start + $index + 1,
                        'id' => $record->id,
                        'request_number' => $record->request_number,
                        'request_date' => $record->request_date ? $record->request_date->format('Y-m-d') : '-',
                        'project' => $record->project ? $record->project->project_number . ' - ' . $record->project->project_name : '-',
                        'division' => $record->division ? $record->division->division_name : '-',
                        'requested_by' => $record->requester ? $record->requester->name : '-',
                        'items_count' => $record->items->count(),
                        'status' => $statusLabels[$record->status] ?? '<span class="badge badge-secondary">' . ucfirst($record->status) . '</span>',
                        'actions' => $actions,
                    ];
                }),
            ]);
        }

        $projects = Project::orderBy('project_name')->get();
        return view('warehouse.indirect-goods.requests.index', compact('projects'));
    }

    /**
     * Show the form for creating a new request.
     */
    public function create()
    {
        $projects = Project::orderBy('project_name')->get();
        $divisions = ProjectDivision::orderBy('division_name')->get();

        return view('warehouse.indirect-goods.requests.create', compact('projects', 'divisions'));
    }

    /**
     * Store a newly created request.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'request_date' => 'required|date',
            'project_id' => 'required|exists:projects,id',
            'division_id' => 'nullable|exists:project_divisions,id',
            'receiver_name' => 'nullable|string|max:255',
            'notes' => 'nullable|string|max:2000',
            'requires_approval' => 'nullable',
            'request_file' => 'nullable|file|mimes:pdf,doc,docx,jpg,jpeg,png|max:10240',
            'items' => 'required|array|min:1',
            'items.*.indirect_good_id' => 'required|exists:indirect_goods,id',
            'items.*.quantity_requested' => 'required|numeric|min:0.01',
            'items.*.notes' => 'nullable|string|max:500',
        ]);

        try {
            DB::beginTransaction();

            $requiresApproval = $request->has('requires_approval') && $request->requires_approval;

            // Handle file upload
            $filePath = null;
            if ($request->hasFile('request_file')) {
                $filePath = $request->file('request_file')->store('indirect-goods/requests', 'public');
            }

            // Create the request
            $igRequest = IndirectGoodsRequest::create([
                'request_date' => $validated['request_date'],
                'project_id' => $validated['project_id'],
                'division_id' => $validated['division_id'] ?? null,
                'status' => $requiresApproval ? 'pending_approval' : 'approved',
                'requires_approval' => $requiresApproval,
                'requested_by' => auth()->id(),
                'receiver_name' => $validated['receiver_name'] ?? null,
                'notes' => $validated['notes'] ?? null,
                'request_file' => $filePath,
            ]);

            // If auto-approved, set approval fields
            if (!$requiresApproval) {
                $igRequest->approved_by = auth()->id();
                $igRequest->approved_at = now();
                $igRequest->save();
            }

            // Create request items
            foreach ($validated['items'] as $item) {
                IndirectGoodsRequestItem::create([
                    'indirect_goods_request_id' => $igRequest->id,
                    'indirect_good_id' => $item['indirect_good_id'],
                    'quantity_requested' => $item['quantity_requested'],
                    'quantity_released' => 0,
                    'quantity_balance' => $item['quantity_requested'],
                    'unit_price' => 0,
                    'total_price' => 0,
                    'notes' => $item['notes'] ?? null,
                ]);
            }

            DB::commit();

            return redirect()->route('warehouse.indirect-goods.requests.show', $igRequest->id)
                ->with('success', 'Material request ' . $igRequest->request_number . ' created successfully.' . (!$requiresApproval ? ' (Auto-approved)' : ''));

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('IndirectGoodsRequest store error: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString(),
            ]);

            return back()->withInput()->with('error', 'Failed to create material request: ' . $e->getMessage());
        }
    }

    /**
     * Display the specified request.
     */
    public function show($id)
    {
        $igRequest = IndirectGoodsRequest::with([
            'project',
            'division',
            'requester',
            'approvedBy',
            'issuedBy',
            'items.indirectGood',
        ])->findOrFail($id);

        return view('warehouse.indirect-goods.requests.show', compact('igRequest'));
    }

    /**
     * Display requests pending approval.
     */
    public function pendingApproval(Request $request)
    {
        $query = IndirectGoodsRequest::with(['project', 'division', 'requester', 'items'])
            ->where('status', 'pending_approval')
            ->orderBy('created_at', 'asc');

        $pendingCount = $query->count();
        $requests = $query->paginate(20);

        return view('warehouse.indirect-goods.requests.pending-approval', compact('requests', 'pendingCount'));
    }

    /**
     * Approve a request.
     */
    public function approve($id)
    {
        $igRequest = IndirectGoodsRequest::findOrFail($id);

        if ($igRequest->approve(auth()->id())) {
            return redirect()->back()->with('success', 'Request ' . $igRequest->request_number . ' has been approved.');
        }

        return redirect()->back()->with('error', 'Cannot approve this request. Current status: ' . $igRequest->status);
    }

    /**
     * Reject a request.
     */
    public function reject(Request $request, $id)
    {
        $request->validate([
            'rejection_reason' => 'required|string|max:1000',
        ]);

        $igRequest = IndirectGoodsRequest::findOrFail($id);

        if ($igRequest->reject(auth()->id(), $request->rejection_reason)) {
            return redirect()->back()->with('success', 'Request ' . $igRequest->request_number . ' has been rejected.');
        }

        return redirect()->back()->with('error', 'Cannot reject this request. Current status: ' . $igRequest->status);
    }

    /**
     * Issue materials for an approved request.
     */
    public function issue($id)
    {
        $igRequest = IndirectGoodsRequest::with('items.indirectGood')->findOrFail($id);

        try {
            DB::beginTransaction();

            if ($igRequest->issue(auth()->id())) {
                DB::commit();
                $statusMsg = $igRequest->status === 'issued' ? 'All materials issued successfully.' : 'Materials partially issued (some items had insufficient stock).';
                return redirect()->route('warehouse.indirect-goods.requests.show', $igRequest->id)
                    ->with('success', 'Request ' . $igRequest->request_number . ': ' . $statusMsg);
            }

            DB::rollBack();
            return redirect()->back()->with('error', 'Cannot issue materials for this request. Current status: ' . $igRequest->status);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('IndirectGoodsRequest issue error: ' . $e->getMessage(), [
                'request_id' => $igRequest->id,
                'trace' => $e->getTraceAsString(),
            ]);

            return redirect()->back()->with('error', 'Failed to issue materials: ' . $e->getMessage());
        }
    }

    /**
     * Print layout for a request.
     */
    public function print($id)
    {
        $igRequest = IndirectGoodsRequest::with([
            'project',
            'division',
            'requester',
            'approvedBy',
            'issuedBy',
            'items.indirectGood',
        ])->findOrFail($id);

        return view('warehouse.indirect-goods.requests.print', compact('igRequest'));
    }
}
