<?php

namespace App\Http\Controllers;

use App\Models\ManufacturingBOM;
use App\Models\ManufacturingBOMStep;
use App\Models\ManufacturingBOMIngredient;
use App\Models\Account;
use App\Models\CostCenter;
use App\Models\ChartOfAccount;
use App\Models\ManufacturingRun;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Yajra\DataTables\Facades\DataTables;
use Barryvdh\DomPDF\Facade\Pdf;

class ManufacturingBOMController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request): View|JsonResponse
    {
        if ($request->ajax()) {
            $boms = ManufacturingBOM::with(['creator', 'steps', 'ingredients', 'finishedGoods.uom'])
                ->select('manufacturing_boms.*');

            return DataTables::of($boms)
                ->addColumn('total_steps', function ($bom) {
                    return $bom->total_steps;
                })
                ->addColumn('total_ingredients', function ($bom) {
                    return $bom->total_ingredients;
                })
                ->addColumn('creator_name', function ($bom) {
                    return $bom->creator ? $bom->creator->name : 'N/A';
                })
                ->addColumn('finished_goods', function ($bom) {
                    return $bom->finishedGoods ? $bom->finishedGoods->name : 'N/A';
                })
                // ->addColumn('basic_unit_info', function ($bom) {
                //     return $bom->basic_unit_amount ? $bom->basic_unit_amount . ' ' . $bom->basic_unit : 'N/A';
                // })
                ->addColumn('basic_unit_info', function ($bom) {
                $unit = $bom->finishedGoods && $bom->finishedGoods->uom
                    ? $bom->finishedGoods->uom->name // Get from UOM table
                    : '';

                return $bom->basic_unit_amount
                    ? number_format($bom->basic_unit_amount, 2) . ' ' . $unit
                    : ($unit ?: 'N/A');
            })

                ->addColumn('status_badge', function ($bom) {
                    return $bom->is_active
                        ? '<span class="badge badge-success">Active</span>'
                        : '<span class="badge badge-secondary">Inactive</span>';
                })
                ->addColumn('actions', function ($bom) {
                    $actions = '<div class="btn-group" role="group">';
                    $actions .= '<a href="' . route('manufacturing.boms.show', $bom->id) . '" class="btn btn-sm btn-info">View</a>';
                    $actions .= '<a href="' . route('manufacturing.boms.edit', $bom->id) . '" class="btn btn-sm btn-warning">Edit</a>';
                    $actions .= '<form method="POST" action="' . route('manufacturing.boms.destroy', $bom->id) . '" style="display:inline" onsubmit="return confirm(\'Are you sure?\')">';
                    $actions .= csrf_field();
                    $actions .= method_field('DELETE');
                    $actions .= '<button type="submit" class="btn btn-sm btn-danger">Delete</button>';
                    $actions .= '</form>';
                    $actions .= '</div>';
                    return $actions;
                })
                ->rawColumns(['status_badge', 'actions'])
                ->make(true);
        }

        return view('manufacturing.boms.index');
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(): View
    {
        // dd("dd");
        return view('manufacturing.boms.create');
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'description' => 'nullable|string|max:1000',
            'finished_goods_account_id' => 'required|exists:accounts,id',
            'basic_unit_amount' => 'required|numeric|min:0.0001',
            // 'basic_unit' => 'required|string|max:50',
            'ingredients' => 'required|array|min:1',
            'ingredients.*.ingredient_account_id' => 'required|exists:accounts,id',
            'ingredients.*.quantity_required' => 'required|numeric|min:0.0001',
            // 'ingredients.*.unit' => 'required|string|max:50',
            'ingredients.*.wastage_type' => 'required|in:percentage,absolute',
            'ingredients.*.wastage_value' => 'required|numeric|min:0',
        ]);

        // Check if BOM already exists for this finished good
        $existingBom = ManufacturingBOM::where('finished_goods_account_id', $request->finished_goods_account_id)
            ->where('is_active', true)
            ->first();

        if ($existingBom) {
            $finishedGoods = Account::find($request->finished_goods_account_id);
            $finishedGoodsName = $finishedGoods ? $finishedGoods->name : 'Unknown';

            return back()->withInput()
                ->withErrors([
                    'finished_goods_account_id' => "A BOM already exists for '{$finishedGoodsName}'. Only one active BOM is allowed per finished good. Please edit the existing BOM or deactivate it first."
                ]);
        }

        try {
            DB::transaction(function () use ($request) {
                // Get finished goods info for BOM name
                $finishedGoods = Account::find($request->finished_goods_account_id);
                $bomName = $finishedGoods ? $finishedGoods->name . ' BOM' : 'Manufacturing BOM';

                // Create BOM
                $bom = ManufacturingBOM::create([
                    'name' => $bomName,
                    'description' => $request->description,
                    'version' => 1,
                    'is_active' => true,
                    'created_by' => Auth::id(),
                    'finished_goods_account_id' => $request->finished_goods_account_id,
                    'basic_unit_amount' => $request->basic_unit_amount,
                    // 'basic_unit' => $request->basic_unit,
                ]);

                // Add direct ingredients
                if ($request->has('ingredients')) {
                    foreach ($request->ingredients as $ingredientData) {
                        $bom->ingredients()->create([
                            'ingredient_account_id' => $ingredientData['ingredient_account_id'],
                            'quantity_required' => $ingredientData['quantity_required'],
                            // 'unit' => $ingredientData['unit'],
                            'wastage_type' => $ingredientData['wastage_type'],
                            'wastage_value' => $ingredientData['wastage_value'],
                        ]);
                    }
                }
            });

            return redirect()->route('manufacturing.boms.index')
                ->with('success', 'BOM created successfully.');
        } catch (\Exception $e) {
            return back()->withInput()
                ->withErrors(['error' => 'Failed to create BOM: ' . $e->getMessage()]);
        }
    }

    /**
     * Display the specified resource.
     */
        public function show(ManufacturingBOM $manufacturingBom): View
        {
            $manufacturingBom->load(['steps.ingredients.ingredient', 'ingredients.ingredient.uom', 'creator', 'finishedGoods.uom']);

            return view('manufacturing.boms.show', compact('manufacturingBom'));
        }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(ManufacturingBOM $manufacturingBom): View
    {
        $manufacturingBom->load(['steps.ingredients.ingredient', 'ingredients.ingredient']);

        return view('manufacturing.boms.edit', compact('manufacturingBom'));
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, ManufacturingBOM $manufacturingBom): RedirectResponse
    {
        $request->validate([
            'description' => 'nullable|string|max:1000',
            'finished_goods_account_id' => 'required|exists:accounts,id',
            'basic_unit_amount' => 'required|numeric|min:0.0001',
            // 'basic_unit' => 'required|string|max:50',
            'ingredients' => 'required|array|min:1',
            'ingredients.*.ingredient_account_id' => 'required|exists:accounts,id',
            'ingredients.*.quantity_required' => 'required|numeric|min:0.0001',
            // 'ingredients.*.unit' => 'required|string|max:50',
            'ingredients.*.wastage_type' => 'required|in:percentage,absolute',
            'ingredients.*.wastage_value' => 'required|numeric|min:0',
        ]);

        // Check if BOM already exists for this finished good (excluding current BOM)
        $existingBom = ManufacturingBOM::where('finished_goods_account_id', $request->finished_goods_account_id)
            ->where('is_active', true)
            ->where('id', '!=', $manufacturingBom->id)
            ->first();

        if ($existingBom) {
            $finishedGoods = Account::find($request->finished_goods_account_id);
            $finishedGoodsName = $finishedGoods ? $finishedGoods->name : 'Unknown';

            return back()->withInput()
                ->withErrors([
                    'finished_goods_account_id' => "A BOM already exists for '{$finishedGoodsName}'. Only one active BOM is allowed per finished good. Please edit the existing BOM or deactivate it first."
                ]);
        }

        try {
            DB::transaction(function () use ($request, $manufacturingBom) {
                // Get finished goods info for BOM name
                $finishedGoods = Account::find($request->finished_goods_account_id);
                $bomName = $finishedGoods ? $finishedGoods->name . ' BOM' : 'Manufacturing BOM';

                // Update BOM
                $manufacturingBom->update([
                    'name' => $bomName,
                    'description' => $request->description,
                    'finished_goods_account_id' => $request->finished_goods_account_id,
                    'basic_unit_amount' => $request->basic_unit_amount,
                    // 'basic_unit' => $request->basic_unit,
                ]);

                // Delete existing ingredients
                $manufacturingBom->ingredients()->delete();

                // Add updated ingredients
                if ($request->has('ingredients')) {
                    foreach ($request->ingredients as $ingredientData) {
                        $manufacturingBom->ingredients()->create([
                            'ingredient_account_id' => $ingredientData['ingredient_account_id'],
                            'quantity_required' => $ingredientData['quantity_required'],
                            // 'unit' => $ingredientData['unit'],
                            'wastage_type' => $ingredientData['wastage_type'],
                            'wastage_value' => $ingredientData['wastage_value'],
                        ]);
                    }
                }
            });

            return redirect()->route('manufacturing.boms.index')
                ->with('success', 'BOM updated successfully.');
        } catch (\Exception $e) {
            return back()->withInput()
                ->withErrors(['error' => 'Failed to update BOM: ' . $e->getMessage()]);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(ManufacturingBOM $manufacturingBom): RedirectResponse
    {
        try {
            $manufacturingBom->delete();

            return redirect()->route('manufacturing.boms.index')
                ->with('success', 'BOM deleted successfully.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => 'Failed to delete BOM: ' . $e->getMessage()]);
        }
    }

    /**
     * Search finished goods for Select2
     */
    public function searchFinishedGoods(Request $request): JsonResponse
    {
        $search = $request->input('q', '');

        try {
            \Log::info('Searching finished goods with query: ' . $search);

            // First try: Get finished goods accounts (chart_of_account_id = 53 or parent_id = 53)
            $finishedGoods = Account::where('model_type', 'Item')
                ->where('is_shop_item', 0) // Exclude shop items
                ->whereHas('chartOfAccount', function ($query) {
                    $query->where('parent_id', 53);
                })
                ->where('is_active', true)
                ->where(function ($query) use ($search) {
                    $query->where('name', 'like', "%{$search}%")
                          ->orWhere('sku', 'like', "%{$search}%");
                })
                ->limit(10)
                ->get();

            // Fallback: If no results, try direct chart_of_account_id = 53
            if ($finishedGoods->isEmpty()) {
                \Log::info('No results with parent_id=53, trying direct chart_of_account_id=53');
                $finishedGoods = Account::where('model_type', 'Item')
                    ->where('is_shop_item', 0) // Exclude shop items
                    ->where('chart_of_account_id', 53)
                    ->where('is_active', true)
                    ->where(function ($query) use ($search) {
                        $query->where('name', 'like', "%{$search}%")
                              ->orWhere('sku', 'like', "%{$search}%");
                    })
                    ->limit(10)
                    ->get();
            }

            // Another fallback: Search all active items if still no results
            if ($finishedGoods->isEmpty()) {
                \Log::info('No results with chart_of_account_id=53, trying all active items');
                $finishedGoods = Account::where('model_type', 'Item')
                    ->where('is_shop_item', 0) // Exclude shop items
                    ->where('is_active', true)
                    ->where(function ($query) use ($search) {
                        $query->where('name', 'like', "%{$search}%")
                              ->orWhere('sku', 'like', "%{$search}%");
                    })
                    ->limit(10)
                    ->get();
            }

            $results = $finishedGoods->map(function ($item) {
                return [
                    'id' => $item->id,
                    'text' => $item->name . ' (' . $item->sku . ')',
                    'name' => $item->name,
                    'sku' => $item->sku,
                    // 'unit' => $item->unit_of_measure ?? 'pcs',
                    'unit' => optional($item->uom)->name ?? 'pcs',
                    'minimum_output_qty' => 1, // Default value
                ];
            });

            \Log::info('Found ' . $results->count() . ' finished goods');
            return response()->json(['results' => $results]);
        } catch (\Exception $e) {
            \Log::error('Error in searchFinishedGoods: ' . $e->getMessage() . ' at line ' . $e->getLine());
            return response()->json([
                'results' => [],
                'error' => 'Failed to search finished goods'
            ]);
        }
    }

    /**
     * Get all child chart of account IDs recursively
     */
    private function getAllChildChartOfAccountIds($parentId): array
    {
        $ids = [$parentId]; // Include the parent itself

        $children = ChartOfAccount::where('parent_id', $parentId)->pluck('id');

        foreach ($children as $childId) {
            $ids = array_merge($ids, $this->getAllChildChartOfAccountIds($childId));
        }

        return array_unique($ids);
    }

    /**
     * Search raw materials for Select2
     */
    public function searchRawMaterials(Request $request): JsonResponse
    {
        $search = $request->input('q', '');

        // Get raw materials chart of account (Raw Material - 113001)
        $inventoryCoA = ChartOfAccount::where('code', '113001')->first();

        if (!$inventoryCoA) {
            return response()->json(['results' => []]);
        }

        // Get all child chart of accounts under inventory (1130) recursively
        $inventoryCoAIds = $this->getAllChildChartOfAccountIds($inventoryCoA->id);

        $rawMaterials = Account::where('model_type', 'Item')
            ->where('is_shop_item', 0) // Exclude shop items
            ->whereIn('chart_of_account_id', $inventoryCoAIds)
            ->where('is_active', true)
            ->where(function ($query) use ($search) {
                $query->where('name', 'like', "%{$search}%")
                      ->orWhere('sku', 'like', "%{$search}%");
            })
            ->limit(10)
            ->get()
            ->map(function ($item) {
                return [
                    'id' => $item->id,
                    'text' => $item->name . ' (' . $item->sku . ')',
                    'name' => $item->name,
                    'sku' => $item->sku,
                    'unit' => $item->uom->name ?? 'pcs',
                ];
            });

        return response()->json(['results' => $rawMaterials]);
    }

    /**
     * Add step to BOM
     */
    public function addStep(Request $request, ManufacturingBOM $manufacturingBom): JsonResponse
    {
        $request->validate([
            'step_name' => 'required|string|max:255',
            'instruction' => 'nullable|string|max:1000',
            'sequence_order' => 'required|integer|min:1',
        ]);

        try {
            DB::transaction(function () use ($request, $manufacturingBom) {
                $manufacturingBom->steps()->create([
                    'step_name' => $request->step_name,
                    'instruction' => $request->instruction,
                    'sequence_order' => $request->sequence_order,
                ]);
            });

            return response()->json(['success' => true, 'message' => 'Step added successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Failed to add step'], 500);
        }
    }

    /**
     * Remove step from BOM
     */
    public function removeStep(ManufacturingBOM $manufacturingBom, ManufacturingBOMStep $step): JsonResponse
    {
        try {
            $step->delete();

            return response()->json(['success' => true, 'message' => 'Step removed successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Failed to remove step'], 500);
        }
    }

    /**
     * Add ingredient to BOM (directly or to a step)
     */
    public function addIngredient(Request $request, ManufacturingBOM $manufacturingBom): JsonResponse
    {
        $request->validate([
            'ingredient_account_id' => 'required|exists:accounts,id',
            'quantity_required' => 'required|numeric|min:0.0001',
            'unit' => 'required|string|max:50',
            'wastage_type' => 'required|in:percentage,absolute',
            'wastage_value' => 'required|numeric|min:0',
            'manufacturing_bom_step_id' => 'nullable|exists:manufacturing_bom_steps,id',
        ]);

        try {
            DB::transaction(function () use ($request, $manufacturingBom) {
                $manufacturingBom->ingredients()->create([
                    'ingredient_account_id' => $request->ingredient_account_id,
                    'quantity_required' => $request->quantity_required,
                    'unit' => $request->unit,
                    'wastage_type' => $request->wastage_type,
                    'wastage_value' => $request->wastage_value,
                    'manufacturing_bom_step_id' => $request->manufacturing_bom_step_id,
                ]);
            });

            return response()->json(['success' => true, 'message' => 'Ingredient added successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Failed to add ingredient'], 500);
        }
    }

    /**
     * Remove ingredient from BOM
     */
    public function removeIngredient(ManufacturingBOM $manufacturingBom, ManufacturingBOMIngredient $ingredient): JsonResponse
    {
        try {
            $ingredient->delete();

            return response()->json(['success' => true, 'message' => 'Ingredient removed successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Failed to remove ingredient'], 500);
        }
    }

    /**
     * Download BOM report as PDF
     */
    public function downloadReport($id, $pageSize = 'A4')
    {
        try {
            $bom = ManufacturingBOM::with([
                'finishedGoods',
                'ingredients.ingredient',
                'steps.ingredients.ingredient'
            ])->findOrFail($id);

            // Validate page size
            $allowedSizes = ['A4', 'A5', 'Letter'];
            if (!in_array($pageSize, $allowedSizes)) {
                $pageSize = 'A4';
            }

            // Prepare data for the PDF template
            $data = [
                'bom' => $bom,
                'pageSize' => $pageSize,
                'documentTitle' => 'BOM REPORT',
                'documentSubtitle' => $bom->name,
                'documentNumber' => 'BOM-' . $bom->id,
                'qrCode' => 'BOM-' . $bom->id,
                'footerText' => 'Generated on ' . now()->format('M d, Y H:i:s') . ' | BOM Report for ' . $bom->name,
                'additionalFooter' => 'This document contains detailed BOM information.',
            ];

            // Generate PDF using DomPDF with master template
            $pdf = Pdf::loadView('manufacturing.pdfs.bom-report', $data);
            $pdf->setPaper($pageSize, 'portrait');

            $filename = 'bom_report_' . $bom->name . '_' . strtolower($pageSize) . '.pdf';
            $filename = preg_replace('/[^a-zA-Z0-9_-]/', '_', $filename); // Clean filename

            return $pdf->download($filename);

        } catch (\Exception $e) {
            return redirect()->back()
                ->withErrors(['error' => 'Failed to generate BOM report: ' . $e->getMessage()]);
        }
    }

    /**
     * Get BOM details for AJAX requests
     */
public function getBOMDetails(ManufacturingBOM $manufacturingBom)
    {
        try {
            $manufacturingBom->load(['finishedGoods.chartOfAccount']);

            return response()->json([
                'id' => $manufacturingBom->id,
                'name' => $manufacturingBom->name,
                'basic_unit' => $manufacturingBom->basic_unit,
                'basic_unit_amount' => $manufacturingBom->basic_unit_amount,
                'finished_goods_name' => $manufacturingBom->finishedGoods->name,
                'finished_goods_sku' => $manufacturingBom->finishedGoods->sku,
                'chart_of_account_code' => $manufacturingBom->finishedGoods->chartOfAccount->code,
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to load BOM details'], 500);
        }
    }

    /**
     * Get BOM cost data for manufacturing runs
     */
    public function getBOMCostData(ManufacturingBOM $manufacturingBom, Request $request)
    {
        $pieces = (float) $request->input('pieces', 1); // get pieces from frontend, default 1
        try {
            $manufacturingBom->load([
                'ingredients.ingredient',
                'finishedGoods'
            ]);

            $rawMaterials = [];
            $totalCostPerUnit = 0;
            foreach ($manufacturingBom->ingredients as $ingredient) {
                $averageWeightedPrice = (float) ($ingredient->ingredient->weighted_average_price ?? 0);
                // Calculate net quantity including wastage
            $netQuantity = (float) $ingredient->quantity_required;

            if ($ingredient->wastage_type == 'percentage') {
                $netQuantity *= 1 + ($ingredient->wastage_value / 100);
            } elseif ($ingredient->wastage_type == 'absolute') {
                $netQuantity += $ingredient->wastage_value;
            }

            $netQuantity *= $pieces; // multiply by pieces
                // $netQuantity = (float) $ingredient->net_quantity;
                $totalCost = $averageWeightedPrice * $netQuantity;

                $rawMaterials[] = [
                    'id' => $ingredient->id,
                    'ingredient_name' => $ingredient->ingredient->name,
                    'ingredient_sku' => $ingredient->ingredient->sku,
                    'quantity_required' => (float) $ingredient->quantity_required,
                    'effective_quantity' => $netQuantity,
                    'unit' => $ingredient->unit,
                    'average_weighted_price' => $averageWeightedPrice,
                    'total_cost' => $totalCost,
                ];

                $totalCostPerUnit += $totalCost;
            }

            // dd($manufacturingBom);
            return response()->json([
                'success' => true,
                'data' => [
                    'bom_id' => $manufacturingBom->id,
                    'bom_name' => $manufacturingBom->name,
                    'finished_goods_name' => $manufacturingBom->finishedGoods->name,
                    'basic_unit' => $manufacturingBom->basic_unit,
                    'basic_unit_amount' => $manufacturingBom->basic_unit_amount,
                    'raw_materials' => $rawMaterials,
                    'total_cost_per_unit' => (float) $totalCostPerUnit,
                    'cost_of_production'=> $this->getCostOfProduction($manufacturingBom->finished_goods_account_id),
                    // 'cost_of_production'=> 123,
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Failed to load BOM cost data: ' . $e->getMessage().' at line '.$e->getLine().' in file '.$e->getFile()
            ], 500);
        }
    }

    /**
     * Check if BOM exists for finished good
     */
    public function checkBOMExists(Request $request)
    {
        $request->validate([
            'finished_goods_account_id' => 'required|exists:accounts,id',
            'exclude_bom_id' => 'nullable|exists:manufacturing_boms,id'
        ]);

        // Check if BOM already exists for this finished good (excluding current BOM)
        $query = ManufacturingBOM::where('finished_goods_account_id', $request->finished_goods_account_id)
            ->where('is_active', true);

        if ($request->exclude_bom_id) {
            $query->where('id', '!=', $request->exclude_bom_id);
        }

        $existingBom = $query->first();

        if ($existingBom) {
            $finishedGoods = Account::find($request->finished_goods_account_id);
            return response()->json([
                'exists' => true,
                'bom_id' => $existingBom->id,
                'bom_name' => $existingBom->name,
                'finished_goods_name' => $finishedGoods ? $finishedGoods->name : 'Unknown',
                'message' => "A BOM already exists for '{$finishedGoods->name}'. Only one active BOM is allowed per finished good."
            ]);
        }

        return response()->json([
            'exists' => false,
            'message' => 'No existing BOM found for this finished good.'
        ]);
    }

    /**
     * Debug endpoint to check finished goods data
     */
    public function debugFinishedGoods(Request $request)
    {
        $search = $request->input('q', '');

        $debug = [
            'search_query' => $search,
            'chart_of_account_53' => ChartOfAccount::where('id', 53)->first(),
            'chart_of_account_parent_53' => ChartOfAccount::where('parent_id', 53)->get(),
            'accounts_with_chart_53' => Account::where('chart_of_account_id', 53)->where('model_type', 'Item')->where('is_shop_item', 0)->get(),
            'accounts_with_parent_53' => Account::whereHas('chartOfAccount', function ($query) {
                $query->where('parent_id', 53);
            })->where('model_type', 'Item')->where('is_shop_item', 0)->get(),
            'all_active_items' => Account::where('model_type', 'Item')->where('is_shop_item', 0)->where('is_active', true)->limit(5)->get()
        ];

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

    private function getCostOfProduction($finishedGoodsId)
    {

        $account = Account::find($finishedGoodsId);
        $finishedGoodCOA = ChartOfAccount::find($account->chart_of_account_id);
        // dd($finishedGoodsId,$finishedGoodCOA->parent_id,$account->chart_of_account_id);
        $accounts = [];
        if($finishedGoodCOA->parent_id ==69){ //switch
            // dd("hhhhd");
            $accounts = $this->getCostCenterAccounts($finishedGoodsId);

        }
        elseif($finishedGoodCOA->id== 68 || $finishedGoodCOA->id == 70) //pipe and wires
        {
            // dd($finishedGoodsId);
            $accounts = $this->getCostCenterAccounts($finishedGoodsId);

        }
        // ✅ Safe guard — if still empty, just return 0
    if (empty($accounts)) {
        return 0;
    }
    // dd ( $accounts);

        $totalProductionCost =$this->getSumOfBalanceOfAccounts($accounts);
        $totalProduction = $this->getTotalProduction($finishedGoodCOA);
        return $totalProductionCost == 0 ? 0 : $totalProductionCost / $totalProduction;
    }

    private function getCostCenterAccounts($finishedGoodsId)
    {
        // Get direct account assignments
        $directAccountIds = CostCenter::where('item_id', $finishedGoodsId)
            ->whereNotNull('account_id')
            ->pluck('account_id')
            ->toArray();

        // Get chart of account level assignments
        $chartOfAccountIds = CostCenter::where('item_id', $finishedGoodsId)
            ->whereNull('account_id')
            ->pluck('chart_of_account_id')
            ->toArray();

        // Get all child chart of account IDs recursively
        $allChartOfAccountIds = $this->getAllChildChartOfAccountIds($chartOfAccountIds);

        // Get all account IDs under these chart of accounts
        // dd ($directAccountIds);
        $chartAccountIds = \App\Models\Account::whereIn('chart_of_account_id', $allChartOfAccountIds)
            ->pluck('id')
            ->toArray();

        // Merge direct account IDs with chart-based account IDs
        $allAccountIds = array_unique(array_merge($directAccountIds, $chartAccountIds));

        return $allAccountIds;
    }

    /**
     * Recursively get all child chart of account IDs
     */
    private function getAllChildChartOfAccountIdsCostCenter($chartOfAccountIds)
    {
        $allIds = $chartOfAccountIds;

        foreach ($chartOfAccountIds as $chartId) {
            $childIds = \App\Models\ChartOfAccount::where('parent_id', $chartId)
                ->pluck('id')
                ->toArray();

            if (!empty($childIds)) {
                $allIds = array_merge($allIds, $childIds);
                // Recursively get children of children
                $grandChildIds = $this->getAllChildChartOfAccountIdsCostCenter($childIds);
                $allIds = array_merge($allIds, $grandChildIds);
            }
        }

        return array_unique($allIds);
    }

    private function getSumOfBalanceOfAccounts($accountIds)
    {
        $sum = 0;

        foreach ($accountIds as $accountId) {
            $account = \App\Models\Account::with('chartOfAccount.parent')->find($accountId);

            if (!$account) continue;

            // Get the root parent chart of account
            $rootParent = $this->getRootParentChartOfAccount($account->chartOfAccount);

            // Calculate balance based on parent chart of account type
            $balance = $this->calculateAccountBalance($account, $rootParent);
            $sum += $balance;
        }

        return $sum;
    }

    /**
     * Get the root parent chart of account
     */
    private function getRootParentChartOfAccount($chartOfAccount)
    {
        $current = $chartOfAccount;
        while ($current->parent) {
            $current = $current->parent;
        }
        return $current;
    }

    /**
     * Calculate account balance based on parent chart of account type
     */
    private function calculateAccountBalance($account, $rootParent)
    {
        // Get debit and credit totals for this account
        $debitTotal = $this->getAccountDebitTotal($account->id);
        $creditTotal = $this->getAccountCreditTotal($account->id);

        // Assets and Expenses: Debit Balance (Debit - Credit)
        if (in_array($rootParent->id, [1, 5])) { // Assuming 1=Assets, 5=Expenses
            return $debitTotal - $creditTotal;
        }

        // Liabilities, Equity, Revenue: Credit Balance (Credit - Debit)
        if (in_array($rootParent->id, [2, 3, 4])) { // Assuming 2=Liabilities, 3=Equity, 4=Revenue
            return $creditTotal - $debitTotal;
        }

        // Default to debit balance
        return $debitTotal - $creditTotal;
    }

    /**
     * Get total debit amount for an account (previous month only)
     */
    private function getAccountDebitTotal($accountId)
    {
        $previousMonth = now()->subMonth();
        $startOfMonth = $previousMonth->copy()->startOfMonth();
        $endOfMonth = $previousMonth->copy()->endOfMonth();

        return \App\Models\AccountTransaction::where('account_id', $accountId)
            ->where('transaction_type', 'debit')
            ->whereBetween('transaction_at', [$startOfMonth, $endOfMonth])
            ->sum('amount');
    }

    /**
     * Get total credit amount for an account (previous month only)
     */
    private function getAccountCreditTotal($accountId)
    {
        $previousMonth = now()->subMonth();
        $startOfMonth = $previousMonth->copy()->startOfMonth();
        $endOfMonth = $previousMonth->copy()->endOfMonth();

        return \App\Models\AccountTransaction::where('account_id', $accountId)
            ->where('transaction_type', 'credit')
            ->whereBetween('transaction_at', [$startOfMonth, $endOfMonth])
            ->sum('amount');
    }
    private function getTotalProduction(ChartOfAccount $finishedGoodCOA)
    {
        $totalProduction = 0;
        $previousMonth = now()->subMonth();
        $startOfMonth = $previousMonth->copy()->startOfMonth();
        $endOfMonth = $previousMonth->copy()->endOfMonth();

        $allProducts = Account::where('chart_of_account_id', $finishedGoodCOA->id)->pluck('id');
        $BOM_ids = ManufacturingBOM::whereIn('finished_goods_account_id', $allProducts)->pluck('id');

        $totalProduction = ManufacturingRun::whereIn('manufacturing_bom_id', $BOM_ids)
            ->where('status', 'completed')
            ->whereBetween('created_at', [$startOfMonth, $endOfMonth])

            ->sum('actual_output_qty');
        return $totalProduction;
    }
}

