<?php

namespace App\Services;

use App\Models\ProductAttribute;
use App\Models\Store;
use App\Models\UserType;
use App\Models\RelationTypeAttribute;
use App\Models\RelationProductAttribute;
use App\Models\ProductDetail;
use App\Traits\HasResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class ProductAttributeService
{
    use HasResponse;

    public function list($params, $withPagination)
    {
        $productAttributes = ProductAttribute::where('status', '!=', 2)->orderBy('id', 'desc');

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

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

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

    public function listByCompany($params, $withPagination)
{
    // Incluir las relaciones con tipo, padres e hijos
    $productAttributes = ProductAttribute::with(['type', 'parentAttributes', 'childAttributes'])
        ->where('status', '!=', 2)
        ->orderBy('id', 'desc');

    // Filtrar por compañía
    $idcompany = isset($params['idcompany']) ? $params['idcompany'] : '';
    if ($idcompany) {
        $productAttributes->where(function ($query) use ($idcompany) {
            $query->where('idcompany', $idcompany);
        });
    }

    // Filtrar por búsqueda (nombre)
    $search = isset($params['search']) ? $params['search'] : '';
    if ($search) {
        $productAttributes->where(function ($query) use ($search) {
            $query->where('name', 'like', "%$search%");
        });
    }

    // Paginación o consulta completa
    $productAttributes = !empty($withPagination)
        ? $productAttributes->paginate($withPagination['perPage'], page: $withPagination['page'])
        : $productAttributes->get();

    // Mapear los atributos de producto y sus relaciones
    $productAttributes = $productAttributes->map(function ($attribute) {
        return [
            'id' => $attribute->id,
            'code' => $attribute->code,
            'name' => $attribute->name,
            'description' => $attribute->description,
            'idtype' => $attribute->idtype,
            'type_name' => $attribute->type ? $attribute->type->name : null,
            'status' => $attribute->status,
            'createdby' => $attribute->createdby,
            'idcompany' => $attribute->idcompany,
            // Incluir las relaciones de padres e hijos
            'parent_attributes' => $attribute->parentAttributes->map(function ($parent) {
                return [
                    'parent_id' => $parent->id,
                    'parent_name' => $parent->name,
                ];
            }),
            'child_attributes' => $attribute->childAttributes->map(function ($child) {
                return [
                    'child_id' => $child->id,
                    'child_name' => $child->name,
                ];
            })
        ];
    });

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

    

    public function register($params)
    {
        DB::beginTransaction();
        try {
            
            $nameExisting = ProductAttribute::where('name', $params['name'])->where('idcompany', $params['idcompany'])->where('status', 1)->first();
            if ($nameExisting) return $this->errorResponse('El nombre ya se encuentra registrado.', 400);

            $codeExisting = ProductAttribute::where('code', $params['code'])->where('idcompany', $params['idcompany'])->where('status', 1)->first();
            if ($codeExisting) return $this->errorResponse('El código ya se encuentra registrado.', 400);

            $usersession = Auth::user();

            $productAttribute = ProductAttribute::create([
                'code' => $params['code'],
                'name' => $params['name'],
                'description' => $params['description'],
                'idtype' => $params['idtype'],
                'idspecificattributes' => $params['idspecificattributes'],
                'createdby' => $usersession->id,
                'status' => isset($params['status']) ? $params['status'] : 1,
                'idcompany' => $params['idcompany'],
            ]);
            $productAttribute->save();

            DB::commit();
            return $this->successResponse('Atributo de producto creado satisfactoriamente.', $productAttribute);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la creación de un Atributo.', $th->getMessage());
        }
    }

    public function dataOptimizated($params) 
    {
        DB::beginTransaction();
        try {
            $data  = $params['data'];
            $idcompany = $params['idcompany'];
            $idtype = $params['idtype'];
            $usersession = Auth::user();
        
            # Recopilar los nombres de las categorías a crear
            $categoryNames = array_column($data, 'name');
        
            # Buscar las categorías que ya existen en la base de datos
            $existingAttributes = ProductAttribute::where('idcompany', $idcompany)
                ->whereIn('name', $categoryNames)
                ->where('status', 1)
                ->pluck('name', 'id')  // Guardamos el 'id' junto con el 'name'
                ->toArray();
        
            # Filtrar solo las categorías que no existen en la base de datos
            $newData = array_filter($data, function ($item) use ($existingAttributes) {
                return !in_array($item['name'], array_keys($existingAttributes));
            });
        
            # Preparar los datos para la inserción masiva
            $insertData = [];
            foreach ($newData as $item) {
                $name = $item['name'];
                $insertData[] = [
                    'code' => $name,
                    'name' => $name,
                    'description' => $name,
                    'createdby' => $usersession->id,
                    'idreference' => $item['idreference'],
                    'idcompany' => $idcompany,
                    'idtype' => $idtype,
                ];
            }
        
            // Realizar la inserción masiva si hay datos nuevos
            if (!empty($insertData)) {
                ProductAttribute::insert($insertData); // Insertar en masa
    
                # Obtener los IDs de los nuevos atributos insertados
                $newAttributes = ProductAttribute::where('idcompany', $idcompany)
                    ->whereIn('name', array_column($newData, 'name'))
                    ->pluck('id', 'name')
                    ->toArray();
    
                # Crear relaciones entre padres e hijos
                $dataRelation = [];
                $relationAttributes = [];  // Para almacenar los IDs de RelationProductAttribute
                foreach ($newData as $item) {
                    // Verificar si el parent_attribute_id existe antes de crear la relación
                    if (!empty($item['idparent']) && isset($newAttributes[$item['name']])) {
                        $parentExists = ProductAttribute::where('id', $item['idparent'])->exists(); // Verificar si el idparent existe
        
                        if ($parentExists) {
                            $dataRelation[] = [
                                'parent_attribute_id' => $item['idparent'],  // id del padre proporcionado
                                'child_attribute_id' => $newAttributes[$item['name']],  // id del atributo recién creado
                                'idcompany' => $idcompany,
                            ];
                        }
                    }
                }
    
                # Insertar relaciones en la tabla RelationProductAttribute y obtener los IDs
                if (!empty($dataRelation)) {
                    RelationProductAttribute::insert($dataRelation);
    
                    # Obtener los IDs de las relaciones insertadas
                    $relationAttributes = RelationProductAttribute::where('idcompany', $idcompany)
                        ->whereIn('child_attribute_id', array_values($newAttributes))
                        ->pluck('id', 'child_attribute_id')  // Pluck para obtener los IDs de las relaciones
                        ->toArray();
                }
    
                # Insertar en ProductDetail
                $productDetailsData = [];
                foreach ($newData as $item) {
                    if (isset($item['products']) && !empty($item['products'])) {
                        foreach ($item['products'] as $product) {
                            if (isset($relationAttributes[$newAttributes[$item['name']]])) {
                                $productDetailsData[] = [
                                    'product_id' => $product['id'],  // ID del producto
                                    'relation_product_attribute_id' => $relationAttributes[$newAttributes[$item['name']]],
                                    'idcompany' => $idcompany
                                ];
                            }
                        }
                    }
                }
    
                if (!empty($productDetailsData)) {
                    ProductDetail::insert($productDetailsData);  // Insertar en la tabla ProductDetail
                }
            }
    
            DB::commit();
            return $this->successResponse('Data optimizada.');
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('Ocurrió un problema durante la optimización.', $th->getMessage());
        }
    }
    

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

            $nameExisting = ProductAttribute::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);

            $codeExisting = ProductAttribute::where('code', $params['code'])->where('id','!=', $id)->where('idcompany', $params['idcompany'])->where('status', 1)->first();
            if ($codeExisting) return $this->errorResponse('El código ya se encuentra registrado.', 400);

            $productAttribute = ProductAttribute::find($id);
            $productAttribute->code = $params['code'];
            $productAttribute->name = $params['name'];
            $productAttribute->description = $params['description'];
            $productAttribute->idtype = $params['idtype'];
            $productAttribute->idspecificattributes = $params['idspecificattributes'];
            $productAttribute->save();

            DB::commit();
            return $this->successResponse('Atributo de producto actualizado satisfactoriamente.', $productAttribute);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la actualización de un Atributo.', $th->getMessage());
        }
    }

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

            if($params['status'] == '2') return $this->successResponse('Solo se puede habilitar o deshabilitar.');

            $productAttribute = ProductAttribute::find($id);
            $productAttribute->status = $params['status'];
            $productAttribute->save();

            DB::commit();
            return $this->successResponse('Estado actualizado satisfactoriamente.', $productAttribute);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la actualización de un Atributo.', $th->getMessage());
        }
    }

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

            $productAttribute = ProductAttribute::find($id);
            $productAttribute->status = 2;
            $productAttribute->save();

            DB::commit();
            return $this->successResponse('Atributo de producto eliminado satisfactoriamente.', $productAttribute);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la eliminación de un Atributo.', $th->getMessage());
        }
    }

    private function verifyAttribute($idattribute)
    {
        $productAttribute = ProductAttribute::where('id', $idattribute)->first();
        if (!$productAttribute) return $this->errorResponse('No se encontró el atributo.', 400);

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