<?php

namespace App\Services\Material;

use App\Models\TechnicianMaterial;
use App\Models\TechnicianConsumable;
use App\Models\MaterialMovement;
use Carbon\Carbon;
use DB;

class MaterialService
{
    /*
    |--------------------------------------------------------------------------
    | ASSIGN MATERIAL (AUTO DETECT TYPE)
    |--------------------------------------------------------------------------
    */
    public function assign($data)
    {
        return DB::transaction(function () use ($data) {

            $type = $data['type']; 
            // type dari API Gudang: serialized / consumable

            /*
            |--------------------------------------------------------------------------
            | SERIALIZED (ONT, Router, dll)
            |--------------------------------------------------------------------------
            */
            if ($type === 'serialized') {

                $material = TechnicianMaterial::create([
                    'user_id' => $data['user_id'],
                    'barcode_id' => $data['barcode_id'],
                    'material_name' => $data['material_name'],
                    'serial_number' => $data['serial_number'] ?? null,
                    'status' => 'assigned',
                    'assigned_at' => now(),
                    'assigned_by' => auth()->id(),
                ]);

                MaterialMovement::create([
                    'barcode_id' => $data['barcode_id'],
                    'user_id' => $data['user_id'],
                    'to_user_id' => $data['user_id'],
                    'movement_type' => 'assign',
                    'created_by' => auth()->id(),
                    'created_at' => now(),
                ]);

                return $material;
            }

            /*
            |--------------------------------------------------------------------------
            | CONSUMABLE (FO, kabel, dll)
            |--------------------------------------------------------------------------
            */
            $material = TechnicianConsumable::create([
                'user_id' => $data['user_id'],
                'barcode_id' => $data['barcode_id'],
                'material_name' => $data['material_name'],
                'unit' => $data['unit'] ?? 'meter',
                'qty_received' => $data['qty'] ?? 0,
                'qty_remaining' => $data['qty'] ?? 0,
                'qty_used' => 0,
                'status' => 'assigned',
                'assigned_at' => now(),
                'assigned_by' => auth()->id(),
            ]);

            MaterialMovement::create([
                'barcode_id' => $data['barcode_id'],
                'user_id' => $data['user_id'],
                'to_user_id' => $data['user_id'],
                'movement_type' => 'assign',
                'qty' => $data['qty'] ?? 0,
                'created_by' => auth()->id(),
                'created_at' => now(),
            ]);

            return $material;
        });
    }

    /*
    |--------------------------------------------------------------------------
    | TRANSFER MATERIAL
    |--------------------------------------------------------------------------
    */
    public function transfer($data)
    {
        return DB::transaction(function () use ($data) {

            $barcode = $data['barcode_id'];

            // cek serialized dulu
            $serialized = TechnicianMaterial::where('barcode_id', $barcode)->first();

            if ($serialized) {

                $serialized->update([
                    'user_id' => $data['to_user_id']
                ]);

                MaterialMovement::create([
                    'barcode_id' => $barcode,
                    'from_user_id' => $data['from_user_id'],
                    'to_user_id' => $data['to_user_id'],
                    'movement_type' => 'transfer',
                    'created_by' => auth()->id(),
                    'created_at' => now(),
                ]);

                return $serialized;
            }

            // kalau bukan serialized → consumable
            $consumable = TechnicianConsumable::where('barcode_id', $barcode)->first();

            $consumable->update([
                'user_id' => $data['to_user_id']
            ]);

            MaterialMovement::create([
                'barcode_id' => $barcode,
                'from_user_id' => $data['from_user_id'],
                'to_user_id' => $data['to_user_id'],
                'movement_type' => 'transfer',
                'qty' => $consumable->qty_remaining,
                'created_by' => auth()->id(),
                'created_at' => now(),
            ]);

            return $consumable;
        });
    }

    /*
    |--------------------------------------------------------------------------
    | RETURN MATERIAL
    |--------------------------------------------------------------------------
    */
    public function return($data)
    {
        return DB::transaction(function () use ($data) {

            $barcode = $data['barcode_id'];

            $serialized = TechnicianMaterial::where('barcode_id', $barcode)->first();

            if ($serialized) {

                $serialized->update([
                    'user_id' => null,
                    'status' => 'returned'
                ]);

                MaterialMovement::create([
                    'barcode_id' => $barcode,
                    'user_id' => $data['user_id'],
                    'from_user_id' => $data['user_id'],
                    'movement_type' => 'return',
                    'created_by' => auth()->id(),
                    'created_at' => now(),
                ]);

                return $serialized;
            }

            $consumable = TechnicianConsumable::where('barcode_id', $barcode)->first();

            $consumable->update([
                'user_id' => null,
                'status' => 'returned'
            ]);

            MaterialMovement::create([
                'barcode_id' => $barcode,
                'user_id' => $data['user_id'],
                'from_user_id' => $data['user_id'],
                'movement_type' => 'return',
                'qty' => $consumable->qty_remaining,
                'created_by' => auth()->id(),
                'created_at' => now(),
            ]);

            return $consumable;
        });
    }

    public function listByUser($userId)
    {
        $serialized = TechnicianMaterial::where('user_id', $userId)
            ->get()
            ->map(function ($item) {
                $item->type = 'serialized';
                return $item;
            });

        $consumable = TechnicianConsumable::where('user_id', $userId)
            ->get()
            ->map(function ($item) {
                $item->type = 'consumable';
                return $item;
            });

        return $serialized
            ->concat($consumable)
            ->values();
    }

    public function history($barcodeId)
    {
        return MaterialMovement::where('barcode_id', $barcodeId)
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($item) {

                return [
                    'barcode_id'    => $item->barcode_id,
                    'type'          => $item->movement_type,
                    'from_user_id'  => $item->from_user_id,
                    'to_user_id'    => $item->to_user_id,
                    'ticket_id'     => $item->ticket_id,
                    'qty'           => $item->qty,
                    'description'   => $item->description,
                    'created_at'    => $item->created_at,
                ];
            });
    }
}