<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\ServiceSheet;
use App\Models\ServiceSheetItem;
use App\Models\BusinessSetting;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class ServiceSheetController extends Controller
{
    /**
     * Lista todas as fichas de serviço do usuário
     */
    public function index(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        
        $query = ServiceSheet::ofUser($userId)
            ->with(['items', 'businessSetting:id,name,currency,markup_factor,fixed_expenses,employees_count,hours_per_week,working_days_per_week,working_days_per_month,productivity_rate']);
        
        // Filtro por categoria
        if ($request->has('category')) {
            $query->where('category', $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(), [
                'cost_breakdown' => $sheet->cost_breakdown,
            ]);
        });
        
        return response()->json($sheets);
    }

    /**
     * Cria uma nova ficha de serviço
     */
    public function store(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'code' => 'nullable|string|max:100',
            'description' => 'nullable|string',
            'category' => 'nullable|string|max:100',
            'business_setting_id' => 'required|exists:business_settings,id',
            'duration_minutes' => 'required|numeric|min:1',
            'items' => 'nullable|array',
            'items.*.name' => 'required|string|max:255',
            'items.*.type' => 'required|in:supply,consumable,material,equipment_usage,other',
            'items.*.unit_cost' => 'required|numeric|min:0',
            'items.*.quantity_used' => 'nullable|numeric|min:0',
            'items.*.unit' => 'nullable|string|max:20',
            // 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',
            'pricing_strategy' => 'nullable|in:aggressive,neutral,premium',
            'psychological_pricing' => 'nullable|boolean',
            'target_margin' => 'nullable|numeric|min:0|max:99',
        ]);

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

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

        // Verificar se a configuração suporta serviços
        if ($setting->business_type === 'products') {
            return response()->json(['message' => 'Esta configuração é apenas para produtos. Altere para "Serviços" ou "Ambos".'], 422);
        }

        DB::beginTransaction();
        
        try {
            // Criar a ficha de serviço
            $sheet = ServiceSheet::create([
                'user_id' => $userId,
                'business_setting_id' => $request->business_setting_id,
                'name' => $request->name,
                'code' => $request->code,
                'description' => $request->description,
                'category' => $request->category,
                'duration_minutes' => $request->duration_minutes,
                'competitor_price' => $request->competitor_price,
                'min_price' => $request->min_price,
                'max_price' => $request->max_price,
                'premium_multiplier' => $request->premium_multiplier ?? 1,
                'pricing_strategy' => $request->pricing_strategy ?? 'neutral',
                'psychological_pricing' => $request->psychological_pricing ?? false,
                'target_margin' => $request->target_margin,
            ]);

            // Criar os itens (insumos)
            if ($request->has('items') && is_array($request->items)) {
                foreach ($request->items as $itemData) {
                    ServiceSheetItem::create([
                        'service_sheet_id' => $sheet->id,
                        'name' => $itemData['name'],
                        'type' => $itemData['type'],
                        'unit_cost' => $itemData['unit_cost'],
                        'quantity_used' => $itemData['quantity_used'] ?? 1,
                        'unit' => $itemData['unit'] ?? null,
                        'notes' => $itemData['notes'] ?? null,
                    ]);
                }
            }

            // Recalcular tudo
            $sheet->recalculate();

            DB::commit();

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

            return response()->json(array_merge($sheet->toArray(), [
                'cost_breakdown' => $sheet->cost_breakdown,
            ]), 201);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Erro ao criar ficha de serviço: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Exibe uma ficha de serviço específica
     */
    public function show(Request $request, $id): JsonResponse
    {
        $sheet = ServiceSheet::ofUser($request->user()->id)
            ->with(['items', 'businessSetting'])
            ->findOrFail($id);

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

    /**
     * Atualiza uma ficha de serviço
     */
    public function update(Request $request, $id): JsonResponse
    {
        $sheet = ServiceSheet::ofUser($request->user()->id)->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
            'code' => 'nullable|string|max:100',
            'description' => 'nullable|string',
            'category' => 'nullable|string|max:100',
            'business_setting_id' => 'sometimes|exists:business_settings,id',
            'duration_minutes' => 'sometimes|numeric|min:1',
            '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',
            'pricing_strategy' => 'nullable|in:aggressive,neutral,premium',
            'psychological_pricing' => 'nullable|boolean',
            'target_margin' => 'nullable|numeric|min:0|max:99',
        ]);

        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);
            }
            // Verificar se suporta serviços
            if ($setting->business_type === 'products') {
                return response()->json(['message' => 'Esta configuração é apenas para produtos.'], 422);
            }
        }

        $sheet->update($validator->validated());
        
        // Recalcular preços
        $sheet->recalculate();
        
        $sheet->load(['items', 'businessSetting:id,name,currency,markup_factor']);

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

    /**
     * Remove uma ficha de serviço
     */
    public function destroy(Request $request, $id): JsonResponse
    {
        $sheet = ServiceSheet::ofUser($request->user()->id)->findOrFail($id);
        $sheet->delete();

        return response()->json(['message' => 'Ficha de serviço excluída com sucesso']);
    }

    /**
     * Adiciona um item à ficha de serviço
     */
    public function addItem(Request $request, $id): JsonResponse
    {
        $sheet = ServiceSheet::ofUser($request->user()->id)->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'type' => 'required|in:supply,consumable,material,equipment_usage,other',
            'unit_cost' => 'required|numeric|min:0',
            'quantity_used' => 'nullable|numeric|min:0',
            'unit' => 'nullable|string|max:20',
            'notes' => 'nullable|string',
        ]);

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

        ServiceSheetItem::create([
            'service_sheet_id' => $sheet->id,
            'name' => $request->name,
            'type' => $request->type,
            'unit_cost' => $request->unit_cost,
            'quantity_used' => $request->quantity_used ?? 1,
            'unit' => $request->unit,
            'notes' => $request->notes,
        ]);

        // Recalcular preço
        $sheet->recalculate();

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

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

    /**
     * Atualiza um item da ficha de serviço
     */
    public function updateItem(Request $request, $sheetId, $itemId): JsonResponse
    {
        $sheet = ServiceSheet::ofUser($request->user()->id)->findOrFail($sheetId);
        $item = ServiceSheetItem::where('service_sheet_id', $sheet->id)->findOrFail($itemId);

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
            'type' => 'sometimes|in:supply,consumable,material,equipment_usage,other',
            'unit_cost' => 'sometimes|numeric|min:0',
            'quantity_used' => 'sometimes|numeric|min:0',
            'unit' => 'nullable|string|max:20',
            'notes' => 'nullable|string',
        ]);

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

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

        // Recalcular preço
        $sheet->recalculate();

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

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

    /**
     * Remove um item da ficha de serviço
     */
    public function removeItem(Request $request, $sheetId, $itemId): JsonResponse
    {
        $sheet = ServiceSheet::ofUser($request->user()->id)->findOrFail($sheetId);
        $item = ServiceSheetItem::where('service_sheet_id', $sheet->id)->findOrFail($itemId);
        
        $item->delete();

        // Recalcular preço
        $sheet->recalculate();

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

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

    /**
     * Lista as categorias de serviços do usuário
     */
    public function categories(Request $request): JsonResponse
    {
        $categories = ServiceSheet::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(ServiceSheetItem::TYPES);
    }

    /**
     * Duplica uma ficha de serviço
     */
    public function duplicate(Request $request, $id): JsonResponse
    {
        $sheet = ServiceSheet::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->service_sheet_id = $newSheet->id;
                $newItem->save();
            }

            // Recalcular
            $newSheet->recalculate();

            DB::commit();

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

            return response()->json(array_merge($newSheet->toArray(), [
                'cost_breakdown' => $newSheet->cost_breakdown,
            ]), 201);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Erro ao duplicar ficha de serviço: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Simula o preço de um serviço (para calculadora)
     */
    public function simulate(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'business_setting_id' => 'required|exists:business_settings,id',
            'duration_minutes' => 'required|numeric|min:1',
            'csv' => 'required|numeric|min:0',
        ]);

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

        $setting = BusinessSetting::ofUser($request->user()->id)->findOrFail($request->business_setting_id);
        
        $price = $setting->calculateServicePrice(
            (float) $request->duration_minutes,
            (float) $request->csv
        );
        
        // Calcular breakdown
        $fixedCostPortion = $setting->fixed_cost_per_minute * $request->duration_minutes;
        $baseCost = $fixedCostPortion + $request->csv;
        $markup = $setting->markup_factor ?? $setting->calculateMarkup();
        
        $priceWithoutVat = $baseCost * $markup;
        $vatAmount = 0;
        
        if ($setting->price_includes_tax) {
            $vatAmount = $price - $priceWithoutVat;
        }

        return response()->json([
            'duration_minutes' => (float) $request->duration_minutes,
            'duration_hours' => round($request->duration_minutes / 60, 2),
            'csv' => (float) $request->csv,
            'fixed_cost_per_hour' => $setting->fixed_cost_per_hour,
            'fixed_cost_portion' => round($fixedCostPortion, 2),
            'base_cost' => round($baseCost, 2),
            'markup' => $markup,
            'price_without_vat' => round($priceWithoutVat, 2),
            'vat_rate' => $setting->price_includes_tax ? (float) $setting->vat_rate : 0,
            'vat_amount' => round($vatAmount, 2),
            'final_price' => $price,
            'productive_hours' => $setting->productive_hours,
        ]);
    }
}
