<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\ProductSheet;
use App\Models\ProductSheetItem;
use App\Models\ProductVariant;
use App\Models\BusinessSetting;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class ProductSheetController extends Controller
{
    /**
     * Lista todas as fichas técnicas do usuário
     */
    public function index(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        
        $query = ProductSheet::ofUser($userId)
            ->with(['items', 'variants', 'businessSetting:id,name,currency,markup_factor']);
        
        // Filtro por categoria
        if ($request->has('category')) {
            $query->byCategory($request->category);
        }
        
        // Filtro por status
        if ($request->has('active')) {
            $query->where('is_active', $request->boolean('active'));
        }
        
        // Ordenação
        $sortBy = $request->get('sort_by', 'name');
        $sortDir = $request->get('sort_dir', 'asc');
        $query->orderBy($sortBy, $sortDir);
        
        $sheets = $query->get()->map(function ($sheet) {
            return array_merge($sheet->toArray(), [
                'contribution_margin_percent' => $sheet->contribution_margin_percent,
                'competitor_comparison' => $sheet->competitor_comparison,
            ]);
        });
        
        return response()->json($sheets);
    }

    /**
     * Cria uma nova ficha técnica
     */
    public function store(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'sku' => 'nullable|string|max:100',
            'description' => 'nullable|string',
            'category' => 'nullable|string|max:100',
            'base_volume_ml' => 'nullable|integer|min:1',
            'standard_portion_ml' => 'nullable|integer|min:1',
            'currency' => 'required|string|size:3',
            'business_setting_id' => 'nullable|exists:business_settings,id',
            'items' => 'nullable|array',
            'items.*.name' => 'required|string|max:255',
            'items.*.type' => 'required|in:product_cost,packaging,label,shipping,handling,other',
            'items.*.amount' => 'required|numeric|min:0',
            'items.*.quantity' => 'nullable|numeric|min:0',
            'items.*.unit' => 'nullable|string|max:20',
            'variants' => 'nullable|array',
            'variants.*.name' => 'required|string|max:255',
            'variants.*.portion_ratio' => 'required|numeric|min:0|max:1',
            'variants.*.quantity_per_unit' => 'nullable|numeric|min:0',
            'variants.*.volume_ml' => 'nullable|integer|min:1',
            'variants.*.markup' => 'nullable|numeric|min:1',
            'variants.*.is_default' => 'nullable|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $userId = $request->user()->id;
        
        // Verificar se business_setting_id pertence ao usuário
        if ($request->business_setting_id) {
            $setting = BusinessSetting::ofUser($userId)->find($request->business_setting_id);
            if (!$setting) {
                return response()->json(['message' => 'Configuração de negócio não encontrada'], 404);
            }
        }

        DB::beginTransaction();
        
        try {
            // Criar a ficha técnica
            $sheet = ProductSheet::create([
                'user_id' => $userId,
                'business_setting_id' => $request->business_setting_id,
                'name' => $request->name,
                'sku' => $request->sku,
                'description' => $request->description,
                'category' => $request->category,
                'base_volume_ml' => $request->base_volume_ml,
                'standard_portion_ml' => $request->standard_portion_ml,
                'currency' => $request->currency,
            ]);

            // Criar os itens
            if ($request->has('items') && is_array($request->items)) {
                foreach ($request->items as $index => $itemData) {
                    ProductSheetItem::create([
                        'product_sheet_id' => $sheet->id,
                        'name' => $itemData['name'],
                        'type' => $itemData['type'],
                        'amount' => $itemData['amount'],
                        'quantity' => $itemData['quantity'] ?? 1,
                        'unit' => $itemData['unit'] ?? null,
                        'sort_order' => $index,
                    ]);
                }
            }

            // Recalcular CMV
            $sheet->recalculateCmv();
            
            // Calcular preço de venda se tiver configuração
            if ($sheet->business_setting_id) {
                $sheet->calculateSalePrice();
            }

            // Criar as variantes
            if ($request->has('variants') && is_array($request->variants)) {
                $markup = $sheet->markup_used ?? $sheet->businessSetting?->markup_factor ?? 2.5;
                
                foreach ($request->variants as $index => $variantData) {
                    $variant = new ProductVariant([
                        'product_sheet_id' => $sheet->id,
                        'name' => $variantData['name'],
                        'portion_ratio' => $variantData['portion_ratio'],
                        'quantity_per_unit' => $variantData['quantity_per_unit'] ?? null,
                        'volume_ml' => $variantData['volume_ml'] ?? null,
                        'markup' => $variantData['markup'] ?? $markup,
                        'is_default' => $variantData['is_default'] ?? ($index === 0),
                        'sort_order' => $index,
                    ]);
                    $variant->productSheet = $sheet;
                    $variant->recalculate($variantData['markup'] ?? $markup);
                    $variant->save();
                }
            }

            DB::commit();

            // Recarregar com relacionamentos
            $sheet->load(['items', 'variants', 'businessSetting:id,name,currency,markup_factor']);

            return response()->json(array_merge($sheet->toArray(), [
                'contribution_margin_percent' => $sheet->contribution_margin_percent,
            ]), 201);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Erro ao criar ficha técnica: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Exibe uma ficha técnica específica
     */
    public function show(Request $request, $id): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)
            ->with(['items', 'variants', 'businessSetting'])
            ->findOrFail($id);

        return response()->json(array_merge($sheet->toArray(), [
            'contribution_margin_percent' => $sheet->contribution_margin_percent,
        ]));
    }

    /**
     * Atualiza uma ficha técnica
     */
    public function update(Request $request, $id): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
            'sku' => 'nullable|string|max:100',
            'description' => 'nullable|string',
            'category' => 'nullable|string|max:100',
            'base_volume_ml' => 'nullable|integer|min:1',
            'standard_portion_ml' => 'nullable|integer|min:1',
            'currency' => 'sometimes|string|size:3',
            'business_setting_id' => 'nullable|exists:business_settings,id',
            'is_active' => 'sometimes|boolean',
            // Strategic pricing fields
            'competitor_price' => 'nullable|numeric|min:0',
            'min_price' => 'nullable|numeric|min:0',
            'max_price' => 'nullable|numeric|min:0',
            'premium_multiplier' => 'nullable|numeric|min:0.1|max:5',
            'price_strategy' => 'nullable|in:aggressive,neutral,premium',
            'psychological_rounding' => 'nullable|boolean',
            'target_margin_percent' => 'nullable|numeric|min:0|max:99',
            // Variants
            'variants' => 'nullable|array',
            'variants.*.id' => 'nullable|integer',
            'variants.*.name' => 'required|string|max:255',
            'variants.*.portion_ratio' => 'required|numeric|min:0|max:1',
            'variants.*.quantity_per_unit' => 'nullable|numeric|min:0',
            'variants.*.volume_ml' => 'nullable|integer|min:1',
            'variants.*.markup' => 'nullable|numeric|min:1',
            'variants.*.is_default' => 'nullable|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        // Verificar se business_setting_id pertence ao usuário
        if ($request->has('business_setting_id') && $request->business_setting_id) {
            $setting = BusinessSetting::ofUser($request->user()->id)->find($request->business_setting_id);
            if (!$setting) {
                return response()->json(['message' => 'Configuração de negócio não encontrada'], 404);
            }
        }

        $sheet->update($validator->validated());
        
        // Recalcular preço se mudou a configuração
        if ($request->has('business_setting_id') && $sheet->business_setting_id) {
            $sheet->calculateSalePrice();
        }
        
        // Calcular preço final com estratégias
        $sheet->calculateFinalPrice();
        
        // Atualizar variantes
        if ($request->has('variants') && is_array($request->variants)) {
            $markup = $sheet->markup_used ?? $sheet->businessSetting?->markup_factor ?? 2.5;
            $existingIds = [];
            
            foreach ($request->variants as $index => $variantData) {
                if (!empty($variantData['id'])) {
                    // Atualizar variante existente
                    $variant = ProductVariant::where('product_sheet_id', $sheet->id)
                        ->find($variantData['id']);
                    if ($variant) {
                        $variant->update([
                            'name' => $variantData['name'],
                            'portion_ratio' => $variantData['portion_ratio'],
                            'quantity_per_unit' => $variantData['quantity_per_unit'] ?? null,
                            'volume_ml' => $variantData['volume_ml'] ?? null,
                            'markup' => $variantData['markup'] ?? $markup,
                            'is_default' => $variantData['is_default'] ?? false,
                            'sort_order' => $index,
                        ]);
                        $variant->recalculate($variantData['markup'] ?? $markup);
                        $variant->save();
                        $existingIds[] = $variant->id;
                    }
                } else {
                    // Criar nova variante
                    $variant = new ProductVariant([
                        'product_sheet_id' => $sheet->id,
                        'name' => $variantData['name'],
                        'portion_ratio' => $variantData['portion_ratio'],
                        'quantity_per_unit' => $variantData['quantity_per_unit'] ?? null,
                        'volume_ml' => $variantData['volume_ml'] ?? null,
                        'markup' => $variantData['markup'] ?? $markup,
                        'is_default' => $variantData['is_default'] ?? false,
                        'sort_order' => $index,
                    ]);
                    $variant->productSheet = $sheet;
                    $variant->recalculate($variantData['markup'] ?? $markup);
                    $variant->save();
                    $existingIds[] = $variant->id;
                }
            }
            
            // Remover variantes que não estão na lista
            ProductVariant::where('product_sheet_id', $sheet->id)
                ->whereNotIn('id', $existingIds)
                ->delete();
        }
        
        $sheet->load(['items', 'variants', 'businessSetting:id,name,currency,markup_factor']);

        return response()->json(array_merge($sheet->toArray(), [
            'contribution_margin_percent' => $sheet->contribution_margin_percent,
            'competitor_comparison' => $sheet->competitor_comparison,
        ]));
    }

    /**
     * Remove uma ficha técnica
     */
    public function destroy(Request $request, $id): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)->findOrFail($id);
        $sheet->delete();

        return response()->json(['message' => 'Ficha técnica excluída com sucesso']);
    }

    /**
     * Adiciona um item à ficha técnica
     */
    public function addItem(Request $request, $id): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'type' => 'required|in:product_cost,packaging,label,shipping,handling,other',
            'amount' => 'required|numeric|min:0',
            'quantity' => 'nullable|numeric|min:0',
            'unit' => 'nullable|string|max:20',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $maxOrder = $sheet->items()->max('sort_order') ?? -1;

        $item = ProductSheetItem::create([
            'product_sheet_id' => $sheet->id,
            'name' => $request->name,
            'type' => $request->type,
            'amount' => $request->amount,
            'quantity' => $request->quantity ?? 1,
            'unit' => $request->unit,
            'sort_order' => $maxOrder + 1,
        ]);

        // Recalcular preço de venda
        if ($sheet->business_setting_id) {
            $sheet->calculateSalePrice();
        }

        $sheet->load(['items', 'businessSetting:id,name,currency,markup_factor']);

        return response()->json(array_merge($sheet->toArray(), [
            'contribution_margin_percent' => $sheet->contribution_margin_percent,
        ]));
    }

    /**
     * Atualiza um item da ficha técnica
     */
    public function updateItem(Request $request, $sheetId, $itemId): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)->findOrFail($sheetId);
        $item = ProductSheetItem::where('product_sheet_id', $sheet->id)->findOrFail($itemId);

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
            'type' => 'sometimes|in:product_cost,packaging,label,shipping,handling,other',
            'amount' => 'sometimes|numeric|min:0',
            'quantity' => 'sometimes|numeric|min:0',
            'unit' => 'nullable|string|max:20',
            'sort_order' => 'sometimes|integer|min:0',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $item->update($validator->validated());

        // Recalcular preço de venda
        if ($sheet->business_setting_id) {
            $sheet->calculateSalePrice();
        }

        $sheet->load(['items', 'businessSetting:id,name,currency,markup_factor']);

        return response()->json(array_merge($sheet->toArray(), [
            'contribution_margin_percent' => $sheet->contribution_margin_percent,
        ]));
    }

    /**
     * Remove um item da ficha técnica
     */
    public function removeItem(Request $request, $sheetId, $itemId): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)->findOrFail($sheetId);
        $item = ProductSheetItem::where('product_sheet_id', $sheet->id)->findOrFail($itemId);
        
        $item->delete();

        // Recalcular preço de venda
        if ($sheet->business_setting_id) {
            $sheet->calculateSalePrice();
        }

        $sheet->load(['items', 'businessSetting:id,name,currency,markup_factor']);

        return response()->json(array_merge($sheet->toArray(), [
            'contribution_margin_percent' => $sheet->contribution_margin_percent,
        ]));
    }

    /**
     * Recalcula o preço de venda de uma ficha
     */
    public function recalculatePrice(Request $request, $id): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)->findOrFail($id);

        // Pode usar uma configuração diferente
        $settingId = $request->business_setting_id;
        $setting = null;
        
        if ($settingId) {
            $setting = BusinessSetting::ofUser($request->user()->id)->findOrFail($settingId);
        } elseif ($sheet->business_setting_id) {
            $setting = $sheet->businessSetting;
        }

        if (!$setting) {
            return response()->json(['message' => 'Nenhuma configuração de negócio disponível'], 422);
        }

        $salePrice = $sheet->calculateSalePrice($setting);
        
        $sheet->load(['items', 'businessSetting:id,name,currency,markup_factor']);

        return response()->json(array_merge($sheet->toArray(), [
            'contribution_margin_percent' => $sheet->contribution_margin_percent,
        ]));
    }

    /**
     * Lista as categorias de produtos do usuário
     */
    public function categories(Request $request): JsonResponse
    {
        $categories = ProductSheet::ofUser($request->user()->id)
            ->whereNotNull('category')
            ->distinct()
            ->pluck('category');

        return response()->json($categories);
    }

    /**
     * Lista os tipos de componentes disponíveis
     */
    public function itemTypes(): JsonResponse
    {
        return response()->json(ProductSheetItem::getTypes());
    }

    /**
     * Duplica uma ficha técnica
     */
    public function duplicate(Request $request, $id): JsonResponse
    {
        $sheet = ProductSheet::ofUser($request->user()->id)
            ->with('items')
            ->findOrFail($id);

        DB::beginTransaction();
        
        try {
            // Criar cópia da ficha
            $newSheet = $sheet->replicate();
            $newSheet->name = $sheet->name . ' (cópia)';
            $newSheet->save();

            // Copiar os itens
            foreach ($sheet->items as $item) {
                $newItem = $item->replicate();
                $newItem->product_sheet_id = $newSheet->id;
                $newItem->save();
            }

            // Recalcular
            $newSheet->recalculateCmv();
            if ($newSheet->business_setting_id) {
                $newSheet->calculateSalePrice();
            }

            DB::commit();

            $newSheet->load(['items', 'businessSetting:id,name,currency,markup_factor']);

            return response()->json(array_merge($newSheet->toArray(), [
                'contribution_margin_percent' => $newSheet->contribution_margin_percent,
            ]), 201);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Erro ao duplicar ficha técnica: ' . $e->getMessage()], 500);
        }
    }
}
