<?php

namespace App\Services\Inventory;

use App\Services\BaseService;
use App\Repositories\RawMaterialRepository;
use App\Models\RawMaterial;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class RawMaterialService extends BaseService
{
    protected RawMaterialRepository $rawMaterialRepository;

    public function __construct(RawMaterialRepository $repository)
    {
        parent::__construct($repository);
        $this->rawMaterialRepository = $repository;
    }

    /**
     * Get with type
     */
    public function getAllWithType(): Collection
    {
        return $this->rawMaterialRepository->getWithType();
    }

    /**
     * Get by type
     */
    public function getByType(int $typeId): Collection
    {
        return $this->rawMaterialRepository->getByType($typeId);
    }

    /**
     * Get active materials
     */
    public function getActive(): Collection
    {
        return $this->rawMaterialRepository->getActive();
    }

    /**
     * Search
     */
    public function search(string $term): Collection
    {
        return $this->rawMaterialRepository->search($term);
    }

    /**
     * Get low stock
     */
    public function getLowStock(int $threshold = 10): Collection
    {
        return $this->rawMaterialRepository->getLowStock($threshold);
    }

    /**
     * Generate material code
     */
    public function generateCode(): string
    {
        return nextNumber('RM', 'raw_materials', 'code', 1);
    }

    /**
     * Create with files
     */
    public function createWithFiles(array $data, array $files = []): RawMaterial
    {
        return DB::transaction(function () use ($data, $files) {
            $data['code'] = $data['code'] ?? $this->generateCode();
            $material = $this->create($data);

            if (!empty($files)) {
                $this->uploadFiles($material, $files);
            }

            $this->logAction('Raw Material created', ['id' => $material->id]);
            return $material;
        });
    }

    /**
     * Upload files
     */
    protected function uploadFiles(RawMaterial $material, array $files): void
    {
        foreach ($files as $file) {
            $path = $file->store('raw-material-files', 'public');
            $material->files()->create([
                'file_path' => $path,
                'file_name' => $file->getClientOriginalName(),
            ]);
        }
    }

    /**
     * Delete file with proper error handling
     */
    public function deleteFile(int $fileId): bool
    {
        $file = \App\Models\RawMaterialFile::findOrFail($fileId);

        try {
            // Try to delete the physical file
            if (Storage::disk('public')->exists($file->file_path)) {
                $deleted = Storage::disk('public')->delete($file->file_path);
                if (!$deleted) {
                    \Log::warning("Could not delete file from storage: {$file->file_path}");
                }
            } else {
                \Log::info("File not found on disk, proceeding with DB deletion: {$file->file_path}");
            }

            // Delete the database record
            $result = $file->delete();

            $this->logAction('Raw Material file deleted', [
                'file_id' => $fileId,
                'file_path' => $file->file_path,
            ]);

            return $result;
        } catch (\Exception $e) {
            \Log::error("Failed to delete raw material file: {$e->getMessage()}", [
                'file_id' => $fileId,
                'file_path' => $file->file_path,
            ]);
            throw $e;
        }
    }

    /**
     * Adjust stock
     */
    public function adjustStock(int $id, float $quantity, string $type, ?string $reason = null): RawMaterial
    {
        return DB::transaction(function () use ($id, $quantity, $type, $reason) {
            $material = $this->findByIdOrFail($id);

            if ($type === 'add') {
                $material->increment('quantity', $quantity);
            } else {
                $material->decrement('quantity', $quantity);
            }

            $this->logAction('Stock adjusted', [
                'id' => $id,
                'type' => $type,
                'quantity' => $quantity,
                'reason' => $reason,
            ]);

            return $material->fresh();
        });
    }
}
