<?php

namespace App\Services;

use App\Http\Resources\CategoryResource;
use App\Models\Category;
use App\Models\Product;
use App\Traits\HasResponse;
use Illuminate\Support\Facades\DB;

class CategoryService
{
    use HasResponse;

    public function list($params, $withPagination)
    {
        $categories = Category::where('status', 1)->orderBy('id', 'desc');

        $search = isset($params['search']) ? $params['search'] : '';
        if($search){
            $categories->where(function ($query) use ($search) {
                $query->where('name', 'like', "%$search%");
            });
        }

        $categories = !empty($withPagination)
            ? $categories->paginate($withPagination['perPage'], page: $withPagination['page'])
            : $categories->get();

        $categories = CategoryResource::collection($categories);

        return $this->successResponse('Lectura exitosa.', $categories);
    }

    public function listByCompany($params, $withPagination)
    {
        $categories = Category::where('status', 1)->orderBy('id', 'desc');

        $idcompany = isset($params['idcompany']) ? $params['idcompany'] : '';
        if($idcompany) {
            $categories->where(function ($query) use ($idcompany) {
                $query->where('idcompany', $idcompany);
            });
        }

        $search = isset($params['search']) ? $params['search'] : '';
        if($search){
            $categories->where(function ($query) use ($search) {
                $query->where('name', 'like', "%$search%");
            });
        }

        $categories = !empty($withPagination)
            ? $categories->paginate($withPagination['perPage'], page: $withPagination['page'])
            : $categories->get();

        $categories = CategoryResource::collection($categories);

        return $this->successResponse('Lectura exitosa.', $categories);
    }

    public function listDuplicated($idcompany)
    {
        $duplicatedCategories = Category::where('idcompany', $idcompany)
            ->groupBy('name', 'idcompany')
            ->select('name', 'idcompany', \Illuminate\Support\Facades\DB::raw('COUNT(*) as total'))
            ->where('status',1) 
            ->having('total', '>', 1)
            ->get();

        return $this->successResponse('Categorias duplicadas.', $duplicatedCategories);
    }

    public function unifyDuplicated($params)
    {
        DB::beginTransaction();
        try {
            $categories  = $params['dataCategory'];
    
            foreach ($categories as $category) {
    
                $name = $category['name'];
                $idcompany = $category['idcompany'];
                $duplicatedCategories = Category::where('name', $name)
                    ->where('idcompany', $idcompany)
                    ->get();
    
                if ($duplicatedCategories->count() > 1) {
                    # Selecciona un ID para mantener activo (el primer ID)
                    $activeCategory = $duplicatedCategories->first();
                    $activeCategoryId = $activeCategory->id;
    
                    # Desactiva todas las otras categorías duplicadas excepto la seleccionada
                    Category::where('name', $name)
                        ->where('idcompany', $idcompany)
                        ->where('id', '!=', $activeCategoryId)
                        ->update(['status' => 2]); 
    
                    # Actualiza los productos que usaban los IDs desactivados
                    Product::whereIn('idcategory', $duplicatedCategories->pluck('id')->toArray())
                        ->update(['idcategory' => $activeCategoryId]);
                }
            }
    
            DB::commit();
            return $this->successResponse('Unificación satisfactoria.');
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('Ocurrió un problema durante la unificación.', $th->getMessage());
        }
    }

    public function reviewData($params)
    {
        $idcompany = $idcompany = $params['idcompany'];
        $categories = Category::where('idcompany', $idcompany)->active()->get();
        $segmentedFamilies = [];
        $usedNames = [];  // Mantener un registro de los nombres que ya han sido utilizados
    
        foreach ($categories as $category) {
            $brands = explode('*', $category->name);
            foreach ($brands as $brand) {
                $cleanedBrand = trim($brand);
                if (!empty($cleanedBrand)) {
                    // Si el nombre ya está en la lista, no lo añadimos de nuevo
                    if (!isset($usedNames[$cleanedBrand])) {
                        $segmentedFamilies[] = [
                            'name' => $cleanedBrand,
                            'idreference' => $category->id,
                            'category_name' => $category->name
                        ];
                        $usedNames[$cleanedBrand] = true;  // Marcamos el nombre como usado
                    }
                }
            }
        }
    
        return $this->successResponse('Familias revisadas.', $segmentedFamilies);
    }
    
    public function listWithProducts($params, $withPagination)
    {
        $categories = Category::where('status', 1)->where('quantity_products', '>', 0)->orderBy('id', 'desc');

        $search = isset($params['search']) ? $params['search'] : '';
        if($search){
            $categories->where(function ($query) use ($search) {
                $query->where('name', 'like', "%$search%");
            });
        }

        $categories = !empty($withPagination)
            ? $categories->paginate($withPagination['perPage'], page: $withPagination['page'])
            : $categories->get();

        return $this->successResponse('Lectura exitosa.', $categories);
    }

    public function register($params)
    {
        DB::beginTransaction();
        try {
            
            $nameExisting = Category::where('name', $params['name'])->where('idcompany', $params['idcompany'])->where('status', 1)->first();
            if ($nameExisting) return $this->errorResponse('El nombre ya se encuentra registrado.', 400);
            
            $category = Category::create([
                'name' => $params['name'],
                'description' => $params['description'],
                'idsubcategories' => $params['idsubcategories'],
                'idcompany' => isset($params['idcompany']) ? $params['idcompany'] : null,
            ]);
            $category->save();

            DB::commit();
            return $this->successResponse('Categoria creada satisfactoriamente.', $category);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la creación de una categoria.', $th->getMessage());
        }
    }

    public function update($id, $params)
    {
        DB::beginTransaction();
        try {
            # Verificar validez de la categoria
            $validate = $this->verifyCategory($id);
            if (!$validate->original['status']) return $validate;

            $nameExisting = Category::where('name', $params['name'])->where('id','!=', $id)->where('idcompany', $params['idcompany'])->where('status', 1)->first();
            if ($nameExisting) return $this->errorResponse('El nombre ya se encuentra registrado.', 400);

            $category = Category::find($id);
            $category->name = $params['name'];
            $category->description = $params['description'];
            $category->idsubcategories = $params['idsubcategories']; 
            $category->save();

            DB::commit();
            return $this->successResponse('Categoria actualizada satisfactoriamente.', $category);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la actualización de una categoria.', $th->getMessage());
        }
    }

    public function delete($id)
    {
        DB::beginTransaction();
        try {
            # Verificar validez de la categoria
            $validate = $this->verifyCategory($id);
            if (!$validate->original['status']) return $validate;

            $category = Category::find($id);
            $category->status = 2;
            $category->save();

            DB::commit();
            return $this->successResponse('Categoria eliminada satisfactoriamente.', $category);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la eliminación de una categoria.', $th->getMessage());
        }
    }

    private function verifyCategory($idcategory)
    {
        $category = Category::where('id', $idcategory)->where('status', 1)->first();
        if (!$category) return $this->errorResponse('No se encontró la categoria.', 400);

        return $this->successResponse('OK');
    }
}
