<?php

namespace App\Http\Controllers\Warehouse;

use App\Http\Controllers\Controller;
use App\Models\Warehouse\MaterialTransferIssue;
use App\Models\Warehouse\MaterialTransferIssueItem;
use App\Models\Warehouse\MaterialTransferRequest;
use App\Models\Warehouse\ProjectInventory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class MaterialTransferIssueController extends Controller
{
    /**
     * Display a listing of transfer issues.
     */
    public function index(Request $request)
    {
        // Handle DataTable AJAX requests
        if ($request->has('ajax_request') && $request->expectsJson()) {
            return $this->getTransferIssuesDataForTable($request);
        }

        // Get all transfer requests in workflow
        $allPendingRequests = MaterialTransferRequest::with([
            'transferrerProject',
            'receiverProject',
            'requestedBy',
            'items'
        ])
        ->whereIn('status', ['pending_transferrer_approval', 'partially_approved', 'approved'])
        ->latest('created_at')
        ->get();

        return view('warehouse.transfer-issues.index', compact('allPendingRequests'));
    }

    /**
     * Get transfer issues data for DataTable.
     */
    private function getTransferIssuesDataForTable(Request $request)
    {
        $start = $request->get('start', 0);
        $length = $request->get('length', 25);
        $search = $request->get('search.value');

        // Query transfer issues with relationships
        $query = MaterialTransferIssue::with([
            'transferRequest.transferrerProject',
            'transferRequest.receiverProject',
            'items'
        ])->latest('issue_date');

        // Apply search filter
        if (!empty($search)) {
            $query->where(function($q) use ($search) {
                $q->where('id', 'like', "%{$search}%")
                  ->orWhereHas('transferRequest.transferrerProject', function($subQ) use ($search) {
                      $subQ->where('project_name', 'like', "%{$search}%");
                  })
                  ->orWhereHas('transferRequest.receiverProject', function($subQ) use ($search) {
                      $subQ->where('project_name', 'like', "%{$search}%");
                  });
            });
        }

        // Apply status filter
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        // Apply date filters
        if ($request->filled('issue_date_from')) {
            $query->where('issue_date', '>=', $request->issue_date_from);
        }

        if ($request->filled('issue_date_to')) {
            $query->where('issue_date', '<=', $request->issue_date_to);
        }

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

        $transferIssues = $query->offset($start)->limit($length)->get();

        // Format data for DataTable
        $data = $transferIssues->map(function($issue) {
            return [
                'id' => $issue->id,
                'issue_number' => 'TI-' . str_pad($issue->id, 5, '0', STR_PAD_LEFT),
                'issue_date' => $issue->issue_date->format('M d, Y'),
                'from_project' => $issue->transferRequest->transferrerProject ?
                    $issue->transferRequest->transferrerProject->project_name : 'N/A',
                'to_project' => $issue->transferRequest->receiverProject ?
                    $issue->transferRequest->receiverProject->project_name : 'N/A',
                'items_count' => '<span class="badge badge-info">' . $issue->items->count() . ' items</span>',
                'status' => [
                    'label' => ucfirst(str_replace('_', ' ', $issue->status)),
                    'class' => $this->getTransferIssueStatusClass($issue->status)
                ],
                'actions' => $this->generateTransferIssueActions($issue)
            ];
        });

        return response()->json([
            'draw' => intval($request->get('draw')),
            'recordsTotal' => $totalRecords,
            'recordsFiltered' => $filteredRecords,
            'data' => $data->toArray()
        ]);
    }

    /**
     * Get status CSS class for transfer issue badge styling.
     */
    private function getTransferIssueStatusClass($status)
    {
        return match($status) {
            'draft' => 'secondary',
            'dispatched' => 'info',
            'in_transit' => 'warning',
            'delivered' => 'primary',
            'completed' => 'success',
            'cancelled' => 'danger',
            default => 'secondary'
        };
    }

    /**
     * Generate action buttons for transfer issues.
     */
    private function generateTransferIssueActions($issue)
    {
        $buttons = [];

        // View button - always available
        $buttons[] = '<a href="' . route('warehouse.transfer-issues.show', $issue->id) . '" class="btn btn-sm btn-outline-primary" title="View Details">
                        <i class="material-icons" style="font-size: 16px;">visibility</i>
                      </a>';

        // Print button - always available
        $buttons[] = '<button class="btn btn-sm btn-outline-info" title="Print Transfer Note" onclick="printTransferIssue(' . $issue->id . ')">
                        <i class="material-icons" style="font-size: 16px;">print</i>
                      </button>';

        // Status-specific actions
        switch ($issue->status) {
            case 'draft':
                $buttons[] = '<button class="btn btn-sm btn-outline-success" title="Dispatch" onclick="dispatchTransfer(' . $issue->id . ')">
                                <i class="material-icons" style="font-size: 16px;">local_shipping</i>
                              </button>';
                break;
            case 'dispatched':
                $buttons[] = '<button class="btn btn-sm btn-outline-warning" title="Mark In Transit" onclick="markInTransit(' . $issue->id . ')">
                                <i class="material-icons" style="font-size: 16px;">local_shipping</i>
                              </button>';
                break;
            case 'in_transit':
            case 'delivered':
                $buttons[] = '<button class="btn btn-sm btn-outline-success" title="Receive" onclick="receiveTransfer(' . $issue->id . ')">
                                <i class="material-icons" style="font-size: 16px;">assignment_turned_in</i>
                              </button>';
                break;
        }

        return implode(' ', $buttons);
    }

    /**
     * Show the form for creating transfer issue from approved request.
     */
    public function create(MaterialTransferRequest $transferRequest)
    {
        if (!$transferRequest->canCreateTransferIssue()) {
            return redirect()->back()
                ->with('error', 'Cannot create transfer issue for this request.');
        }

        $transferRequest->load([
            'transferrerProject',
            'receiverProject',
            'items.item'
        ]);

        return view('warehouse.transfer-issues.create', compact('transferRequest'));
    }

    /**
     * Store a newly created transfer issue.
     */
    public function store(Request $request, MaterialTransferRequest $transferRequest)
    {
        if (!$transferRequest->canCreateTransferIssue()) {
            return redirect()->back()
                ->with('error', 'Cannot create transfer issue for this request.');
        }

        $validated = $request->validate([
            'issue_date' => 'required|date',
            'transfer_type' => 'required|in:direct_transfer,staged_transfer',
            'transfer_instructions' => 'nullable|string',
            'requires_inspection' => 'boolean',
            'items' => 'required|array',
            'items.*.quantity_issued' => 'required|numeric|min:0.01',
            'items.*.unit_price' => 'required|numeric|min:0',
            'items.*.batch_number' => 'nullable|string',
            'items.*.serial_numbers' => 'nullable|string',
            'items.*.manufacturing_date' => 'nullable|date',
            'items.*.expiry_date' => 'nullable|date|after:manufacturing_date',
            'items.*.source_location' => 'nullable|string',
            'items.*.source_notes' => 'nullable|string',
            'items.*.condition' => 'required|in:new,good,fair,poor'
        ]);

        DB::transaction(function () use ($transferRequest, $validated) {
            // Create transfer issue
            $transferIssue = MaterialTransferIssue::create([
                'transfer_request_id' => $transferRequest->id,
                'issue_date' => $validated['issue_date'],
                'transfer_type' => $validated['transfer_type'],
                'transfer_instructions' => $validated['transfer_instructions'],
                'requires_inspection' => $validated['requires_inspection'] ?? false,
                'status' => 'draft'
            ]);

            // Create transfer issue items
            foreach ($transferRequest->items as $requestItem) {
                $itemData = $validated['items'][$requestItem->id] ?? null;
                if (!$itemData) continue;

                MaterialTransferIssueItem::create([
                    'transfer_issue_id' => $transferIssue->id,
                    'transfer_request_item_id' => $requestItem->id,
                    'item_id' => $requestItem->item_id,
                    'quantity_requested' => $requestItem->quantity_approved,
                    'quantity_issued' => $itemData['quantity_issued'],
                    'unit_of_measure' => $requestItem->unit_of_measure,
                    'unit_price' => $itemData['unit_price'],
                    'batch_number' => $itemData['batch_number'],
                    'serial_numbers' => $itemData['serial_numbers'],
                    'manufacturing_date' => $itemData['manufacturing_date'],
                    'expiry_date' => $itemData['expiry_date'],
                    'source_location' => $itemData['source_location'],
                    'source_notes' => $itemData['source_notes'],
                    'condition' => $itemData['condition']
                ]);
            }
        });

        return redirect()->route('warehouse.transfer-issues.index')
            ->with('success', 'Material Transfer Issue created successfully.');
    }

    /**
     * Display the specified transfer issue.
     */
    public function show(MaterialTransferIssue $transferIssue)
    {
        $transferIssue->load([
            'transferRequest.transferrerProject',
            'transferRequest.receiverProject',
            'dispatchedBy',
            'receivedBy',
            'inspectedBy',
            'items.item',
            'items.transferRequestItem'
        ]);

        return view('warehouse.transfer-issues.show', compact('transferIssue'));
    }

    /**
     * Dispatch the transfer issue.
     */
    public function dispatch(Request $request, MaterialTransferIssue $transferIssue)
    {
        if ($transferIssue->status !== 'draft') {
            return redirect()->back()
                ->with('error', 'Transfer issue has already been dispatched.');
        }

        $validated = $request->validate([
            'dispatch_vehicle' => 'nullable|string|max:100',
            'driver_name' => 'nullable|string|max:100',
            'driver_contact' => 'nullable|string|max:20'
        ]);

        $transferIssue->dispatch(
            Auth::id(),
            ['vehicle' => $validated['dispatch_vehicle']],
            [
                'name' => $validated['driver_name'],
                'contact' => $validated['driver_contact']
            ]
        );

        return redirect()->back()
            ->with('success', 'Transfer dispatched successfully.');
    }

    /**
     * Mark transfer as in transit.
     */
    public function markInTransit(MaterialTransferIssue $transferIssue)
    {
        if (!$transferIssue->isDispatched() || $transferIssue->status !== 'dispatched') {
            return redirect()->back()
                ->with('error', 'Transfer must be dispatched first.');
        }

        $transferIssue->markInTransit();

        return redirect()->back()
            ->with('success', 'Transfer marked as in transit.');
    }

    /**
     * Receive the transfer.
     */
    public function receive(Request $request, MaterialTransferIssue $transferIssue)
    {
        if (!in_array($transferIssue->status, ['dispatched', 'in_transit', 'delivered'])) {
            return redirect()->back()
                ->with('error', 'Transfer cannot be received at this stage.');
        }

        $validated = $request->validate([
            'receipt_notes' => 'nullable|string',
            'items' => 'required|array',
            'items.*.quantity_received' => 'required|numeric|min:0',
            'items.*.quantity_rejected' => 'nullable|numeric|min:0',
            'items.*.receipt_notes' => 'nullable|string',
            'items.*.condition' => 'required|in:new,good,fair,poor'
        ]);

        DB::transaction(function () use ($transferIssue, $validated) {
            // Update item receipt information
            foreach ($transferIssue->items as $item) {
                $itemData = $validated['items'][$item->id] ?? null;
                if (!$itemData) continue;

                $item->receiveQuantity(
                    $itemData['quantity_received'],
                    $itemData['receipt_notes'],
                    $itemData['condition']
                );

                if ($itemData['quantity_rejected'] > 0) {
                    $item->rejectQuantity(
                        $itemData['quantity_rejected'],
                        $itemData['receipt_notes']
                    );
                }
            }

            $transferIssue->receive(Auth::id(), $validated['receipt_notes']);
        });

        return redirect()->back()
            ->with('success', 'Transfer received successfully.');
    }

    /**
     * Complete inspection for transfer issue.
     */
    public function completeInspection(Request $request, MaterialTransferIssue $transferIssue)
    {
        if (!$transferIssue->requiresInspection() || $transferIssue->status !== 'delivered') {
            return redirect()->back()
                ->with('error', 'Inspection not required or already completed.');
        }

        $validated = $request->validate([
            'inspection_status' => 'required|in:passed,failed,conditional',
            'inspection_notes' => 'nullable|string'
        ]);

        $transferIssue->completeInspection(
            Auth::id(),
            $validated['inspection_status'],
            $validated['inspection_notes']
        );

        return redirect()->back()
            ->with('success', 'Inspection completed successfully.');
    }

    /**
     * Upload delivery documentation.
     */
    public function uploadDocuments(Request $request, MaterialTransferIssue $transferIssue)
    {
        $validated = $request->validate([
            'delivery_note' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:10240',
            'additional_documents.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:10240'
        ]);

        $documents = $transferIssue->attached_documents ?? [];

        if ($request->hasFile('delivery_note')) {
            $deliveryNotePath = $request->file('delivery_note')->store(
                'transfer-issues/' . $transferIssue->id . '/delivery-notes',
                'public'
            );
            $transferIssue->delivery_note_path = $deliveryNotePath;
        }

        if ($request->hasFile('additional_documents')) {
            foreach ($request->file('additional_documents') as $file) {
                $path = $file->store(
                    'transfer-issues/' . $transferIssue->id . '/documents',
                    'public'
                );
                $documents[] = [
                    'name' => $file->getClientOriginalName(),
                    'path' => $path,
                    'uploaded_at' => now()->toISOString()
                ];
            }
        }

        $transferIssue->attached_documents = $documents;
        $transferIssue->save();

        return redirect()->back()
            ->with('success', 'Documents uploaded successfully.');
    }

    /**
     * Cancel transfer issue.
     */
    public function cancel(Request $request, MaterialTransferIssue $transferIssue)
    {
        if ($transferIssue->isCompleted()) {
            return redirect()->back()
                ->with('error', 'Cannot cancel completed transfer.');
        }

        $validated = $request->validate([
            'cancellation_reason' => 'required|string|max:500'
        ]);

        $transferIssue->update([
            'status' => 'cancelled',
            'transfer_instructions' => $transferIssue->transfer_instructions .
                "\n\nCancelled: " . $validated['cancellation_reason']
        ]);

        return redirect()->back()
            ->with('success', 'Transfer issue cancelled.');
    }

    /**
     * Print transfer issue document.
     */
    public function print(MaterialTransferIssue $transferIssue)
    {
        $transferIssue->load([
            'transferRequest.transferrerProject',
            'transferRequest.receiverProject',
            'dispatchedBy',
            'items.item'
        ]);

        // Create a delivery note object that matches our template structure
        $deliveryNote = (object) [
            'outgoingTransaction' => (object) [
                'mr_number' => 'TI-' . str_pad($transferIssue->id, 5, '0', STR_PAD_LEFT),
            ],
            'delivered_to' => $transferIssue->transferRequest->receiverProject ?
                $transferIssue->transferRequest->receiverProject->project_name : 'N/A',
            'generated_date' => $transferIssue->issue_date,
            'project' => $transferIssue->transferRequest->transferrerProject ? (object) [
                'project_number' => $transferIssue->transferRequest->transferrerProject->project_number ?:
                    $transferIssue->transferRequest->transferrerProject->project_name
            ] : null,
            'items' => $transferIssue->items->map(function($item) {
                return (object) [
                    'item' => (object) [
                        'item_name' => $item->item->item_description,
                        'unit' => $item->unit_of_measure ?: 'pcs'
                    ],
                    'quantity_released' => $item->quantity_issued,
                    'remarks' => $item->source_notes ?: ''
                ];
            })
        ];

        return view('warehouse.delivery-notes.template', compact('deliveryNote'));
    }
}