<?php

namespace App\Services;

use App\Models\Branch;
use App\Repositories\Eloquent\ProductRepository;
use App\Repositories\Eloquent\BranchProductRepository;
use Illuminate\Support\Str;

class ProductService
{
    public function __construct(
        protected ProductRepository $productRepository,
        protected BranchProductRepository $branchProductRepository,
        protected LoggingService $loggingService
    ) {}

    public function getAll()
    {
        $this->loggingService->logInfo('Fetching all products');
        return $this->productRepository->all();
    }

    public function getActive()
    {
        $this->loggingService->logInfo('Fetching active products');
        return $this->productRepository->getActive();
    }

    public function getByCategory(int $categoryId)
    {
        $this->loggingService->logInfo('Fetching products by category', ['category_id' => $categoryId]);
        return $this->productRepository->getByCategory($categoryId);
    }

    public function find(int $id)
    {
        $this->loggingService->logInfo('Finding product', ['id' => $id]);
        return $this->productRepository->find($id);
    }

    public function findWithRelations(int $id)
    {
        $this->loggingService->logInfo('Finding product with relations', ['id' => $id]);
        return $this->productRepository->getWithRelations($id);
    }

    public function findBySlug(string $slug)
    {
        $this->loggingService->logInfo('Finding product by slug', ['slug' => $slug]);
        return $this->productRepository->findBySlug($slug);
    }

    public function create(array $data)
    {
        $this->loggingService->logInfo('Creating product', ['data' => $data]);

        $data['slug'] = $data['slug'] ?? Str::slug($data['name']);
        $data['base_price'] = $data['base_price'] ?? 0;

        $optionSetIds = $data['option_set_ids'] ?? [];
        $innerOptionSetIds = $data['inner_option_set_ids'] ?? [];

        unset($data['option_set_ids'], $data['inner_option_set_ids']);

        $product = $this->productRepository->create($data);

        if (!empty($optionSetIds)) {
            $this->productRepository->syncOptionSets($product->id, $optionSetIds);
        }

        if (!empty($innerOptionSetIds)) {
            $this->productRepository->syncInnerOptionSets($product->id, $innerOptionSetIds);
        }

        // Auto-assign product to all active branches
        $activeBranches = Branch::where('is_active', true)->get();
        foreach ($activeBranches as $branch) {
            $this->branchProductRepository->updateOrCreateForBranch(
                $branch->id,
                $product->id,
                ['is_available' => true]
            );
        }

        $this->loggingService->logInfo('Product auto-assigned to all branches', [
            'product_id' => $product->id,
            'branch_count' => $activeBranches->count()
        ]);

        return $product->fresh(['optionSets', 'innerOptionSets', 'category']);
    }

    public function update(int $id, array $data)
    {
        $this->loggingService->logInfo('Updating product', ['id' => $id, 'data' => $data]);

        if (isset($data['name']) && !isset($data['slug'])) {
            $data['slug'] = Str::slug($data['name']);
        }

        $optionSetIds = $data['option_set_ids'] ?? null;
        $innerOptionSetIds = $data['inner_option_set_ids'] ?? null;

        unset($data['option_set_ids'], $data['inner_option_set_ids']);

        $product = $this->productRepository->update($id, $data);

        if ($optionSetIds !== null) {
            $this->productRepository->syncOptionSets($id, $optionSetIds);
        }

        if ($innerOptionSetIds !== null) {
            $this->productRepository->syncInnerOptionSets($id, $innerOptionSetIds);
        }

        return $product->fresh(['optionSets', 'innerOptionSets', 'category']);
    }

    public function delete(int $id)
    {
        $this->loggingService->logInfo('Deleting product', ['id' => $id]);
        return $this->productRepository->delete($id);
    }

    public function getForBranch(int $branchId)
    {
        $this->loggingService->logInfo('Fetching products for branch', ['branch_id' => $branchId]);
        return $this->productRepository->getForBranch($branchId);
    }

    public function assignToBranch(int $branchId, int $productId, array $data = [])
    {
        $this->loggingService->logInfo('Assigning product to branch', [
            'branch_id' => $branchId,
            'product_id' => $productId,
            'data' => $data
        ]);

        return $this->branchProductRepository->updateOrCreateForBranch($branchId, $productId, array_merge([
            'is_available' => true,
        ], $data));
    }

    public function updateBranchProduct(int $branchId, int $productId, array $data)
    {
        $this->loggingService->logInfo('Updating branch product', [
            'branch_id' => $branchId,
            'product_id' => $productId,
            'data' => $data
        ]);

        return $this->branchProductRepository->updateOrCreateForBranch($branchId, $productId, $data);
    }

    public function bulkAssignToBranch(int $branchId, array $productIds)
    {
        $this->loggingService->logInfo('Bulk assigning products to branch', [
            'branch_id' => $branchId,
            'product_ids' => $productIds
        ]);

        foreach ($productIds as $productId) {
            $this->branchProductRepository->updateOrCreateForBranch($branchId, $productId, [
                'is_available' => true
            ]);
        }

        return $this->branchProductRepository->getByBranch($branchId);
    }
}
