<?php

namespace App\Http\Controllers;

use App\Brand;
use App\Coat;
use App\Curtain;
use App\CurtainBeddingDetail;
use App\CurtainDoorDetail;
use App\CurtainReorder;
use App\CurtainWindowDetail;
use App\Customer;
use App\CustomerGroup;
use App\Biller;
use App\CashRegister;
use App\CustomField;
use App\Dress;
use App\MailSetting;
use App\Pant;
use App\Product;
use App\Product_Warehouse;
use App\Product_Sale;
use App\Sale;
use App\GeneralSetting;
use App\Tailor;
use App\TailoringCategory;
use App\TailoringProduct;
use App\Tax;
use App\Traits\CacheForget;
use App\Traits\TenantInfo;
use App\Unit;
use App\User;
use App\Waiscoat;
use App\Warehouse;
use App\Services\MainCashAccount;
use App\FinancialTransaction;
use Exception;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Spatie\Permission\Models\Role;

class TailoringProductController extends Controller
{
    use CacheForget;
    use TenantInfo;
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $role = Role::find(Auth::user()->role_id);
        if ($role->hasPermissionTo('Tailoring-index')) {
            $permissions = Role::findByName($role->name)->permissions;
            foreach ($permissions as $permission)
                $all_permission[] = $permission->name;
            if (empty($all_permission))
                $all_permission[] = 'dummy text';
            $role_id = $role->id;
            $numberOfProduct = TailoringProduct::where([['status', 'pending'], ['is_active', true], ['type', 'Curtain']])->count();

            return view('backend.tailoringproduct.index', compact('all_permission', 'role_id', 'numberOfProduct'));
        } else
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $role = Role::firstOrCreate(['id' => Auth::user()->role_id]);
        if ($role->hasPermissionTo('products-add')) {

            $lims_category_list = TailoringCategory::where([['is_active', true], ['parent_id', null], ['name', 'Curtain']])->get();
            $lims_customer_all = Customer::select('id', 'name')->with('customerGroup')->where('is_active', true)->get();
            $lims_customer_group_all = CustomerGroup::where('is_active', true)->get();
            $custom_fields = CustomField::where('belongs_to', 'customer')->get();
            $tailor_waiscoat_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [1, 3]);
            })->get();
            $tailor_coat_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [1, 4]);
            })->get();
            $tailor_pant_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [1, 5]);
            })->get();
            $tailor_dress_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [2]);
            })->get();
            $tailor_curtain_all = Tailor::where('is_active', true)->loginEnabled()->orderBy('name')->get();
            $lims_product_all = Product::with('brand')->where('is_active', true)->orderBy('name')->orderBy('code')->get();
            $nextOrderCode = $this->nextTailoringOrderCode();

            return view('backend.tailoringproduct.create', compact('tailor_waiscoat_all', 'tailor_coat_all', 'tailor_pant_all', 'tailor_dress_all', 'tailor_curtain_all', 'lims_customer_group_all', 'custom_fields', 'lims_customer_all', 'lims_category_list', 'lims_product_all', 'nextOrderCode'));
        } else
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->merge(['code' => $this->nextTailoringOrderCode()]);

        $this->validate($request, [
            'type' => [
                'required',
                'string',
            ],
            'code' => [
                'required',
                'max:255',
                Rule::unique('tailoring_products'),
            ],
            'customer_id' => ['required', 'exists:customers,id'],
            'paid_amount' => ['required', 'numeric', 'min:0'],
            'service_charge' => ['nullable', 'numeric', 'min:0'],
            'window_detail_fabric_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'window_detail_netting_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'door_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'mattress_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'pillow_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'bolster_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'mattress_detail_under_cover_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'pillow_detail_under_cover_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'bolster_detail_under_cover_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'curtain_tailor' => [
                'required',
                function ($attribute, $value, $fail) {
                    $available = Tailor::where('is_active', true)
                        ->loginEnabled()
                        ->whereKey($value)
                        ->exists();
                    if (!$available) {
                        $fail(trans('file.Selected tailor does not have an active login account'));
                    }
                },
            ],
            'completion_date' => ['required', 'date', 'after:today'],
        ]);


        $inputs = $request->all();
        if (ucwords($inputs['type'], ' ') !== 'Curtain') {
            return redirect()->back()->with('not_permitted', trans('file.Only Curtain Orders Available'));
        }
        $inputs['is_wisecoat_order'] = $request->is_wisecoat_order ?? false;
        $inputs['is_coat_order'] = $request->is_coat_order ?? false;
        $inputs['is_pant_order'] = $request->is_pant_order ?? false;
        try {
            DB::beginTransaction();
            if (ucfirst($inputs['type']) == 'Suit') {
                if ($inputs['is_wisecoat_order']) {
                    $inputs['design_v_neck_collar'] = $request->design_v_neck_collar ?? false;
                    $inputs['design_round_neck_collar'] = $request->design_round_neck_collar ?? false;
                    $inputs['design_pakistani_collar'] = $request->design_pakistani_collar ?? false;
                    $inputs['design_zippered_pocket'] = $request->design_zippered_pocket ?? false;
                    $inputs['design_plain_pocket'] = $request->design_plain_pocket ?? false;
                    $inputs['design_four_side_pocket'] = $request->design_four_side_pocket ?? false;
                    $inputs['design_two_side_pocket'] = $request->design_two_side_pocket ?? false;
                    $inputs['tailor_id'] = $inputs['waiscoat_tailor'];

                    $lim_waiscoat = Waiscoat::create([
                        'waiscoat_height' => $inputs['waiscoat_height'],
                        'waiscoat_shoulder' => $inputs['waiscoat_shoulder'],
                        'waiscoat_side' => $inputs['waiscoat_side'],
                        'waiscoat_waist' => $inputs['waiscoat_waist'],
                        'waiscoat_abdomen' => $inputs['waiscoat_abdomen'],
                        'waiscoat_hip' => $inputs['waiscoat_hip'],
                        'vest_chest_circumference' => $inputs['vest_chest_circumference'],
                        'design_v_neck_collar' => $inputs['design_v_neck_collar'],
                        'design_round_neck_collar' => $inputs['design_round_neck_collar'],
                        'design_pakistani_collar' => $inputs['design_pakistani_collar'],
                        'design_zippered_pocket' => $inputs['design_zippered_pocket'],
                        'design_plain_pocket' => $inputs['design_plain_pocket'],
                        'design_four_side_pocket' => $inputs['design_four_side_pocket'],
                        'design_two_side_pocket' => $inputs['design_two_side_pocket'],
                        'waiscoat_order_details' => $inputs['waiscoat_order_details'],
                        'qty' => $inputs['waiscoat_qty'],
                        'tailor_id' => $inputs['tailor_id'],
                    ]);
                    $inputs['waiscoat_id'] = $lim_waiscoat->id;
                }
                if ($inputs['is_coat_order']) {
                    $inputs['coat_style_one_button'] = $request->coat_style_one_button ?? false;
                    $inputs['coat_style_two_button'] = $request->coat_style_two_button ?? false;
                    $inputs['coat_style_three_button'] = $request->coat_style_three_button ?? false;
                    $inputs['tailor_id'] = $inputs['coat_tailor'];
                    $lim_coat = Coat::create([
                        'coat_height' => $inputs['coat_height'],
                        'coat_shoulder' => $inputs['coat_shoulder'],
                        'coat_sleeve' => $inputs['coat_sleeve'],
                        'coat_armhole_circumference' => $inputs['coat_armhole_circumference'],
                        'coat_bicep_circumference' => $inputs['coat_bicep_circumference'],
                        'coat_cuff' => $inputs['coat_cuff'],
                        'coat_side_width' => $inputs['coat_side_width'],
                        'coat_waist' => $inputs['coat_waist'],
                        'coat_abdomen_circumference' => $inputs['coat_abdomen_circumference'],
                        'coat_hip_width' => $inputs['coat_hip_width'],
                        'upperbody_front_length' => $inputs['upperbody_front_length'],
                        'upperbody_back_length' => $inputs['upperbody_back_length'],
                        'chest_distance' => $inputs['chest_distance'],
                        'coat_collar' => $inputs['coat_collar'],
                        'coat_style_one_button' => $inputs['coat_style_one_button'],
                        'coat_style_two_button' => $inputs['coat_style_two_button'],
                        'coat_style_three_button' => $inputs['coat_style_three_button'],
                        'coat_order_details' => $inputs['coat_order_details'],
                        'qty' => $inputs['coat_qty'],
                        'tailor_id' => $inputs['tailor_id'],
                    ]);
                    $inputs['coat_id'] = $lim_coat->id;
                }
                if ($inputs['is_pant_order']) {
                    $inputs['pant_straight_loose'] = $request->pant_straight_loose ?? false;
                    $inputs['pant_straight_medium'] = $request->pant_straight_medium ?? false;
                    $inputs['pant_straight_military'] = $request->pant_straight_military ?? false;
                    $inputs['pant_straight_cuban_pocket'] = $request->pant_straight_cuban_pocket ?? false;
                    $inputs['pant_straight_classic'] = $request->pant_straight_classic ?? false;
                    $inputs['tailor_id'] = $inputs['pant_tailor'];
                    $lim_pant = Pant::create([
                        'pant_length' => $inputs['pant_length'],
                        'pant_waist' => $inputs['pant_waist'],
                        'pant_thigh' => $inputs['pant_thigh'],
                        'pant_rise' => $inputs['pant_rise'],
                        'pant_hem' => $inputs['pant_hem'],
                        'pant_hip' => $inputs['pant_hip'],
                        'trouser_crotch_depth' => $inputs['trouser_crotch_depth'],
                        'pant_straight_loose' => $inputs['pant_straight_loose'],
                        'pant_straight_medium' => $inputs['pant_straight_medium'],
                        'pant_straight_military' => $inputs['pant_straight_military'],
                        'pant_straight_cuban_pocket' => $inputs['pant_straight_cuban_pocket'],
                        'pant_straight_classic' => $inputs['pant_straight_classic'],
                        'pant_order_details' => $inputs['pant_order_details'],
                        'qty' => $inputs['pant_qty'],
                        'tailor_id' => $inputs['tailor_id'],
                    ]);
                    $inputs['pant_id'] = $lim_pant->id;
                }
            } else if (ucwords($inputs['type'], ' ') == 'Afghan Cloths') {
                $inputs['tailor_id'] = $inputs['dress_tailor'];
                $lim_dress = Dress::create([
                    'dress_shirt_length' => $inputs['dress_shirt_length'],
                    'dress_sleeve' => $inputs['dress_sleeve'],
                    'dress_shoulder_width' => $inputs['dress_shoulder_width'],
                    'dress_collar' => $inputs['dress_collar'],
                    'dress_side_width' => $inputs['dress_side_width'],
                    'dress_armhole_circumference' => $inputs['dress_armhole_circumference'],
                    'dress_waist' => $inputs['dress_waist'],
                    'dress_hem' => $inputs['dress_hem'],
                    'dress_skirt_length' => $inputs['dress_skirt_length'],
                    'dress_cuff' => $inputs['dress_cuff'],
                    'dress_skirt_width' => $inputs['dress_skirt_width'],
                    'shirt_trouser_crotch_depth' => $inputs['shirt_trouser_crotch_depth'],
                    'dress_order_details' => $inputs['dress_order_details'],
                    'qty' => $inputs['dress_qty'],
                    'tailor_id' => $inputs['tailor_id'],
                ]);
                $inputs['dress_id'] = $lim_dress->id;
            } else if (ucwords($inputs['type'], ' ') == 'Curtain') {
                $inputs['tailor_id'] = $inputs['curtain_tailor'];
                $inputs['product_id'] = $this->curtainProductId($inputs);
                $inputs['pleating_type'] = $inputs['pleating_type'] ?? '';
                $inputs['ring_stitch_type'] = $inputs['ring_stitch_type'] ?? '';
                $inputs['curtain_model'] = $this->curtainModelValue($inputs['curtain_model'] ?? '');
                $curtainWindowDetails = $this->curtainWindowDetailsFromInputs($inputs);
                $curtainWindowTotals = $this->curtainWindowTotals($curtainWindowDetails);
                $curtainDoorDetails = $this->curtainDoorDetailsFromInputs($inputs);
                $curtainDoorTotals = $this->curtainDoorTotals($curtainDoorDetails, $inputs['door_count'] ?? 0);
                $curtainBeddingDetails = $this->curtainBeddingDetailsFromInputs($inputs);
                $curtainBeddingSummary = $this->curtainBeddingSummary($curtainBeddingDetails);
                if ($detailError = $this->curtainDetailsValidationError($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails)) {
                    DB::rollBack();
                    return redirect()->back()->withInput()->with('not_permitted', $detailError);
                }
                $inputs['material_total'] = $this->curtainMaterialTotal($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails);
                $tailorFeeSnapshot = $this->curtainTailorFeeSnapshot(Tailor::findOrFail($inputs['tailor_id']));
                $inputs['tailor_cost'] = $this->curtainTailorCost($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails, $tailorFeeSnapshot);
                $inputs['service_charge'] = round((float) ($inputs['service_charge'] ?? 0), 2);
                $inputs['total_price'] = round($inputs['material_total'] + $inputs['service_charge'], 2);
                if ((float) $inputs['paid_amount'] > $inputs['total_price']) {
                    DB::rollBack();
                    return redirect()->back()->withInput()->with('not_permitted', trans('file.Paid Exceeds Grand Total'));
                }
                $inputs['due_amount'] = round($inputs['total_price'] - (float) $inputs['paid_amount'], 2);
                $curtainMaterialUsage = $this->curtainMaterialUsageFromDetails($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails);
                if ($stockError = $this->curtainMaterialStockError($curtainMaterialUsage, null)) {
                    DB::rollBack();
                    return redirect()->back()->withInput()->with('not_permitted', $stockError);
                }
                $lim_curtain = Curtain::create([
                    'fabric_type' => $this->curtainLegacyProductName($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails, 'fabric'),
                    'netting_type' => $this->curtainLegacyProductName($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails, 'netting'),
                    'window_count' => $curtainWindowTotals['window_count'],
                    'door_count' => $curtainDoorTotals['door_count'],
                    'panel_count' => $curtainWindowTotals['panel_count'],
                    'panel_meter' => number_format((float) $curtainWindowTotals['panel_meter'] + (float) $curtainDoorTotals['fabric_meterage'], 2, '.', ''),
                    'middle_netting_meter' => number_format((float) $curtainWindowTotals['middle_netting_meter'] + (float) $curtainDoorTotals['netting_meterage'], 2, '.', ''),
                    'pleating_type' => $inputs['pleating_type'],
                    'ring_stitch_type' => $inputs['ring_stitch_type'],
                    'curtain_model' => $inputs['curtain_model'],
                    'mattress_count' => $curtainBeddingSummary['mattress_count'],
                    'pillow_count' => $curtainBeddingSummary['pillow_count'],
                    'bolster_count' => $curtainBeddingSummary['bolster_count'],
                    'mattress_pillow_size' => $curtainBeddingSummary['size'],
                    'pillow_mattress_model' => $curtainBeddingSummary['model'],
                    'curtain_order_details' => $inputs['curtain_order_details'],
                    'qty' => $inputs['curtain_qty'],
                    'tailor_id' => $inputs['tailor_id'],
                ]);
                $this->syncCurtainWindowDetails($lim_curtain, $curtainWindowDetails);
                $this->syncCurtainDoorDetails($lim_curtain, $curtainDoorDetails);
                $this->syncCurtainBeddingDetails($lim_curtain, $curtainBeddingDetails);
                $inputs['curtain_id'] = $lim_curtain->id;
            }
            $product = TailoringProduct::create([
                'type' => $inputs['type'],
                'customer_id' => $inputs['customer_id'],
                'total_price' => number_format($inputs['total_price'], 2, '.', ''),
                'material_total' => number_format($inputs['material_total'], 2, '.', ''),
                'service_charge' => number_format($inputs['service_charge'], 2, '.', ''),
                'tailor_cost' => number_format($inputs['tailor_cost'], 2, '.', ''),
                'tailor_fabric_meter_fee' => $tailorFeeSnapshot['tailor_fabric_meter_fee'],
                'tailor_netting_meter_fee' => $tailorFeeSnapshot['tailor_netting_meter_fee'],
                'tailor_mattress_fee' => $tailorFeeSnapshot['tailor_mattress_fee'],
                'tailor_pillow_fee' => $tailorFeeSnapshot['tailor_pillow_fee'],
                'tailor_bolster_fee' => $tailorFeeSnapshot['tailor_bolster_fee'],
                'tailor_under_cover_fee_method' => $tailorFeeSnapshot['tailor_under_cover_fee_method'],
                'tailor_mattress_under_cover_fee' => $tailorFeeSnapshot['tailor_mattress_under_cover_fee'],
                'tailor_pillow_under_cover_fee' => $tailorFeeSnapshot['tailor_pillow_under_cover_fee'],
                'tailor_bolster_under_cover_fee' => $tailorFeeSnapshot['tailor_bolster_under_cover_fee'],
                'paid_amount' => number_format($inputs['paid_amount'], 2, '.', ''),
                'due_amount' => $inputs['due_amount'],
                'completion_date' => $inputs['completion_date'],
                'code' => $inputs['code'],
                'coat_id' => $inputs['coat_id'] ?? null,
                'waiscoat_id' => $inputs['waiscoat_id'] ?? null,
                'pant_id' => $inputs['pant_id'] ?? null,
                'dress_id' => $inputs['dress_id'] ?? null,
                'curtain_id' => $inputs['curtain_id'] ?? null,
                'product_id' => $inputs['product_id'],
            ]);
            if ((float) $product->paid_amount > 0) {
                app(MainCashAccount::class)->deposit(
                    (float) $product->paid_amount,
                    'curtain_order_payment',
                    TailoringProduct::class,
                    $product->id,
                    $product->code,
                    trans('file.Curtain order payment'),
                    now()
                );
            }
            if ($product->curtain) {
                $this->syncTailoringProductStock($product, null, $curtainMaterialUsage);
                $product->stock_synced = true;
                $product->save();
            }
            $this->syncTailoringSale($product, $curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails);
            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            Log::error('Tailoring order transaction failed', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return redirect()->back()->withInput()->with('not_permitted', $e->getMessage());
        }
        $this->cacheForget('product_list');
        $this->cacheForget('product');
        return view('backend.tailoringproduct.display', compact('product'));
    }


    public function active($id)
    {
        $product = TailoringProduct::findOrFail($id);
        $product->is_active = true;
        $product->save();
        \Session::flash('create_message', 'Order created successfully.');
        return redirect()->route('tailoringproducts.index');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $product = TailoringProduct::findOrFail($id);
        if ($product->status != 'pending') {
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
        }
        $role = Role::firstOrCreate(['id' => Auth::user()->role_id]);
        if ($role->hasPermissionTo('Tailoring-edit')) {
            if ($product->type !== 'Curtain') {
                return redirect()->route('tailoringproducts.index')->with('not_permitted', trans('file.Only Curtain Orders Available'));
            }
            $lims_category_list = TailoringCategory::where([['is_active', true], ['name', 'Curtain']])->get();
            $lims_customer_all = Customer::where('is_active', true)->get();
            $tailor_all = Tailor::where('is_active', true)->get();
            $lims_customer_group_all = CustomerGroup::where('is_active', true)->get();
            $custom_fields = CustomField::where('belongs_to', 'customer')->get();
            $product = TailoringProduct::where([['id', $id], ['is_active', true]])->with('waiscoat', 'coat', 'pant', 'dress', 'curtain', 'customer')->first();
            $lims_product_all = Product::with('brand')->where('is_active', true)->orderBy('name')->orderBy('code')->get();
            $tailor_waiscoat_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [1, 3]);
            })->get();
            $tailor_coat_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [1, 4]);
            })->get();
            $tailor_pant_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [1, 5]);
            })->get();
            $tailor_dress_all = Tailor::where('is_active', true)->whereHas('catagory', function ($query) {
                return $query->whereIn('id', [2]);
            })->get();
            $tailor_curtain_all = Tailor::where('is_active', true)->loginEnabled()->orderBy('name')->get();
            $originalCurtainMaterialUsage = ($product->stock_synced && $product->curtain)
                ? $this->curtainMaterialUsageFromCurtain($product->curtain)
                : null;

            return view('backend.tailoringproduct.edit', compact('tailor_dress_all', 'tailor_curtain_all', 'tailor_pant_all', 'tailor_coat_all', 'tailor_waiscoat_all', 'product', 'lims_category_list', 'lims_customer_all', 'tailor_all', 'lims_customer_group_all', 'custom_fields', 'lims_product_all', 'originalCurtainMaterialUsage'));
        } else
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $product = TailoringProduct::findOrFail($id);
        if ($product->status != 'pending') {
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
        }
        $this->validate($request, [
            'type' => [
                'required',
                'string',
            ],
            'code' => [
                'required',
                'max:255',
                Rule::unique('tailoring_products', 'code')->ignore($id),
            ],
            'customer_id' => ['required', 'exists:customers,id'],
            'paid_amount' => ['required', 'numeric', 'min:0'],
            'service_charge' => ['nullable', 'numeric', 'min:0'],
            'window_detail_fabric_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'window_detail_netting_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'door_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'mattress_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'pillow_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'bolster_detail_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'mattress_detail_under_cover_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'pillow_detail_under_cover_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'bolster_detail_under_cover_unit_price.*' => ['nullable', 'numeric', 'min:0'],
            'curtain_tailor' => [
                'required',
                function ($attribute, $value, $fail) {
                    $available = Tailor::where('is_active', true)
                        ->loginEnabled()
                        ->whereKey($value)
                        ->exists();
                    if (!$available) {
                        $fail(trans('file.Selected tailor does not have an active login account'));
                    }
                },
            ],
            'completion_date' => ['required', 'date', 'after:today'],
        ]);

        $inputs = $request->all();
        if (ucwords($inputs['type'], ' ') !== 'Curtain') {
            return redirect()->back()->with('not_permitted', trans('file.Only Curtain Orders Available'));
        }
        $inputs['is_wisecoat_order'] = $request->is_wisecoat_order ?? false;
        $inputs['is_coat_order'] = $request->is_coat_order ?? false;
        $inputs['is_pant_order'] = $request->is_pant_order ?? false;
        $oldCurtainMaterialUsage = ($product->stock_synced && $product->curtain)
            ? $this->curtainMaterialUsageFromCurtain($product->curtain)
            : null;
        $newCurtainMaterialUsage = null;

        try {
            DB::beginTransaction();
            if (ucfirst($inputs['type']) == 'Suit') {
                if ($inputs['is_wisecoat_order']) {
                    $inputs['design_v_neck_collar'] = $request->design_v_neck_collar ?? false;
                    $inputs['design_round_neck_collar'] = $request->design_round_neck_collar ?? false;
                    $inputs['design_pakistani_collar'] = $request->design_pakistani_collar ?? false;
                    $inputs['design_zippered_pocket'] = $request->design_zippered_pocket ?? false;
                    $inputs['design_plain_pocket'] = $request->design_plain_pocket ?? false;
                    $inputs['design_four_side_pocket'] = $request->design_four_side_pocket ?? false;
                    $inputs['design_two_side_pocket'] = $request->design_two_side_pocket ?? false;
                    $inputs['tailor_id'] = $inputs['waiscoat_tailor'];
                    $data = [
                        'waiscoat_height' => $inputs['waiscoat_height'],
                        'waiscoat_shoulder' => $inputs['waiscoat_shoulder'],
                        'waiscoat_side' => $inputs['waiscoat_side'],
                        'waiscoat_waist' => $inputs['waiscoat_waist'],
                        'waiscoat_abdomen' => $inputs['waiscoat_abdomen'],
                        'waiscoat_hip' => $inputs['waiscoat_hip'],
                        'vest_chest_circumference' => $inputs['vest_chest_circumference'],
                        'design_v_neck_collar' => $inputs['design_v_neck_collar'],
                        'design_round_neck_collar' => $inputs['design_round_neck_collar'],
                        'design_pakistani_collar' => $inputs['design_pakistani_collar'],
                        'design_zippered_pocket' => $inputs['design_zippered_pocket'],
                        'design_plain_pocket' => $inputs['design_plain_pocket'],
                        'design_four_side_pocket' => $inputs['design_four_side_pocket'],
                        'design_two_side_pocket' => $inputs['design_two_side_pocket'],
                        'waiscoat_order_details' => $inputs['waiscoat_order_details'],
                        'qty' => $inputs['waiscoat_qty'],
                        'tailor_id' => $inputs['tailor_id'],
                    ];

                    // Check if product already has a waiscoat
                    if ($product->waiscoat) {
                        // Update the existing waiscoat
                        $product->waiscoat->update($data);
                        $inputs['waiscoat_id'] = $product->waiscoat->id;
                    } else {
                        // Create new waiscoat
                        $newWaiscoat = Waiscoat::create($data);

                        // Assign its ID to the product
                        $product->waiscoat_id = $newWaiscoat->id;
                        $product->save();

                        $inputs['waiscoat_id'] = $newWaiscoat->id;
                    }
                }
                if ($inputs['is_coat_order']) {
                    $inputs['coat_style_one_button'] = $request->coat_style_one_button ?? false;
                    $inputs['coat_style_two_button'] = $request->coat_style_two_button ?? false;
                    $inputs['coat_style_three_button'] = $request->coat_style_three_button ?? false;
                    $inputs['tailor_id'] = $inputs['coat_tailor'];
                    $data = [
                        'coat_height' => $inputs['coat_height'],
                        'coat_shoulder' => $inputs['coat_shoulder'],
                        'coat_sleeve' => $inputs['coat_sleeve'],
                        'coat_armhole_circumference' => $inputs['coat_armhole_circumference'],
                        'coat_bicep_circumference' => $inputs['coat_bicep_circumference'],
                        'coat_cuff' => $inputs['coat_cuff'],
                        'coat_side_width' => $inputs['coat_side_width'],
                        'coat_waist' => $inputs['coat_waist'],
                        'coat_abdomen_circumference' => $inputs['coat_abdomen_circumference'],
                        'coat_hip_width' => $inputs['coat_hip_width'],
                        'upperbody_front_length' => $inputs['upperbody_front_length'],
                        'upperbody_back_length' => $inputs['upperbody_back_length'],
                        'chest_distance' => $inputs['chest_distance'],
                        'coat_collar' => $inputs['coat_collar'],
                        'coat_style_one_button' => $inputs['coat_style_one_button'],
                        'coat_style_two_button' => $inputs['coat_style_two_button'],
                        'coat_style_three_button' => $inputs['coat_style_three_button'],
                        'coat_order_details' => $inputs['coat_order_details'],
                        'qty' => $inputs['coat_qty'],
                        'tailor_id' => $inputs['tailor_id'],
                    ];
                    // Check if product already has a coat
                    if ($product->coat) {
                        // Update the existing coat
                        $product->coat->update($data);
                        $inputs['coat_id'] = $product->coat->id;
                    } else {
                        // Create new coat
                        $newCoat = Coat::create($data);

                        // Assign its ID to the product
                        $product->coat_id = $newCoat->id;
                        $product->save();
                        $inputs['coat_id'] = $newCoat->id;
                    }
                }
                if ($inputs['is_pant_order']) {
                    $inputs['pant_straight_loose'] = $request->pant_straight_loose ?? false;
                    $inputs['pant_straight_medium'] = $request->pant_straight_medium ?? false;
                    $inputs['pant_straight_military'] = $request->pant_straight_military ?? false;
                    $inputs['pant_straight_cuban_pocket'] = $request->pant_straight_cuban_pocket ?? false;
                    $inputs['pant_straight_classic'] = $request->pant_straight_classic ?? false;
                    $inputs['tailor_id'] = $inputs['pant_tailor'];
                    $data =[
                        'pant_length' => $inputs['pant_length'],
                        'pant_waist' => $inputs['pant_waist'],
                        'pant_thigh' => $inputs['pant_thigh'],
                        'pant_rise' => $inputs['pant_rise'],
                        'pant_hem' => $inputs['pant_hem'],
                        'pant_hip' => $inputs['pant_hip'],
                        'trouser_crotch_depth' => $inputs['trouser_crotch_depth'],
                        'pant_straight_loose' => $inputs['pant_straight_loose'],
                        'pant_straight_medium' => $inputs['pant_straight_medium'],
                        'pant_straight_military' => $inputs['pant_straight_military'],
                        'pant_straight_cuban_pocket' => $inputs['pant_straight_cuban_pocket'],
                        'pant_straight_classic' => $inputs['pant_straight_classic'],
                        'pant_order_details' => $inputs['pant_order_details'],
                        'qty' => $inputs['pant_qty'],
                        'tailor_id' => $inputs['tailor_id'],
                    ];
                    // Check if product already has a pant
                    if ($product->pant) {
                        // Update the existing pant
                        $product->pant->update($data);
                        $inputs['pant_id'] = $product->pant->id;
                    } else {
                        // Create new pant
                        $newpant = Pant::create($data);

                        // Assign its ID to the product
                        $product->pant_id = $newpant->id;
                        $product->save();
                        $inputs['pant_id'] = $newpant->id;
                    }
                }
            } else if (ucwords($inputs['type'], ' ') == 'Afghan Cloths') {
                $inputs['tailor_id'] = $inputs['dress_tailor'];
                $data = [
                    'dress_shirt_length' => $inputs['dress_shirt_length'],
                    'dress_sleeve' => $inputs['dress_sleeve'],
                    'dress_shoulder_width' => $inputs['dress_shoulder_width'],
                    'dress_collar' => $inputs['dress_collar'],
                    'dress_side_width' => $inputs['dress_side_width'],
                    'dress_armhole_circumference' => $inputs['dress_armhole_circumference'],
                    'dress_waist' => $inputs['dress_waist'],
                    'dress_hem' => $inputs['dress_hem'],
                    'dress_skirt_length' => $inputs['dress_skirt_length'],
                    'dress_cuff' => $inputs['dress_cuff'],
                    'dress_skirt_width' => $inputs['dress_skirt_width'],
                    'shirt_trouser_crotch_depth' => $inputs['shirt_trouser_crotch_depth'],
                    'dress_order_details' => $inputs['dress_order_details'],
                    'qty' => $inputs['dress_qty'],
                    'tailor_id' => $inputs['tailor_id'],
                ];

                // Check if product already has a dress
                if ($product->dress) {
                    // Update the existing dress
                    $product->dress->update($data);
                    $inputs['dress_id'] = $product->dress->id;
                } else {
                    // Create new dress
                    $newdress = Dress::create($data);

                    // Assign its ID to the product
                    $product->dress_id = $newdress->id;
                    $product->save();
                    $inputs['dress_id'] = $newdress->id;
                }
            } else if (ucwords($inputs['type'], ' ') == 'Curtain') {
                $inputs['tailor_id'] = $inputs['curtain_tailor'];
                $inputs['product_id'] = $this->curtainProductId($inputs);
                $inputs['pleating_type'] = $inputs['pleating_type'] ?? '';
                $inputs['ring_stitch_type'] = $inputs['ring_stitch_type'] ?? '';
                $inputs['curtain_model'] = $this->curtainModelValue($inputs['curtain_model'] ?? '');
                $curtainWindowDetails = $this->curtainWindowDetailsFromInputs($inputs);
                $curtainWindowTotals = $this->curtainWindowTotals($curtainWindowDetails);
                $curtainDoorDetails = $this->curtainDoorDetailsFromInputs($inputs);
                $curtainDoorTotals = $this->curtainDoorTotals($curtainDoorDetails, $inputs['door_count'] ?? 0);
                $curtainBeddingDetails = $this->curtainBeddingDetailsFromInputs($inputs);
                $curtainBeddingSummary = $this->curtainBeddingSummary($curtainBeddingDetails);
                if ($detailError = $this->curtainDetailsValidationError($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails)) {
                    DB::rollBack();
                    return redirect()->back()->withInput()->with('not_permitted', $detailError);
                }
                $inputs['material_total'] = $this->curtainMaterialTotal($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails);
                $tailorFeeSnapshot = $this->curtainTailorFeeSnapshot(Tailor::findOrFail($inputs['tailor_id']), $product);
                $inputs['tailor_cost'] = $this->curtainTailorCost($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails, $tailorFeeSnapshot);
                $inputs['service_charge'] = round((float) ($inputs['service_charge'] ?? 0), 2);
                $inputs['total_price'] = round($inputs['material_total'] + $inputs['service_charge'], 2);
                if ((float) $inputs['paid_amount'] > $inputs['total_price']) {
                    DB::rollBack();
                    return redirect()->back()->withInput()->with('not_permitted', trans('file.Paid Exceeds Grand Total'));
                }
                $inputs['due_amount'] = round($inputs['total_price'] - (float) $inputs['paid_amount'], 2);
                $newCurtainMaterialUsage = $this->curtainMaterialUsageFromDetails($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails);
                if ($stockError = $this->curtainMaterialStockError($newCurtainMaterialUsage, $oldCurtainMaterialUsage)) {
                    DB::rollBack();
                    return redirect()->back()->withInput()->with('not_permitted', $stockError);
                }
                $data = [
                    'fabric_type' => $this->curtainLegacyProductName($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails, 'fabric'),
                    'netting_type' => $this->curtainLegacyProductName($curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails, 'netting'),
                    'window_count' => $curtainWindowTotals['window_count'],
                    'door_count' => $curtainDoorTotals['door_count'],
                    'panel_count' => $curtainWindowTotals['panel_count'],
                    'panel_meter' => number_format((float) $curtainWindowTotals['panel_meter'] + (float) $curtainDoorTotals['fabric_meterage'], 2, '.', ''),
                    'middle_netting_meter' => number_format((float) $curtainWindowTotals['middle_netting_meter'] + (float) $curtainDoorTotals['netting_meterage'], 2, '.', ''),
                    'pleating_type' => $inputs['pleating_type'],
                    'ring_stitch_type' => $inputs['ring_stitch_type'],
                    'curtain_model' => $inputs['curtain_model'],
                    'mattress_count' => $curtainBeddingSummary['mattress_count'],
                    'pillow_count' => $curtainBeddingSummary['pillow_count'],
                    'bolster_count' => $curtainBeddingSummary['bolster_count'],
                    'mattress_pillow_size' => $curtainBeddingSummary['size'],
                    'pillow_mattress_model' => $curtainBeddingSummary['model'],
                    'curtain_order_details' => $inputs['curtain_order_details'],
                    'qty' => $inputs['curtain_qty'],
                    'tailor_id' => $inputs['tailor_id'],
                ];

                if ($product->curtain) {
                    $product->curtain->update($data);
                    $this->syncCurtainWindowDetails($product->curtain, $curtainWindowDetails);
                    $this->syncCurtainDoorDetails($product->curtain, $curtainDoorDetails);
                    $this->syncCurtainBeddingDetails($product->curtain, $curtainBeddingDetails);
                    $inputs['curtain_id'] = $product->curtain->id;
                } else {
                    $newcurtain = Curtain::create($data);
                    $this->syncCurtainWindowDetails($newcurtain, $curtainWindowDetails);
                    $this->syncCurtainDoorDetails($newcurtain, $curtainDoorDetails);
                    $this->syncCurtainBeddingDetails($newcurtain, $curtainBeddingDetails);
                    $product->curtain_id = $newcurtain->id;
                    $product->save();
                    $inputs['curtain_id'] = $newcurtain->id;
                }
            }
            $previousPaidAmount = (float) $product->paid_amount;
            $product->update([
                'type' => $inputs['type'],
                'customer_id' => $inputs['customer_id'],
                'total_price' => $inputs['total_price'],
                'material_total' => $inputs['material_total'],
                'service_charge' => $inputs['service_charge'],
                'tailor_cost' => $inputs['tailor_cost'],
                'tailor_fabric_meter_fee' => $tailorFeeSnapshot['tailor_fabric_meter_fee'],
                'tailor_netting_meter_fee' => $tailorFeeSnapshot['tailor_netting_meter_fee'],
                'tailor_mattress_fee' => $tailorFeeSnapshot['tailor_mattress_fee'],
                'tailor_pillow_fee' => $tailorFeeSnapshot['tailor_pillow_fee'],
                'tailor_bolster_fee' => $tailorFeeSnapshot['tailor_bolster_fee'],
                'tailor_under_cover_fee_method' => $tailorFeeSnapshot['tailor_under_cover_fee_method'],
                'tailor_mattress_under_cover_fee' => $tailorFeeSnapshot['tailor_mattress_under_cover_fee'],
                'tailor_pillow_under_cover_fee' => $tailorFeeSnapshot['tailor_pillow_under_cover_fee'],
                'tailor_bolster_under_cover_fee' => $tailorFeeSnapshot['tailor_bolster_under_cover_fee'],
                'paid_amount' => $inputs['paid_amount'],
                'due_amount' => $inputs['due_amount'],
                'completion_date' => $inputs['completion_date'],
                'code' => $inputs['code'],
                'coat_id' => $inputs['coat_id'] ?? null,
                'waiscoat_id' => $inputs['waiscoat_id'] ?? null,
                'pant_id' => $inputs['pant_id'] ?? null,
                'dress_id' => $inputs['dress_id'] ?? null,
                'curtain_id' => $inputs['curtain_id'] ?? null,
                'product_id' => $inputs['product_id'],
            ]);
            $paidDifference = round((float) $product->paid_amount - $previousPaidAmount, 2);
            if ($paidDifference > 0) {
                app(MainCashAccount::class)->deposit(
                    $paidDifference,
                    'curtain_order_payment',
                    TailoringProduct::class,
                    $product->id,
                    $product->code,
                    trans('file.Curtain order additional payment'),
                    now()
                );
            } elseif ($paidDifference < 0) {
                app(MainCashAccount::class)->withdraw(
                    abs($paidDifference),
                    'customer_refund',
                    TailoringProduct::class,
                    $product->id,
                    $product->code,
                    trans('file.Curtain order payment correction'),
                    now()
                );
            }
            if ($product->curtain && $newCurtainMaterialUsage) {
                $this->syncTailoringProductStock($product, $oldCurtainMaterialUsage, $newCurtainMaterialUsage);
                $product->stock_synced = true;
                $product->save();
            }
            $this->syncTailoringSale($product, $curtainWindowDetails, $curtainDoorDetails, $curtainBeddingDetails);

            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            \Session::flash('not_permitted', 'Transiction Failed.');
            return redirect()->back();
        }
        $this->cacheForget('product_list');
        $this->cacheForget('product');
        \Session::flash('create_message', 'Order Updated successfully');
        return redirect()->route('tailoringproducts.index');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        if (!env('USER_VERIFIED')) {
            return redirect()->back()->with('not_permitted', 'This feature is disable for demo!');
        } else {
            DB::beginTransaction();
            try {
                $lims_product_data = TailoringProduct::findOrFail($id);
                $this->deactivateTailoringProduct($lims_product_data);
                DB::commit();
            } catch (Exception $e) {
                DB::rollBack();
                return redirect()->back()->with('not_permitted', $e->getMessage());
            }
            $this->cacheForget('product_list');
            $this->cacheForget('product_list_with_variant');
            return redirect()->back()->with('message', 'Product deleted successfully');
        }
    }

    public function productWithoutVariant()
    {
        return Product::ActiveStandard()->select('id', 'name', 'code')
            ->whereNull('is_variant')->get();
    }

    public function productWithVariant()
    {
        return Product::join('product_variants', 'products.id', 'product_variants.product_id')
            ->ActiveStandard()
            ->whereNotNull('is_variant')
            ->select('products.id', 'products.name', 'product_variants.item_code')
            ->orderBy('position')->get();
    }

    public function limsProductSearch(Request $request)
    {
        $product_code = explode("(", $request['data']);
        $product_code[0] = rtrim($product_code[0], " ");
        $lims_product_data = Product::where([
            ['code', $product_code[0]],
            ['is_active', true]
        ])->first();
        if (!$lims_product_data) {
            $lims_product_data = Product::join('product_variants', 'products.id', 'product_variants.product_id')
                ->select('products.*', 'product_variants.item_code', 'product_variants.variant_id', 'product_variants.additional_price')
                ->where('product_variants.item_code', $product_code[0])
                ->first();

            $variant_id = $lims_product_data->variant_id;
            $additional_price = $lims_product_data->additional_price;
        } else {
            $variant_id = '';
            $additional_price = 0;
        }
        $product[] = $lims_product_data->name;
        if ($lims_product_data->is_variant)
            $product[] = $lims_product_data->item_code;
        else
            $product[] = $lims_product_data->code;

        $product[] = $lims_product_data->price + $additional_price;
        $product[] = DNS1D::getBarcodePNG($lims_product_data->code, $lims_product_data->barcode_symbology);
        $product[] = $lims_product_data->promotion_price;
        $product[] = config('currency');
        $product[] = config('currency_position');
        $product[] = $lims_product_data->qty;
        $product[] = $lims_product_data->id;
        $product[] = $variant_id;
        return $product;
    }

    public function add_customer(Request $request)
    {
        $validated = Validator::make($request->all(), [
            'phone_number' => [
                'required',
                'max:255',
                Rule::unique('customers')->where(function ($query) {
                    return $query->where('is_active', 1);
                }),
            ],
            'customer_name' => ['required'],
            'email' => ['nullable', 'email', 'max:255'],
            'address' => ['required'],
        ]);

        if ($validated->fails()) {
            return response()->json([
                'status' => false,
                'error' => $validated->errors(),
            ], 400);
        }
        $customer_group_id = CustomerGroup::where('is_active', true)->orderBy('id')->value('id');
        if (!$customer_group_id) {
            return response()->json([
                'status' => false,
                'error' => ['customer_name' => [trans('file.Please create an active customer group first.')]],
            ], 422);
        }

        $lims_customer_data = Customer::create([
            'customer_group_id' => $customer_group_id,
            'name' => trim($request->customer_name),
            'email' => $request->filled('email') ? trim($request->email) : null,
            'phone_number' => trim($request->phone_number),
            'address' => trim($request->address),
            'city' => '',
            'is_active' => true,
        ]);

        $this->cacheForget('customer_list');
        $message = 'Customer created successfully!';

        if ($request->ajax()) {
            return response()->json([
                'status' => true,
                'message' => $message,
                'data' => $lims_customer_data,
            ], 200);
        }
    }


    public function productData(Request $request)
    {
        $columns = array(
            2 => 'code',
            3 => 'customer_id',
            4 => 'type',
            5 => 'total_price',
            6 => 'paid_amount',
            7 => 'due_amount',
            8 => 'created_at',
            9 => 'completion_date',
        );

        $totalData = TailoringProduct::where([['status', 'pending'], ['is_active', true], ['type', 'Curtain']])->count();
        $totalFiltered = $totalData;

        if ($request->input('length') != -1)
            $limit = $request->input('length');
        else
            $limit = $totalData;
        $start = $request->input('start');
        $orderColumn = $columns[$request->input('order.0.column')] ?? 'created_at';
        $order = 'tailoring_products.' . $orderColumn;

        $dir = in_array($request->input('order.0.dir'), ['asc', 'desc']) ? $request->input('order.0.dir') : 'desc';
        if (empty($request->input('search.value'))) {

            $products = TailoringProduct::with('waiscoat', 'coat.tailor', 'pant', 'dress', 'curtain.reorders.reorderedBy', 'customer')
                ->latest()
                ->offset($start)
                ->where([['status', 'pending'], ['is_active', true], ['type', 'Curtain']])
                ->limit($limit)
                ->orderBy($order, $dir)
                ->get();
        } else {
            $search = $request->input('search.value');
            $products =  TailoringProduct::select('tailoring_products.*')->where([['status', 'pending'], ['is_active', true], ['tailoring_products.type', 'Curtain']])
                ->with('waiscoat', 'coat', 'pant', 'dress', 'curtain.reorders.reorderedBy', 'customer')
                ->WhereHas('customer', function ($query) use ($search) {
                    $query->where([
                        ['customers.name', 'LIKE', "%{$search}%"],
                        ['customers.is_active', true]
                    ])
                        ->orWhere([
                            ['customers.phone_number', 'LIKE', "%{$search}%"],
                            ['customers.is_active', true]
                        ]);
                })
                ->orWhere([
                    ['tailoring_products.type', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'pending'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->orWhere([
                    ['tailoring_products.code', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'pending'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->latest()
                ->offset($start)
                ->limit($limit)
                ->orderBy($order, $dir)->get();

            $totalFiltered = TailoringProduct::select('tailoring_products.*')->where([['status', 'pending'], ['is_active', true], ['tailoring_products.type', 'Curtain']])
                ->with('waiscoat', 'coat', 'pant', 'dress', 'curtain.reorders.reorderedBy', 'customer')
                ->WhereHas('customer', function ($query) use ($search) {
                    $query->where([
                        ['customers.name', 'LIKE', "%{$search}%"],
                        ['customers.is_active', true]
                    ])
                        ->orWhere([
                            ['customers.phone_number', 'LIKE', "%{$search}%"],
                            ['customers.is_active', true]
                        ]);
                })
                ->orWhere([
                    ['tailoring_products.type', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'pending'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->orWhere([
                    ['tailoring_products.code', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'pending'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->count();
        }
        $data = array();
        if (!empty($products)) {
            foreach ($products as $key => $product) {
                $nestedData['id'] = $product->id;
                $nestedData['key'] = $key;
                $nestedData['code'] = $product->code;
                $nestedData['customer_name'] = $product->customer->name;
                $nestedData['customer_phone'] = $product->customer->phone_number;
                $nestedData['category'] = trans('file.' . $product->type . '');
                $nestedData['status'] = $product->curtain && $product->curtain->tailor_status === 'reordered'
                    ? '<div class="badge badge-warning">' . trans('file.Re-ordered') . '</div>'
                    : '<div class="badge badge-danger">' . trans('file.Pending') . '</div>';
                $nestedData['total_price'] = number_format($product->total_price, config('decimal'));
                $nestedData['paid_amount'] = number_format($product->paid_amount, config('decimal'));
                $nestedData['due_amount'] = number_format($product->due_amount, config('decimal'));
                $nestedData['issue_date'] = date(config('date_format'), strtotime($product->created_at->toDateString()));
                $nestedData['completion_date'] = date(config('date_format'), strtotime($product->completion_date->toDateString()));


                $nestedData['options'] = '<div class="btn-group">
                            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . trans("file.action") . '
                              <span class="caret"></span>
                              <span class="sr-only">Toggle Dropdown</span>
                            </button>
                            <ul class="dropdown-menu edit-options dropdown-menu-right dropdown-default" user="menu">
                            <li>
                                <button="type" class="btn btn-link view"><i class="fa fa-eye"></i> ' . trans('file.View') . '</button>
                            </li>';

                if (in_array("Tailoring-edit", $request['all_permission'])) {
                    $nestedData['options'] .= '<li>
                            <a href="' . route('tailoringproducts.edit', $product->id) . '" class="btn btn-link"><i class="fa fa-edit"></i> ' . trans('file.edit') . '</a>
                        </li>';
                }
                if (in_array("Tailoring-delete", $request['all_permission'])) {
                    $nestedData['options'] .= \Form::open(["route" => ["tailoringproducts.destroy", $product->id], "method" => "DELETE"]) . '
                            <li>
                              <button type="submit" class="btn btn-link" onclick="return confirmDelete()"><i class="fa fa-trash"></i> ' . trans("file.delete") . '</button>
                            </li>' . \Form::close() . '
                        </ul>
                    </div>';
                }

                // data for product details by one click
                $is_waiscoat_order = $product->waiscoat ? true : false;
                $tailor_name =  $is_waiscoat_order ? $product->waiscoat->tailor->name : '';
                $tailor_phone =  $is_waiscoat_order ? $product->waiscoat->tailor->tailor_fee : '';
                $waiscoat_height =  $is_waiscoat_order ? $product->waiscoat->waiscoat_height : '';
                $waiscoat_qty =  $is_waiscoat_order ? $product->waiscoat->qty : '';
                $waiscoat_total =  $is_waiscoat_order ? $product->waiscoat->qty * $product->waiscoat->tailor->tailor_fee : '';
                $waiscoat_shoulder =  $is_waiscoat_order ? $product->waiscoat->waiscoat_shoulder : '';
                $waiscoat_side =  $is_waiscoat_order ? $product->waiscoat->waiscoat_side : '';
                $waiscoat_waist =  $is_waiscoat_order ? $product->waiscoat->waiscoat_waist : '';
                $waiscoat_abdomen =  $is_waiscoat_order ? $product->waiscoat->waiscoat_abdomen : '';
                $waiscoat_hip =  $is_waiscoat_order ? $product->waiscoat->waiscoat_hip : '';
                $vest_chest_circumference =  $is_waiscoat_order ? $product->waiscoat->vest_chest_circumference : '';
                $design_v_neck_collar =  $is_waiscoat_order ? $product->waiscoat->design_v_neck_collar : '';
                $design_round_neck_collar =  $is_waiscoat_order ? $product->waiscoat->design_round_neck_collar : '';
                $design_pakistani_collar =  $is_waiscoat_order ? $product->waiscoat->design_pakistani_collar : '';
                $design_zippered_pocket =  $is_waiscoat_order ? $product->waiscoat->design_zippered_pocket : '';
                $design_plain_pocket =  $is_waiscoat_order ? $product->waiscoat->design_plain_pocket : '';
                $design_four_side_pocket =  $is_waiscoat_order ? $product->waiscoat->design_four_side_pocket : '';
                $design_two_side_pocket =  $is_waiscoat_order ? $product->waiscoat->design_two_side_pocket : '';

                // coat section
                $is_coat_order = $product->coat ? true : false;
                $coat_tailor_name =  $is_coat_order ? $product->coat->tailor->name : '';
                $coat_tailor_phone =  $is_coat_order ? $product->coat->tailor->tailor_fee : '';
                $coat_qty =  $is_coat_order ? $product->coat->qty : '';
                $coat_total =  $is_coat_order ? $product->coat->qty * $product->coat->tailor->tailor_fee : '';
                $coat_height =  $is_coat_order ? $product->coat->coat_height : '';
                $coat_shoulder =  $is_coat_order ? $product->coat->coat_shoulder : '';
                $coat_sleeve =  $is_coat_order ? $product->coat->coat_sleeve : '';
                $coat_armhole_circumference =  $is_coat_order ? $product->coat->coat_armhole_circumference : '';
                $coat_bicep_circumference =  $is_coat_order ? $product->coat->coat_bicep_circumference : '';
                $coat_cuff =  $is_coat_order ? $product->coat->coat_cuff : '';
                $coat_side_width =  $is_coat_order ? $product->coat->coat_side_width : '';
                $coat_waist =  $is_coat_order ? $product->coat->coat_waist : '';
                $coat_abdomen_circumference =  $is_coat_order ? $product->coat->coat_abdomen_circumference : '';
                $coat_hip_width =  $is_coat_order ? $product->coat->coat_hip_width : '';
                $upperbody_front_length =  $is_coat_order ? $product->coat->upperbody_front_length : '';
                $upperbody_back_length =  $is_coat_order ? $product->coat->upperbody_back_length : '';
                $chest_distance =  $is_coat_order ? $product->coat->chest_distance : '';
                $coat_collar =  $is_coat_order ? $product->coat->coat_collar : '';
                $coat_style_one_button =  $is_coat_order ? $product->coat->coat_style_one_button : '';
                $coat_style_two_button =  $is_coat_order ? $product->coat->coat_style_two_button : '';
                $coat_style_three_button =  $is_coat_order ? $product->coat->coat_style_three_button : '';

                // pant section
                $is_pant_order = $product->pant ? true : false;
                $pant_tailor_name =  $is_pant_order ? $product->pant->tailor->name : '';
                $pant_tailor_phone =  $is_pant_order ? $product->pant->tailor->tailor_fee : '';
                $pant_qty =  $is_pant_order ? $product->pant->qty : '';
                $pant_total =  $is_pant_order ? $product->pant->qty * $product->pant->tailor->tailor_fee : '';
                $pant_length =  $is_pant_order ? $product->pant->pant_length : '';
                $pant_waist =  $is_pant_order ? ucwords(str_replace('_', ' ', $product->pant->pant_waist)) : '';
                $pant_thigh =  $is_pant_order ? $product->pant->pant_thigh : '';
                $pant_rise =  $is_pant_order ? $product->pant->pant_rise : '';
                $pant_hem =  $is_pant_order ? $product->pant->pant_hem : '';
                $pant_hip =  $is_pant_order ? $product->pant->pant_hip : '';
                $trouser_crotch_depth =  $is_pant_order ? $product->pant->trouser_crotch_depth : '';
                $pant_straight_loose =  $is_pant_order ? $product->pant->pant_straight_loose : '';
                $pant_straight_medium =  $is_pant_order ? $product->pant->pant_straight_medium : '';
                $pant_straight_military =  $is_pant_order ? $product->pant->pant_straight_military : '';
                $pant_straight_cuban_pocket =  $is_pant_order ? $product->pant->pant_straight_cuban_pocket : '';
                $pant_straight_classic =  $is_pant_order ? $product->pant->pant_straight_classic : '';

                // afghan cloths section
                $is_dress_order = $product->dress ? true : false;
                $dress_tailor_name =  $is_dress_order ? $product->dress->tailor->name : '';
                $dress_tailor_phone =  $is_dress_order ? $product->dress->tailor->tailor_fee : '';
                $dress_qty =  $is_dress_order ? $product->dress->qty : '';
                $dress_total =  $is_dress_order ? $product->dress->qty * $product->dress->tailor->tailor_fee : '';
                $dress_shirt_length =  $is_dress_order ? $product->dress->dress_shirt_length : '';
                $dress_sleeve =  $is_dress_order ? $product->dress->dress_sleeve : '';
                $dress_shoulder_width =  $is_dress_order ? $product->dress->dress_shoulder_width : '';
                $dress_collar =  $is_dress_order ? $product->dress->dress_collar : '';
                $dress_side_width =  $is_dress_order ? $product->dress->dress_side_width : '';
                $dress_armhole_circumference =  $is_dress_order ? $product->dress->dress_armhole_circumference : '';
                $dress_waist =  $is_dress_order ? $product->dress->dress_waist : '';
                $dress_hem =  $is_dress_order ? $product->dress->dress_hem : '';
                $dress_skirt_length =  $is_dress_order ? $product->dress->dress_skirt_length : '';
                $dress_cuff =  $is_dress_order ? $product->dress->dress_cuff : '';
                $dress_skirt_width =  $is_dress_order ? $product->dress->dress_skirt_width : '';
                $shirt_trouser_crotch_depth = $is_dress_order ? $product->dress->shirt_trouser_crotch_depth : '';
                // curtain section
                $is_curtain_order = $product->curtain ? true : false;
                $curtain_tailor_name = $is_curtain_order ? $product->curtain->tailor->name : '';
                $curtain_tailor_phone = $is_curtain_order ? $product->curtain->tailor->tailor_fee : '';
                $curtain_qty = $is_curtain_order ? $product->curtain->qty : '';
                $curtain_total = $is_curtain_order ? $product->curtain->qty * $product->curtain->tailor->tailor_fee : '';
                $fabric_type = $is_curtain_order ? $product->curtain->fabric_type : '';
                $netting_type = $is_curtain_order ? $product->curtain->netting_type : '';
                $window_count = $is_curtain_order ? $product->curtain->window_count : '';
                $door_count = $is_curtain_order ? $product->curtain->door_count : '';
                $panel_count = $is_curtain_order ? $product->curtain->panel_count : '';
                $panel_meter = $is_curtain_order ? $product->curtain->panel_meter : '';
                $middle_netting_meter = $is_curtain_order ? $product->curtain->middle_netting_meter : '';
                $pleating_type = $is_curtain_order ? $product->curtain->pleating_type : '';
                $ring_stitch_type = $is_curtain_order ? $product->curtain->ring_stitch_type : '';
                $curtain_model = $is_curtain_order ? $product->curtain->curtain_model : '';
                $mattress_count = $is_curtain_order ? $product->curtain->mattress_count : '';
                $pillow_count = $is_curtain_order ? $product->curtain->pillow_count : '';
                $bolster_count = $is_curtain_order ? $product->curtain->bolster_count : '';
                $mattress_pillow_size = $is_curtain_order ? $product->curtain->mattress_pillow_size : '';
                $pillow_mattress_model = $is_curtain_order ? $product->curtain->pillow_mattress_model : '';
                $curtain_window_details = $is_curtain_order ? $this->curtainWindowDetailText($product->curtain) : '';
                $curtain_door_details = $is_curtain_order ? $this->curtainDoorDetailText($product->curtain) : '';
                $curtain_bedding_details = $is_curtain_order ? $this->curtainBeddingDetailText($product->curtain) : '';
                // order details section
                $waiscoat_order_details =  $is_waiscoat_order ? $product->waiscoat->waiscoat_order_details : 'N/A';
                $coat_order_details =  $is_coat_order ? $product->coat->coat_order_details : 'N/A';
                $pant_order_details =  $is_pant_order ? $product->pant->pant_order_details : 'N/A';
                $dress_order_details =  $is_dress_order ? $product->dress->dress_order_details : 'N/A';
                $curtain_order_details = $is_curtain_order ? $product->curtain->curtain_order_details : 'N/A';
                
                $i = 0;
                
                if($is_waiscoat_order)
                    $i++;
                if($is_coat_order)
                    $i++;
                if($is_pant_order)
                    $i++;
                if($is_curtain_order)
                    $i++;

                $nestedData['product'] = array(
                    '[ "' . $product->code . '"',
                    ' "' . $product->type . '"',
                    ' "' . $product->getCompositionLabel() . '"',
                    ' "' . $nestedData['total_price'] . '"',
                    ' "' . $nestedData['paid_amount'] . '"',
                    ' "' . $nestedData['due_amount'] . '"',
                    ' "' . $nestedData['issue_date'] . '"',
                    ' "' . $nestedData['completion_date'] . '"',
                    ' "' . $product->customer->name . '"',
                    ' "' . $product->customer->phone_number  . '"',
                    ' "' . $product->customer->address  . '"',
                    ' "' . $product->customer->city . '"',
                    ' "' . $product->id . '"',
                    ' "' . $is_waiscoat_order . '"',
                    ' '. $i . '',
                    ' "' . trans('file.Waiscoat Order') . '"',
                    ' "' . $tailor_name . '"',
                    ' "' . $tailor_phone . '"',
                    ' "' . $waiscoat_height . '"',
                    ' "' . $waiscoat_shoulder . '"',
                    ' "' . $waiscoat_side . '"',
                    ' "' . $waiscoat_waist . '"',
                    ' "' . $waiscoat_abdomen . '"',
                    ' "' . $waiscoat_hip . '"',
                    ' "' . $design_v_neck_collar . '"',
                    ' "' . $design_round_neck_collar . '"',
                    ' "' . $design_pakistani_collar . '"',
                    ' "' . $design_zippered_pocket . '"',
                    ' "' . $design_plain_pocket . '"',
                    ' "' . $design_four_side_pocket . '"',
                    ' "' . $design_two_side_pocket . '"',
                    ' "' . $is_coat_order . '"',
                    ' '. $i . '',
                    ' "' . trans('file.Coat Order') . '"',
                    ' "' . $coat_tailor_name . '"',
                    ' "' . $coat_tailor_phone . '"',
                    ' "' . $coat_height . '"',
                    ' "' . $coat_shoulder . '"',
                    ' "' . $coat_sleeve . '"',
                    ' "' . $coat_armhole_circumference . '"',
                    ' "' . $coat_bicep_circumference . '"',
                    ' "' . $coat_cuff . '"',
                    ' "' . $coat_side_width . '"',
                    ' "' . $coat_waist . '"',
                    ' "' . $coat_abdomen_circumference . '"',
                    ' "' . $coat_hip_width . '"',
                    ' "' . $upperbody_front_length . '"',
                    ' "' . $upperbody_back_length . '"',
                    ' "' . $chest_distance . '"',
                    ' "' . $coat_collar . '"',
                    ' "' . $coat_style_one_button . '"',
                    ' "' . $coat_style_two_button . '"',
                    ' "' . $coat_style_three_button . '"',
                    ' "' . $is_pant_order . '"',
                    ' '. $i . '',
                    ' "' . trans('file.Pant Order') . '"',
                    ' "' . $pant_tailor_name . '"',
                    ' "' . $pant_tailor_phone . '"',
                    ' "' . $pant_length . '"',
                    ' "' . trans("file.$pant_waist") . '"',
                    ' "' . $pant_thigh . '"',
                    ' "' . $pant_rise . '"',
                    ' "' . $pant_hem . '"',
                    ' "' . $pant_hip . '"',
                    ' "' . $pant_straight_loose . '"',
                    ' "' . $pant_straight_medium . '"',
                    ' "' . $pant_straight_military . '"',
                    ' "' . $pant_straight_cuban_pocket . '"',
                    ' "' . $pant_straight_classic . '"',
                    ' "1' . '"',
                    ' "' . trans('file.Dress Order') . '"',
                    ' "' . $dress_tailor_name . '"',
                    ' "' . $dress_tailor_phone . '"',
                    ' "' . $dress_shirt_length . '"',
                    ' "' . $dress_sleeve . '"',
                    ' "' . $dress_shoulder_width . '"',
                    ' "' . $dress_collar . '"',
                    ' "' . $dress_side_width . '"',
                    ' "' . $dress_armhole_circumference . '"',
                    ' "' . $dress_waist . '"',
                    ' "' . $dress_hem . '"',
                    ' "' . $dress_skirt_length . '"',
                    ' "' . $dress_cuff . '"',
                    ' "' . $dress_skirt_width . '"',
                    ' "' . $waiscoat_order_details . '"',
                    ' "' . $coat_order_details . '"',
                    ' "' . $pant_order_details . '"',
                    ' "' . $dress_order_details . '"',
                    ' "' . $waiscoat_qty . '"',
                    ' "' . $waiscoat_total . '"',
                    ' "' . $coat_qty . '"',
                    ' "' . $coat_total . '"',
                    ' "' . $pant_qty . '"',
                    ' "' . $pant_total . '"',
                    ' "' . $dress_qty . '"',
                    ' "' . $dress_total . '"',
                    ' "' . $vest_chest_circumference. '"',
                    ' "' . $trouser_crotch_depth. '"',
                    ' "' . $shirt_trouser_crotch_depth . '"',
                    ' "' . $is_curtain_order . '"',
                    ' "' . $i . '"',
                    ' "' . trans('file.Curtain Order') . '"',
                    ' "' . $curtain_tailor_name . '"',
                    ' "' . $curtain_tailor_phone . '"',
                    ' "' . $fabric_type . '"',
                    ' "' . $netting_type . '"',
                    ' "' . $panel_count . '"',
                    ' "' . $panel_meter . '"',
                    ' "' . $middle_netting_meter . '"',
                    ' "' . $pleating_type . '"',
                    ' "' . $ring_stitch_type . '"',
                    ' "' . $curtain_model . '"',
                    ' "' . $mattress_count . '"',
                    ' "' . $pillow_count . '"',
                    ' "' . $bolster_count . '"',
                    ' "' . $mattress_pillow_size . '"',
                    ' "' . $pillow_mattress_model . '"',
                    ' "' . $curtain_order_details . '"',
                    ' "' . $curtain_qty . '"',
                    ' "' . $curtain_total . '"',
                    ' "' . $window_count . '"',
                    ' "' . $door_count . '"',
                    ' "' . $curtain_window_details . '"',
                    ' "' . $curtain_bedding_details . '"',
                    ' "' . $curtain_door_details . '"]'
                );
                //$nestedData['imagedata'] = DNS1D::getBarcodePNG($product->code, $product->barcode_symbology);
                $data[] = $nestedData;
            }
        }

        $json_data = array(
            "draw"            => intval($request->input('draw')),
            "recordsTotal"    => intval($totalData),
            "recordsFiltered" => intval($totalFiltered),
            "data"            => $data
        );

        echo json_encode($json_data);
    }

    public function productComplete($id)
    {
        $product = TailoringProduct::findOrFail($id);
        if ($product) {
            $product->status = 'completed';
            $product->save();
        }
        return redirect()->back()->with('create_message', 'Order updated successfully.');
    }
    public function productDeliver($id)
    {
        $role = Role::find(Auth::user()->role_id);
        if (!$role || !$role->hasPermissionTo('Tailoring-edit')) {
            return redirect()->back()->with('not_permitted', trans('file.Sorry! You are not allowed to access this module'));
        }

        $product = TailoringProduct::with('curtain')->findOrFail($id);
        if ($product->status !== 'completed' || !$product->curtain || $product->curtain->tailor_status !== 'finished') {
            return redirect()->back()->with('not_permitted', trans('file.Only finished orders can be accepted'));
        }

        DB::transaction(function () use ($product) {
            $remainingDue = round((float) $product->due_amount, 2);
            if ($remainingDue > 0) {
                app(MainCashAccount::class)->deposit(
                    $remainingDue,
                    'curtain_order_payment',
                    TailoringProduct::class,
                    $product->id,
                    $product->code,
                    trans('file.Final curtain order payment'),
                    now()
                );
            }
            $product->status = 'delivered';
            $total_price = $product->total_price;
            $product->paid_amount = $total_price;
            $product->due_amount = 0;
            $product->save();
            $this->syncTailoringSalePayment($product);

            $product->curtain->accepted_at = now();
            $product->curtain->accepted_by = Auth::id();
            $product->curtain->save();
        });

        return redirect()->back()->with('create_message', trans('file.Order accepted and delivered successfully'));
    }

    public function productReorder(Request $request, $id)
    {
        $role = Role::find(Auth::user()->role_id);
        if (!$role || !$role->hasPermissionTo('Tailoring-edit')) {
            return redirect()->back()->with('not_permitted', trans('file.Sorry! You are not allowed to access this module'));
        }

        $this->validate($request, [
            'note' => ['required', 'string', 'max:2000'],
        ]);

        $product = TailoringProduct::with('curtain')->findOrFail($id);
        if ($product->status !== 'completed' || !$product->curtain || $product->curtain->tailor_status !== 'finished') {
            return redirect()->back()->with('not_permitted', trans('file.Only finished orders can be re-ordered'));
        }

        DB::transaction(function () use ($product, $request) {
            CurtainReorder::create([
                'curtain_id' => $product->curtain->id,
                'note' => trim($request->note),
                'reordered_by' => Auth::id(),
                'reordered_at' => now(),
            ]);

            $product->status = 'pending';
            $product->save();

            $product->curtain->tailor_status = 'reordered';
            $product->curtain->tailor_finished_at = null;
            $product->curtain->accepted_at = null;
            $product->curtain->accepted_by = null;
            $product->curtain->save();
        });

        return redirect()->route('tailoringproducts.index')
            ->with('create_message', trans('file.Order sent back to tailor successfully'));
    }

    public function reorderHistory($id)
    {
        $role = Role::find(Auth::user()->role_id);
        if (!$role || !$role->hasPermissionTo('Tailoring-index')) {
            abort(403);
        }

        $product = TailoringProduct::with('curtain.reorders.reorderedBy')
            ->where('type', 'Curtain')
            ->findOrFail($id);

        return response()->json([
            'code' => $product->code,
            'reorders' => $product->curtain
                ? $product->curtain->reorders->map(function ($reorder) {
                    return [
                        'note' => $reorder->note,
                        'reordered_at' => optional($reorder->reordered_at)->format('d-m-Y H:i'),
                        'resolved_at' => optional($reorder->resolved_at)->format('d-m-Y H:i'),
                        'reordered_by' => optional($reorder->reorderedBy)->name ?: 'N/A',
                    ];
                })->values()
                : [],
        ]);
    }

    public function deletebyselection(Request $request)
    {
        $product_id = $request['productIdArray'];
        DB::beginTransaction();
        try {
            foreach ($product_id as $id) {
                $lims_product_data = TailoringProduct::findOrFail($id);
                $this->deactivateTailoringProduct($lims_product_data);
            }
            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            return response($e->getMessage(), 422);
        }
        $this->cacheForget('product_list');
        $this->cacheForget('product_list_with_variant');
        return 'Product deleted successfully!';
    }



    public function print($id)
    {
        $general_setting = collect();
        if(cache()->has('general_setting')){
            $general_setting = cache()->get('general_setting'); 
        }
        else{
            $general_setting = DB::table('general_settings')->latest()->first();
        }
        $product = TailoringProduct::with('waiscoat', 'coat', 'pant', 'dress', 'curtain', 'customer', 'product')->findOrFail($id);

        if ($product->type == 'Curtain') {
            return view('backend.tailoringproduct.printCurtain', compact('product','general_setting'));
        }

        return view('backend.tailoringproduct.print', compact('product','general_setting'));
    }
    public function printTailor($type, $id)
    {
        switch ($type) {
            case 'waiscoat':
                $product = Waiscoat::findOrFail($id);
                break;
            case 'coat':
                $product = Coat::findOrFail($id);
                break;
            case 'pant':
                $product = Pant::findOrFail($id);
                break;
            case 'dress':
                $product = Dress::findOrFail($id);
                break;
            case 'curtain':
                $product = Curtain::findOrFail($id);
                break;
            default:
                abort(404);
        }

        $currentTailor = Tailor::where('user_id', Auth::id())->where('is_active', true)->first();
        if ($currentTailor && (int) $product->tailor_id !== (int) $currentTailor->id) {
            abort(403);
        }

        return view('backend.tailoringproduct.printTailor', compact('product'));
    }
    public function completedIndex()
    {
        $role = Role::find(Auth::user()->role_id);
        if ($role->hasPermissionTo('Tailoring-index')) {
            $permissions = Role::findByName($role->name)->permissions;
            foreach ($permissions as $permission)
                $all_permission[] = $permission->name;
            if (empty($all_permission))
                $all_permission[] = 'dummy text';
            $role_id = $role->id;
            $numberOfProduct = TailoringProduct::where([['status', 'completed'], ['is_active', true], ['type', 'Curtain']])->count();

            return view('backend.tailoringproduct.completedIndex', compact('all_permission', 'role_id', 'numberOfProduct'));
        } else
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
    }
    public function deliveredIndex()
    {
        $role = Role::find(Auth::user()->role_id);
        if ($role->hasPermissionTo('Tailoring-index')) {
            $permissions = Role::findByName($role->name)->permissions;
            foreach ($permissions as $permission)
                $all_permission[] = $permission->name;
            if (empty($all_permission))
                $all_permission[] = 'dummy text';
            $role_id = $role->id;
            $numberOfProduct = TailoringProduct::where([['status', 'delivered'], ['is_active', true], ['type', 'Curtain']])->count();

            return view('backend.tailoringproduct.deliveredIndex', compact('all_permission', 'role_id', 'numberOfProduct'));
        } else
            return redirect()->back()->with('not_permitted', 'Sorry! You are not allowed to access this module');
    }
    public function completedProductData(Request $request)
    {
        $columns = array(
            2 => 'code',
            3 => 'customer_id',
            4 => 'type',
            5 => 'total_price',
            6 => 'paid_amount',
            7 => 'due_amount',
            8 => 'created_at',
            9 => 'completion_date',
        );

        $totalData = TailoringProduct::where([['status', 'completed'], ['is_active', true], ['type', 'Curtain']])->count();
        $totalFiltered = $totalData;

        if ($request->input('length') != -1)
            $limit = $request->input('length');
        else
            $limit = $totalData;
        $start = $request->input('start');
        $orderColumn = $columns[$request->input('order.0.column')] ?? 'created_at';
        $order = 'tailoring_products.' . $orderColumn;

        $dir = in_array($request->input('order.0.dir'), ['asc', 'desc']) ? $request->input('order.0.dir') : 'desc';
        if (empty($request->input('search.value'))) {

            $products = TailoringProduct::with('waiscoat', 'coat.tailor', 'pant', 'dress', 'curtain.reorders.reorderedBy', 'customer')
                ->latest()
                ->offset($start)
                ->where([['status', 'completed'], ['is_active', true], ['type', 'Curtain']])
                ->limit($limit)
                ->orderBy($order, $dir)
                ->get();
        } else {
            $search = $request->input('search.value');
            $products =  TailoringProduct::select('tailoring_products.*')->where([['is_active', true], ['tailoring_products.status', 'completed'], ['tailoring_products.type', 'Curtain']])
                ->with('waiscoat', 'coat', 'pant', 'dress', 'curtain.reorders.reorderedBy', 'customer')
                ->WhereHas('customer', function ($query) use ($search) {
                    $query->where([
                        ['customers.name', 'LIKE', "%{$search}%"],
                        ['customers.is_active', true]
                    ])
                        ->orWhere([
                            ['customers.phone_number', 'LIKE', "%{$search}%"],
                            ['customers.is_active', true]
                        ]);
                })
                ->orWhere([
                    ['tailoring_products.type', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'completed'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->orWhere([
                    ['tailoring_products.code', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'completed'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->latest()
                ->offset($start)
                ->limit($limit)
                ->orderBy($order, $dir)->get();

            $totalFiltered = TailoringProduct::select('tailoring_products.*')->where([['is_active', true], ['tailoring_products.status', 'completed'], ['tailoring_products.type', 'Curtain']])
                ->with('waiscoat', 'coat', 'pant', 'dress', 'curtain.reorders.reorderedBy', 'customer')
                ->WhereHas('customer', function ($query) use ($search) {
                    $query->where([
                        ['customers.name', 'LIKE', "%{$search}%"],
                        ['customers.is_active', true]
                    ])
                        ->orWhere([
                            ['customers.phone_number', 'LIKE', "%{$search}%"],
                            ['customers.is_active', true]
                        ]);
                })
                ->orWhere([
                    ['tailoring_products.type', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'completed'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->orWhere([
                    ['tailoring_products.code', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'completed'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->count();
        }
        $data = array();
        if (!empty($products)) {
            foreach ($products as $key => $product) {
                $nestedData['id'] = $product->id;
                $nestedData['key'] = $key;
                $nestedData['code'] = $product->code;
                $nestedData['customer_name'] = $product->customer->name;
                $nestedData['customer_phone'] = $product->customer->phone_number;
                $nestedData['category'] = trans('file.' . $product->type . '');
                $nestedData['status'] = '<div class="badge badge-success">' . trans('file.completed_order') . '</div>';
                $nestedData['total_price'] = number_format($product->total_price, config('decimal'));
                $nestedData['paid_amount'] = number_format($product->paid_amount, config('decimal'));
                $nestedData['due_amount'] = number_format($product->due_amount, config('decimal'));
                $nestedData['issue_date'] = date(config('date_format'), strtotime($product->created_at->toDateString()));
                $nestedData['completion_date'] = date(config('date_format'), strtotime($product->completion_date->toDateString()));


                $nestedData['options'] = '<div class="btn-group">
                            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . trans("file.action") . '
                              <span class="caret"></span>
                              <span class="sr-only">Toggle Dropdown</span>
                            </button>
                            <ul class="dropdown-menu edit-options dropdown-menu-right dropdown-default" user="menu">
                            <li>
                                <button="type" class="btn btn-link view"><i class="fa fa-eye"></i> ' . trans('file.View') . '</button>
                            </li>';
                if (in_array("Tailoring-edit", $request['all_permission'])) {
                    $nestedData['options'] .= '
                        <li>
                            <form method="POST" action="' . route('tailoringproducts.deliver', $product->id) . '">
                                ' . csrf_field() . '
                                <button type="submit" class="btn btn-link" onclick="return confirm(\'' . addslashes(trans('file.Accept and deliver this order?')) . '\')">
                                    <i class="fa fa-check"></i> ' . trans('file.Accept & Deliver') . '
                                </button>
                            </form>
                        </li>
                        <li>
                            <button type="button" class="btn btn-link text-warning reorder-order"
                                    data-id="' . $product->id . '" data-code="' . e($product->code) . '">
                                <i class="fa fa-repeat"></i> ' . trans('file.Re-order') . '
                            </button>
                        </li>';
                    if ($product->curtain && $product->curtain->reorders->count()) {
                        $nestedData['options'] .= '
                        <li>
                            <button type="button" class="btn btn-link view-reorder-history"
                                    data-id="' . $product->id . '" data-code="' . e($product->code) . '">
                                <i class="fa fa-history"></i> ' . trans('file.Re-order History') . '
                            </button>
                        </li>';
                    }
                }

                if (in_array("Tailoring-delete", $request['all_permission'])) {
                    $nestedData['options'] .= \Form::open(["route" => ["tailoringproducts.destroy", $product->id], "method" => "DELETE"]) . '
                            <li>
                              <button type="submit" class="btn btn-link" onclick="return confirmDelete()"><i class="fa fa-trash"></i> ' . trans("file.delete") . '</button>
                            </li>' . \Form::close() . '
                        </ul>
                    </div>';
                }

                // data for product details by one click
                $is_waiscoat_order = $product->waiscoat ? true : false;
                $tailor_name =  $is_waiscoat_order ? $product->waiscoat->tailor->name : '';
                $tailor_phone =  $is_waiscoat_order ? $product->waiscoat->tailor->tailor_fee : '';
                $waiscoat_qty =  $is_waiscoat_order ? $product->waiscoat->qty : '';
                $waiscoat_total =  $is_waiscoat_order ? $product->waiscoat->qty * $product->waiscoat->tailor->tailor_fee : '';
                $waiscoat_height =  $is_waiscoat_order ? $product->waiscoat->waiscoat_height : '';
                $waiscoat_shoulder =  $is_waiscoat_order ? $product->waiscoat->waiscoat_shoulder : '';
                $waiscoat_side =  $is_waiscoat_order ? $product->waiscoat->waiscoat_side : '';
                $waiscoat_waist =  $is_waiscoat_order ? $product->waiscoat->waiscoat_waist : '';
                $waiscoat_abdomen =  $is_waiscoat_order ? $product->waiscoat->waiscoat_abdomen : '';
                $waiscoat_hip =  $is_waiscoat_order ? $product->waiscoat->waiscoat_hip : '';
                $vest_chest_circumference =  $is_waiscoat_order ? $product->waiscoat->vest_chest_circumference : '';
                $design_v_neck_collar =  $is_waiscoat_order ? $product->waiscoat->design_v_neck_collar : '';
                $design_round_neck_collar =  $is_waiscoat_order ? $product->waiscoat->design_round_neck_collar : '';
                $design_pakistani_collar =  $is_waiscoat_order ? $product->waiscoat->design_pakistani_collar : '';
                $design_zippered_pocket =  $is_waiscoat_order ? $product->waiscoat->design_zippered_pocket : '';
                $design_plain_pocket =  $is_waiscoat_order ? $product->waiscoat->design_plain_pocket : '';
                $design_four_side_pocket =  $is_waiscoat_order ? $product->waiscoat->design_four_side_pocket : '';
                $design_two_side_pocket =  $is_waiscoat_order ? $product->waiscoat->design_two_side_pocket : '';

                // coat section
                $is_coat_order = $product->coat ? true : false;
                $coat_tailor_name =  $is_coat_order ? $product->coat->tailor->name : '';
                $coat_tailor_phone =  $is_coat_order ? $product->coat->tailor->tailor_fee : '';
                $coat_qty =  $is_coat_order ? $product->coat->qty : '';
                $coat_total =  $is_coat_order ? $product->coat->qty * $product->coat->tailor->tailor_fee : '';
                $coat_height =  $is_coat_order ? $product->coat->coat_height : '';
                $coat_shoulder =  $is_coat_order ? $product->coat->coat_shoulder : '';
                $coat_sleeve =  $is_coat_order ? $product->coat->coat_sleeve : '';
                $coat_armhole_circumference =  $is_coat_order ? $product->coat->coat_armhole_circumference : '';
                $coat_bicep_circumference =  $is_coat_order ? $product->coat->coat_bicep_circumference : '';
                $coat_cuff =  $is_coat_order ? $product->coat->coat_cuff : '';
                $coat_side_width =  $is_coat_order ? $product->coat->coat_side_width : '';
                $coat_waist =  $is_coat_order ? $product->coat->coat_waist : '';
                $coat_abdomen_circumference =  $is_coat_order ? $product->coat->coat_abdomen_circumference : '';
                $coat_hip_width =  $is_coat_order ? $product->coat->coat_hip_width : '';
                $upperbody_front_length =  $is_coat_order ? $product->coat->upperbody_front_length : '';
                $upperbody_back_length =  $is_coat_order ? $product->coat->upperbody_back_length : '';
                $chest_distance =  $is_coat_order ? $product->coat->chest_distance : '';
                $coat_collar =  $is_coat_order ? $product->coat->coat_collar : '';
                $coat_style_one_button =  $is_coat_order ? $product->coat->coat_style_one_button : '';
                $coat_style_two_button =  $is_coat_order ? $product->coat->coat_style_two_button : '';
                $coat_style_three_button =  $is_coat_order ? $product->coat->coat_style_three_button : '';

                // pant section
                $is_pant_order = $product->pant ? true : false;
                $pant_tailor_name =  $is_pant_order ? $product->pant->tailor->name : '';
                $pant_tailor_phone =  $is_pant_order ? $product->pant->tailor->tailor_fee : '';
                $pant_qty =  $is_pant_order ? $product->pant->qty : '';
                $pant_total =  $is_pant_order ? $product->pant->qty * $product->pant->tailor->tailor_fee : '';
                $pant_length =  $is_pant_order ? $product->pant->pant_length : '';
                $pant_waist =  $is_pant_order ? ucwords(str_replace('_', ' ', $product->pant->pant_waist)) : '';
                $pant_thigh =  $is_pant_order ? $product->pant->pant_thigh : '';
                $pant_rise =  $is_pant_order ? $product->pant->pant_rise : '';
                $pant_hem =  $is_pant_order ? $product->pant->pant_hem : '';
                $pant_hip =  $is_pant_order ? $product->pant->pant_hip : '';
                $trouser_crotch_depth =  $is_pant_order ? $product->pant->trouser_crotch_depth : '';
                $pant_straight_loose =  $is_pant_order ? $product->pant->pant_straight_loose : '';
                $pant_straight_medium =  $is_pant_order ? $product->pant->pant_straight_medium : '';
                $pant_straight_military =  $is_pant_order ? $product->pant->pant_straight_military : '';
                $pant_straight_cuban_pocket =  $is_pant_order ? $product->pant->pant_straight_cuban_pocket : '';
                $pant_straight_classic =  $is_pant_order ? $product->pant->pant_straight_classic : '';

                // afghan cloths section
                $is_dress_order = $product->dress ? true : false;
                $dress_tailor_name =  $is_dress_order ? $product->dress->tailor->name : '';
                $dress_tailor_phone =  $is_dress_order ? $product->dress->tailor->tailor_fee : '';
                $dress_qty =  $is_dress_order ? $product->dress->qty : '';
                $dress_total =  $is_dress_order ? $product->dress->qty * $product->dress->tailor->tailor_fee : '';
                $dress_shirt_length =  $is_dress_order ? $product->dress->dress_shirt_length : '';
                $dress_sleeve =  $is_dress_order ? $product->dress->dress_sleeve : '';
                $dress_shoulder_width =  $is_dress_order ? $product->dress->dress_shoulder_width : '';
                $dress_collar =  $is_dress_order ? $product->dress->dress_collar : '';
                $dress_side_width =  $is_dress_order ? $product->dress->dress_side_width : '';
                $dress_armhole_circumference =  $is_dress_order ? $product->dress->dress_armhole_circumference : '';
                $dress_waist =  $is_dress_order ? $product->dress->dress_waist : '';
                $dress_hem =  $is_dress_order ? $product->dress->dress_hem : '';
                $dress_skirt_length =  $is_dress_order ? $product->dress->dress_skirt_length : '';
                $dress_cuff =  $is_dress_order ? $product->dress->dress_cuff : '';
                $dress_skirt_width =  $is_dress_order ? $product->dress->dress_skirt_width : '';
                $shirt_trouser_crotch_depth = $is_dress_order ? $product->dress->shirt_trouser_crotch_depth : '';
                // curtain section
                $is_curtain_order = $product->curtain ? true : false;
                $curtain_tailor_name = $is_curtain_order ? $product->curtain->tailor->name : '';
                $curtain_tailor_phone = $is_curtain_order ? $product->curtain->tailor->tailor_fee : '';
                $curtain_qty = $is_curtain_order ? $product->curtain->qty : '';
                $curtain_total = $is_curtain_order ? $product->curtain->qty * $product->curtain->tailor->tailor_fee : '';
                $fabric_type = $is_curtain_order ? $product->curtain->fabric_type : '';
                $netting_type = $is_curtain_order ? $product->curtain->netting_type : '';
                $window_count = $is_curtain_order ? $product->curtain->window_count : '';
                $door_count = $is_curtain_order ? $product->curtain->door_count : '';
                $panel_count = $is_curtain_order ? $product->curtain->panel_count : '';
                $panel_meter = $is_curtain_order ? $product->curtain->panel_meter : '';
                $middle_netting_meter = $is_curtain_order ? $product->curtain->middle_netting_meter : '';
                $pleating_type = $is_curtain_order ? $product->curtain->pleating_type : '';
                $ring_stitch_type = $is_curtain_order ? $product->curtain->ring_stitch_type : '';
                $curtain_model = $is_curtain_order ? $product->curtain->curtain_model : '';
                $mattress_count = $is_curtain_order ? $product->curtain->mattress_count : '';
                $pillow_count = $is_curtain_order ? $product->curtain->pillow_count : '';
                $bolster_count = $is_curtain_order ? $product->curtain->bolster_count : '';
                $mattress_pillow_size = $is_curtain_order ? $product->curtain->mattress_pillow_size : '';
                $pillow_mattress_model = $is_curtain_order ? $product->curtain->pillow_mattress_model : '';
                $curtain_window_details = $is_curtain_order ? $this->curtainWindowDetailText($product->curtain) : '';
                $curtain_door_details = $is_curtain_order ? $this->curtainDoorDetailText($product->curtain) : '';
                $curtain_bedding_details = $is_curtain_order ? $this->curtainBeddingDetailText($product->curtain) : '';

                // order details section
                $waiscoat_order_details =  $is_waiscoat_order ? $product->waiscoat->waiscoat_order_details : 'N/A';
                $coat_order_details =  $is_coat_order ? $product->coat->coat_order_details : 'N/A';
                $pant_order_details =  $is_pant_order ? $product->pant->pant_order_details : 'N/A';
                $dress_order_details =  $is_dress_order ? $product->dress->dress_order_details : 'N/A';
                $curtain_order_details = $is_curtain_order ? $product->curtain->curtain_order_details : 'N/A';



                $nestedData['product'] = array(
                    '[ "' . $product->code . '"',
                    ' "' . $product->type . '"',
                    ' "' . $product->getCompositionLabel() . '"',
                    ' "' . $nestedData['total_price'] . '"',
                    ' "' . $nestedData['paid_amount'] . '"',
                    ' "' . $nestedData['due_amount'] . '"',
                    ' "' . $nestedData['issue_date'] . '"',
                    ' "' . $nestedData['completion_date'] . '"',
                    ' "' . $product->customer->name . '"',
                    ' "' . $product->customer->phone_number  . '"',
                    ' "' . $product->customer->address  . '"',
                    ' "' . $product->customer->city . '"',
                    ' "' . $product->id . '"',
                    ' "' . $is_waiscoat_order . '"',
                    ' "1' . '"',
                    ' "' . trans('file.Waiscoat Order') . '"',
                    ' "' . $tailor_name . '"',
                    ' "' . $tailor_phone . '"',
                    ' "' . $waiscoat_height . '"',
                    ' "' . $waiscoat_shoulder . '"',
                    ' "' . $waiscoat_side . '"',
                    ' "' . $waiscoat_waist . '"',
                    ' "' . $waiscoat_abdomen . '"',
                    ' "' . $waiscoat_hip . '"',
                    ' "' . $design_v_neck_collar . '"',
                    ' "' . $design_round_neck_collar . '"',
                    ' "' . $design_pakistani_collar . '"',
                    ' "' . $design_zippered_pocket . '"',
                    ' "' . $design_plain_pocket . '"',
                    ' "' . $design_four_side_pocket . '"',
                    ' "' . $design_two_side_pocket . '"',
                    ' "' . $is_coat_order . '"',
                    ' "2' . '"',
                    ' "' . trans('file.Coat Order') . '"',
                    ' "' . $coat_tailor_name . '"',
                    ' "' . $coat_tailor_phone . '"',
                    ' "' . $coat_height . '"',
                    ' "' . $coat_shoulder . '"',
                    ' "' . $coat_sleeve . '"',
                    ' "' . $coat_armhole_circumference . '"',
                    ' "' . $coat_bicep_circumference . '"',
                    ' "' . $coat_cuff . '"',
                    ' "' . $coat_side_width . '"',
                    ' "' . $coat_waist . '"',
                    ' "' . $coat_abdomen_circumference . '"',
                    ' "' . $coat_hip_width . '"',
                    ' "' . $upperbody_front_length . '"',
                    ' "' . $upperbody_back_length . '"',
                    ' "' . $chest_distance . '"',
                    ' "' . $coat_collar . '"',
                    ' "' . $coat_style_one_button . '"',
                    ' "' . $coat_style_two_button . '"',
                    ' "' . $coat_style_three_button . '"',
                    ' "' . $is_pant_order . '"',
                    ' "3' . '"',
                    ' "' . trans('file.Pant Order') . '"',
                    ' "' . $pant_tailor_name . '"',
                    ' "' . $pant_tailor_phone . '"',
                    ' "' . $pant_length . '"',
                    ' "' . trans("file.$pant_waist") . '"',
                    ' "' . $pant_thigh . '"',
                    ' "' . $pant_rise . '"',
                    ' "' . $pant_hem . '"',
                    ' "' . $pant_hip . '"',
                    ' "' . $pant_straight_loose . '"',
                    ' "' . $pant_straight_medium . '"',
                    ' "' . $pant_straight_military . '"',
                    ' "' . $pant_straight_cuban_pocket . '"',
                    ' "' . $pant_straight_classic . '"',
                    ' "1' . '"',
                    ' "' . trans('file.Dress Order') . '"',
                    ' "' . $dress_tailor_name . '"',
                    ' "' . $dress_tailor_phone . '"',
                    ' "' . $dress_shirt_length . '"',
                    ' "' . $dress_sleeve . '"',
                    ' "' . $dress_shoulder_width . '"',
                    ' "' . $dress_collar . '"',
                    ' "' . $dress_side_width . '"',
                    ' "' . $dress_armhole_circumference . '"',
                    ' "' . $dress_waist . '"',
                    ' "' . $dress_hem . '"',
                    ' "' . $dress_skirt_length . '"',
                    ' "' . $dress_cuff . '"',
                    ' "' . $dress_skirt_width . '"',
                    ' "' . $waiscoat_order_details . '"',
                    ' "' . $coat_order_details . '"',
                    ' "' . $pant_order_details . '"',
                    ' "' . $dress_order_details . '"',
                    ' "' . $waiscoat_qty . '"',
                    ' "' . $waiscoat_total . '"',
                    ' "' . $coat_qty . '"',
                    ' "' . $coat_total . '"',
                    ' "' . $pant_qty . '"',
                    ' "' . $pant_total . '"',
                    ' "' . $dress_qty . '"',
                    ' "' . $dress_total . '"',
                    ' "' . $vest_chest_circumference. '"',
                    ' "' . $trouser_crotch_depth. '"',
                    ' "' . $shirt_trouser_crotch_depth . '"',
                    ' "' . $is_curtain_order . '"',
                    ' "1"',
                    ' "' . trans('file.Curtain Order') . '"',
                    ' "' . $curtain_tailor_name . '"',
                    ' "' . $curtain_tailor_phone . '"',
                    ' "' . $fabric_type . '"',
                    ' "' . $netting_type . '"',
                    ' "' . $panel_count . '"',
                    ' "' . $panel_meter . '"',
                    ' "' . $middle_netting_meter . '"',
                    ' "' . $pleating_type . '"',
                    ' "' . $ring_stitch_type . '"',
                    ' "' . $curtain_model . '"',
                    ' "' . $mattress_count . '"',
                    ' "' . $pillow_count . '"',
                    ' "' . $bolster_count . '"',
                    ' "' . $mattress_pillow_size . '"',
                    ' "' . $pillow_mattress_model . '"',
                    ' "' . $curtain_order_details . '"',
                    ' "' . $curtain_qty . '"',
                    ' "' . $curtain_total . '"',
                    ' "' . $window_count . '"',
                    ' "' . $door_count . '"',
                    ' "' . $curtain_window_details . '"',
                    ' "' . $curtain_bedding_details . '"',
                    ' "' . $curtain_door_details . '"]'
                );
                //$nestedData['imagedata'] = DNS1D::getBarcodePNG($product->code, $product->barcode_symbology);
                $data[] = $nestedData;
            }
        }

        $json_data = array(
            "draw"            => intval($request->input('draw')),
            "recordsTotal"    => intval($totalData),
            "recordsFiltered" => intval($totalFiltered),
            "data"            => $data
        );

        echo json_encode($json_data);
    }
    public function deliveredProductData(Request $request)
    {
        $columns = array(
            2 => 'code',
            3 => 'customer_id',
            4 => 'type',
            5 => 'total_price',
            6 => 'paid_amount',
            7 => 'due_amount',
            8 => 'created_at',
            9 => 'completion_date',
        );

        $totalData = TailoringProduct::where([['status', 'delivered'], ['is_active', true], ['type', 'Curtain']])->count();
        $totalFiltered = $totalData;

        if ($request->input('length') != -1)
            $limit = $request->input('length');
        else
            $limit = $totalData;
        $start = $request->input('start');
        $orderColumn = $columns[$request->input('order.0.column')] ?? 'created_at';
        $order = 'tailoring_products.' . $orderColumn;

        $dir = in_array($request->input('order.0.dir'), ['asc', 'desc']) ? $request->input('order.0.dir') : 'desc';
        if (empty($request->input('search.value'))) {

            $products = TailoringProduct::with('waiscoat', 'coat.tailor', 'pant', 'dress', 'curtain', 'customer')
                ->latest()
                ->offset($start)
                ->where([['status', 'delivered'], ['is_active', true], ['type', 'Curtain']])
                ->limit($limit)
                ->orderBy($order, $dir)
                ->get();
        } else {
            $search = $request->input('search.value');
            $products =  TailoringProduct::select('tailoring_products.*')->where([['is_active', true], ['tailoring_products.status', 'delivered'], ['tailoring_products.type', 'Curtain']])
                ->with('waiscoat', 'coat', 'pant', 'dress', 'curtain', 'customer')
                ->WhereHas('customer', function ($query) use ($search) {
                    $query->where([
                        ['customers.name', 'LIKE', "%{$search}%"],
                        ['customers.is_active', true]
                    ])
                        ->orWhere([
                            ['customers.phone_number', 'LIKE', "%{$search}%"],
                            ['customers.is_active', true]
                        ]);
                })
                ->orWhere([
                    ['tailoring_products.type', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'delivered'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->orWhere([
                    ['tailoring_products.code', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'delivered'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->latest()
                ->offset($start)
                ->limit($limit)
                ->orderBy($order, $dir)->get();

            $totalFiltered = TailoringProduct::select('tailoring_products.*')->where([['is_active', true], ['tailoring_products.status', 'delivered'], ['tailoring_products.type', 'Curtain']])
                ->with('waiscoat', 'coat', 'pant', 'dress', 'curtain', 'customer')
                ->WhereHas('customer', function ($query) use ($search) {
                    $query->where([
                        ['customers.name', 'LIKE', "%{$search}%"],
                        ['customers.is_active', true]
                    ])
                        ->orWhere([
                            ['customers.phone_number', 'LIKE', "%{$search}%"],
                            ['customers.is_active', true]
                        ]);
                })
                ->orWhere([
                    ['tailoring_products.type', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'delivered'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->orWhere([
                    ['tailoring_products.code', 'LIKE', "%{$search}%"],
                    ['tailoring_products.status', 'delivered'],
                    ['tailoring_products.is_active', true],
                    ['tailoring_products.type', 'Curtain'],
                ])
                ->count();
        }
        $data = array();
        if (!empty($products)) {
            foreach ($products as $key => $product) {
                $nestedData['id'] = $product->id;
                $nestedData['key'] = $key;
                $nestedData['code'] = $product->code;
                $nestedData['customer_name'] = $product->customer->name;
                $nestedData['customer_phone'] = $product->customer->phone_number;
                $nestedData['category'] = trans('file.' . $product->type . '');
                $nestedData['status'] = '<div class="badge badge-success">' . trans('file.delivered_order') . '</div>';
                $nestedData['total_price'] = number_format($product->total_price, config('decimal'));
                $nestedData['paid_amount'] = number_format($product->paid_amount, config('decimal'));
                $nestedData['due_amount'] = number_format($product->due_amount, config('decimal'));
                $nestedData['issue_date'] = date(config('date_format'), strtotime($product->created_at->toDateString()));
                $nestedData['completion_date'] = date(config('date_format'), strtotime($product->completion_date->toDateString()));


                $nestedData['options'] = '<div class="btn-group">
                            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' . trans("file.action") . '
                              <span class="caret"></span>
                              <span class="sr-only">Toggle Dropdown</span>
                            </button>
                            <ul class="dropdown-menu edit-options dropdown-menu-right dropdown-default" user="menu">
                            <li>
                                <button="type" class="btn btn-link view"><i class="fa fa-eye"></i> ' . trans('file.View') . '</button>
                            </li>';


                if (in_array("Tailoring-delete", $request['all_permission'])) {
                    $nestedData['options'] .= \Form::open(["route" => ["tailoringproducts.destroy", $product->id], "method" => "DELETE"]) . '
                            <li>
                              <button type="submit" class="btn btn-link" onclick="return confirmDelete()"><i class="fa fa-trash"></i> ' . trans("file.delete") . '</button>
                            </li>' . \Form::close() . '
                        </ul>
                    </div>';
                }

                // data for product details by one click
                $is_waiscoat_order = $product->waiscoat ? true : false;
                $tailor_name =  $is_waiscoat_order ? $product->waiscoat->tailor->name : '';
                $tailor_phone =  $is_waiscoat_order ? $product->waiscoat->tailor->tailor_fee : '';
                $waiscoat_qty =  $is_waiscoat_order ? $product->waiscoat->qty : '';
                $waiscoat_total =  $is_waiscoat_order ? $product->waiscoat->qty * $product->waiscoat->tailor->tailor_fee : '';
                $waiscoat_height =  $is_waiscoat_order ? $product->waiscoat->waiscoat_height : '';
                $waiscoat_shoulder =  $is_waiscoat_order ? $product->waiscoat->waiscoat_shoulder : '';
                $waiscoat_side =  $is_waiscoat_order ? $product->waiscoat->waiscoat_side : '';
                $waiscoat_waist =  $is_waiscoat_order ? $product->waiscoat->waiscoat_waist : '';
                $waiscoat_abdomen =  $is_waiscoat_order ? $product->waiscoat->waiscoat_abdomen : '';
                $waiscoat_hip =  $is_waiscoat_order ? $product->waiscoat->waiscoat_hip : '';
                $vest_chest_circumference =  $is_waiscoat_order ? $product->waiscoat->vest_chest_circumference : '';
                $design_v_neck_collar =  $is_waiscoat_order ? $product->waiscoat->design_v_neck_collar : '';
                $design_round_neck_collar =  $is_waiscoat_order ? $product->waiscoat->design_round_neck_collar : '';
                $design_pakistani_collar =  $is_waiscoat_order ? $product->waiscoat->design_pakistani_collar : '';
                $design_zippered_pocket =  $is_waiscoat_order ? $product->waiscoat->design_zippered_pocket : '';
                $design_plain_pocket =  $is_waiscoat_order ? $product->waiscoat->design_plain_pocket : '';
                $design_four_side_pocket =  $is_waiscoat_order ? $product->waiscoat->design_four_side_pocket : '';
                $design_two_side_pocket =  $is_waiscoat_order ? $product->waiscoat->design_two_side_pocket : '';

                // coat section
                $is_coat_order = $product->coat ? true : false;
                $coat_tailor_name =  $is_coat_order ? $product->coat->tailor->name : '';
                $coat_tailor_phone =  $is_coat_order ? $product->coat->tailor->tailor_fee : '';
                $coat_qty =  $is_coat_order ? $product->coat->qty : '';
                $coat_total =  $is_coat_order ? $product->coat->qty * $product->coat->tailor->tailor_fee : '';
                $coat_height =  $is_coat_order ? $product->coat->coat_height : '';
                $coat_shoulder =  $is_coat_order ? $product->coat->coat_shoulder : '';
                $coat_sleeve =  $is_coat_order ? $product->coat->coat_sleeve : '';
                $coat_armhole_circumference =  $is_coat_order ? $product->coat->coat_armhole_circumference : '';
                $coat_bicep_circumference =  $is_coat_order ? $product->coat->coat_bicep_circumference : '';
                $coat_cuff =  $is_coat_order ? $product->coat->coat_cuff : '';
                $coat_side_width =  $is_coat_order ? $product->coat->coat_side_width : '';
                $coat_waist =  $is_coat_order ? $product->coat->coat_waist : '';
                $coat_abdomen_circumference =  $is_coat_order ? $product->coat->coat_abdomen_circumference : '';
                $coat_hip_width =  $is_coat_order ? $product->coat->coat_hip_width : '';
                $upperbody_front_length =  $is_coat_order ? $product->coat->upperbody_front_length : '';
                $upperbody_back_length =  $is_coat_order ? $product->coat->upperbody_back_length : '';
                $chest_distance =  $is_coat_order ? $product->coat->chest_distance : '';
                $coat_collar =  $is_coat_order ? $product->coat->coat_collar : '';
                $coat_style_one_button =  $is_coat_order ? $product->coat->coat_style_one_button : '';
                $coat_style_two_button =  $is_coat_order ? $product->coat->coat_style_two_button : '';
                $coat_style_three_button =  $is_coat_order ? $product->coat->coat_style_three_button : '';

                // pant section
                $is_pant_order = $product->pant ? true : false;
                $pant_tailor_name =  $is_pant_order ? $product->pant->tailor->name : '';
                $pant_tailor_phone =  $is_pant_order ? $product->pant->tailor->tailor_fee : '';
                $pant_qty =  $is_pant_order ? $product->pant->qty : '';
                $pant_total =  $is_pant_order ? $product->pant->qty * $product->pant->tailor->tailor_fee : '';
                $pant_length =  $is_pant_order ? $product->pant->pant_length : '';
                $pant_waist =  $is_pant_order ? ucwords(str_replace('_', ' ', $product->pant->pant_waist)) : '';
                $pant_thigh =  $is_pant_order ? $product->pant->pant_thigh : '';
                $pant_rise =  $is_pant_order ? $product->pant->pant_rise : '';
                $pant_hem =  $is_pant_order ? $product->pant->pant_hem : '';
                $pant_hip =  $is_pant_order ? $product->pant->pant_hip : '';
                $trouser_crotch_depth =  $is_pant_order ? $product->pant->trouser_crotch_depth : '';
                $pant_straight_loose =  $is_pant_order ? $product->pant->pant_straight_loose : '';
                $pant_straight_medium =  $is_pant_order ? $product->pant->pant_straight_medium : '';
                $pant_straight_military =  $is_pant_order ? $product->pant->pant_straight_military : '';
                $pant_straight_cuban_pocket =  $is_pant_order ? $product->pant->pant_straight_cuban_pocket : '';
                $pant_straight_classic =  $is_pant_order ? $product->pant->pant_straight_classic : '';

                // afghan cloths section
                $is_dress_order = $product->dress ? true : false;
                $dress_tailor_name =  $is_dress_order ? $product->dress->tailor->name : '';
                $dress_tailor_phone =  $is_dress_order ? $product->dress->tailor->tailor_fee : '';
                $dress_qty =  $is_dress_order ? $product->dress->qty : '';
                $dress_total =  $is_dress_order ? $product->dress->qty * $product->dress->tailor->tailor_fee : '';
                $dress_shirt_length =  $is_dress_order ? $product->dress->dress_shirt_length : '';
                $dress_sleeve =  $is_dress_order ? $product->dress->dress_sleeve : '';
                $dress_shoulder_width =  $is_dress_order ? $product->dress->dress_shoulder_width : '';
                $dress_collar =  $is_dress_order ? $product->dress->dress_collar : '';
                $dress_side_width =  $is_dress_order ? $product->dress->dress_side_width : '';
                $dress_armhole_circumference =  $is_dress_order ? $product->dress->dress_armhole_circumference : '';
                $dress_waist =  $is_dress_order ? $product->dress->dress_waist : '';
                $dress_hem =  $is_dress_order ? $product->dress->dress_hem : '';
                $dress_skirt_length =  $is_dress_order ? $product->dress->dress_skirt_length : '';
                $dress_cuff =  $is_dress_order ? $product->dress->dress_cuff : '';
                $dress_skirt_width =  $is_dress_order ? $product->dress->dress_skirt_width : '';
                $shirt_trouser_crotch_depth = $is_dress_order ? $product->dress->shirt_trouser_crotch_depth : '';
                // curtain section
                $is_curtain_order = $product->curtain ? true : false;
                $curtain_tailor_name = $is_curtain_order ? $product->curtain->tailor->name : '';
                $curtain_tailor_phone = $is_curtain_order ? $product->curtain->tailor->tailor_fee : '';
                $curtain_qty = $is_curtain_order ? $product->curtain->qty : '';
                $curtain_total = $is_curtain_order ? $product->curtain->qty * $product->curtain->tailor->tailor_fee : '';
                $fabric_type = $is_curtain_order ? $product->curtain->fabric_type : '';
                $netting_type = $is_curtain_order ? $product->curtain->netting_type : '';
                $window_count = $is_curtain_order ? $product->curtain->window_count : '';
                $door_count = $is_curtain_order ? $product->curtain->door_count : '';
                $panel_count = $is_curtain_order ? $product->curtain->panel_count : '';
                $panel_meter = $is_curtain_order ? $product->curtain->panel_meter : '';
                $middle_netting_meter = $is_curtain_order ? $product->curtain->middle_netting_meter : '';
                $pleating_type = $is_curtain_order ? $product->curtain->pleating_type : '';
                $ring_stitch_type = $is_curtain_order ? $product->curtain->ring_stitch_type : '';
                $curtain_model = $is_curtain_order ? $product->curtain->curtain_model : '';
                $mattress_count = $is_curtain_order ? $product->curtain->mattress_count : '';
                $pillow_count = $is_curtain_order ? $product->curtain->pillow_count : '';
                $bolster_count = $is_curtain_order ? $product->curtain->bolster_count : '';
                $mattress_pillow_size = $is_curtain_order ? $product->curtain->mattress_pillow_size : '';
                $pillow_mattress_model = $is_curtain_order ? $product->curtain->pillow_mattress_model : '';
                $curtain_window_details = $is_curtain_order ? $this->curtainWindowDetailText($product->curtain) : '';
                $curtain_door_details = $is_curtain_order ? $this->curtainDoorDetailText($product->curtain) : '';
                $curtain_bedding_details = $is_curtain_order ? $this->curtainBeddingDetailText($product->curtain) : '';

                // order details section
                $waiscoat_order_details =  $is_waiscoat_order ? $product->waiscoat->waiscoat_order_details : 'N/A';
                $coat_order_details =  $is_coat_order ? $product->coat->coat_order_details : 'N/A';
                $pant_order_details =  $is_pant_order ? $product->pant->pant_order_details : 'N/A';
                $dress_order_details =  $is_dress_order ? $product->dress->dress_order_details : 'N/A';
                $curtain_order_details = $is_curtain_order ? $product->curtain->curtain_order_details : 'N/A';



                $nestedData['product'] = array(
                    '[ "' . $product->code . '"',
                    ' "' . $product->type . '"',
                    ' "' . $product->getCompositionLabel() . '"',
                    ' "' . $nestedData['total_price'] . '"',
                    ' "' . $nestedData['paid_amount'] . '"',
                    ' "' . $nestedData['due_amount'] . '"',
                    ' "' . $nestedData['issue_date'] . '"',
                    ' "' . $nestedData['completion_date'] . '"',
                    ' "' . $product->customer->name . '"',
                    ' "' . $product->customer->phone_number  . '"',
                    ' "' . $product->customer->address  . '"',
                    ' "' . $product->customer->city . '"',
                    ' "' . $product->id . '"',
                    ' "' . $is_waiscoat_order . '"',
                    ' "1' . '"',
                    ' "' . trans('file.Waiscoat Order') . '"',
                    ' "' . $tailor_name . '"',
                    ' "' . $tailor_phone . '"',
                    ' "' . $waiscoat_height . '"',
                    ' "' . $waiscoat_shoulder . '"',
                    ' "' . $waiscoat_side . '"',
                    ' "' . $waiscoat_waist . '"',
                    ' "' . $waiscoat_abdomen . '"',
                    ' "' . $waiscoat_hip . '"',
                    ' "' . $design_v_neck_collar . '"',
                    ' "' . $design_round_neck_collar . '"',
                    ' "' . $design_pakistani_collar . '"',
                    ' "' . $design_zippered_pocket . '"',
                    ' "' . $design_plain_pocket . '"',
                    ' "' . $design_four_side_pocket . '"',
                    ' "' . $design_two_side_pocket . '"',
                    ' "' . $is_coat_order . '"',
                    ' "2' . '"',
                    ' "' . trans('file.Coat Order') . '"',
                    ' "' . $coat_tailor_name . '"',
                    ' "' . $coat_tailor_phone . '"',
                    ' "' . $coat_height . '"',
                    ' "' . $coat_shoulder . '"',
                    ' "' . $coat_sleeve . '"',
                    ' "' . $coat_armhole_circumference . '"',
                    ' "' . $coat_bicep_circumference . '"',
                    ' "' . $coat_cuff . '"',
                    ' "' . $coat_side_width . '"',
                    ' "' . $coat_waist . '"',
                    ' "' . $coat_abdomen_circumference . '"',
                    ' "' . $coat_hip_width . '"',
                    ' "' . $upperbody_front_length . '"',
                    ' "' . $upperbody_back_length . '"',
                    ' "' . $chest_distance . '"',
                    ' "' . $coat_collar . '"',
                    ' "' . $coat_style_one_button . '"',
                    ' "' . $coat_style_two_button . '"',
                    ' "' . $coat_style_three_button . '"',
                    ' "' . $is_pant_order . '"',
                    ' "3' . '"',
                    ' "' . trans('file.Pant Order') . '"',
                    ' "' . $pant_tailor_name . '"',
                    ' "' . $pant_tailor_phone . '"',
                    ' "' . $pant_length . '"',
                    ' "' . trans("file.$pant_waist") . '"',
                    ' "' . $pant_thigh . '"',
                    ' "' . $pant_rise . '"',
                    ' "' . $pant_hem . '"',
                    ' "' . $pant_hip . '"',
                    ' "' . $pant_straight_loose . '"',
                    ' "' . $pant_straight_medium . '"',
                    ' "' . $pant_straight_military . '"',
                    ' "' . $pant_straight_cuban_pocket . '"',
                    ' "' . $pant_straight_classic . '"',
                    ' "1' . '"',
                    ' "' . trans('file.Dress Order') . '"',
                    ' "' . $dress_tailor_name . '"',
                    ' "' . $dress_tailor_phone . '"',
                    ' "' . $dress_shirt_length . '"',
                    ' "' . $dress_sleeve . '"',
                    ' "' . $dress_shoulder_width . '"',
                    ' "' . $dress_collar . '"',
                    ' "' . $dress_side_width . '"',
                    ' "' . $dress_armhole_circumference . '"',
                    ' "' . $dress_waist . '"',
                    ' "' . $dress_hem . '"',
                    ' "' . $dress_skirt_length . '"',
                    ' "' . $dress_cuff . '"',
                    ' "' . $dress_skirt_width . '"',
                    ' "' . $waiscoat_order_details . '"',
                    ' "' . $coat_order_details . '"',
                    ' "' . $pant_order_details . '"',
                    ' "' . $dress_order_details. '"',
                    ' "' . $waiscoat_qty . '"',
                    ' "' . $waiscoat_total . '"',
                    ' "' . $coat_qty . '"',
                    ' "' . $coat_total . '"',
                    ' "' . $pant_qty . '"',
                    ' "' . $pant_total . '"',
                    ' "' . $dress_qty . '"',
                    ' "' . $dress_total . '"',
                    ' "' . $vest_chest_circumference. '"',
                    ' "' . $trouser_crotch_depth. '"',
                    ' "' . $shirt_trouser_crotch_depth . '"',
                    ' "' . $is_curtain_order . '"',
                    ' "1"',
                    ' "' . trans('file.Curtain Order') . '"',
                    ' "' . $curtain_tailor_name . '"',
                    ' "' . $curtain_tailor_phone . '"',
                    ' "' . $fabric_type . '"',
                    ' "' . $netting_type . '"',
                    ' "' . $panel_count . '"',
                    ' "' . $panel_meter . '"',
                    ' "' . $middle_netting_meter . '"',
                    ' "' . $pleating_type . '"',
                    ' "' . $ring_stitch_type . '"',
                    ' "' . $curtain_model . '"',
                    ' "' . $mattress_count . '"',
                    ' "' . $pillow_count . '"',
                    ' "' . $bolster_count . '"',
                    ' "' . $mattress_pillow_size . '"',
                    ' "' . $pillow_mattress_model . '"',
                    ' "' . $curtain_order_details . '"',
                    ' "' . $curtain_qty . '"',
                    ' "' . $curtain_total . '"',
                    ' "' . $window_count . '"',
                    ' "' . $door_count . '"',
                    ' "' . $curtain_window_details . '"',
                    ' "' . $curtain_bedding_details . '"',
                    ' "' . $curtain_door_details . '"]'
                );
                //$nestedData['imagedata'] = DNS1D::getBarcodePNG($product->code, $product->barcode_symbology);
                $data[] = $nestedData;
            }
        }

        $json_data = array(
            "draw"            => intval($request->input('draw')),
            "recordsTotal"    => intval($totalData),
            "recordsFiltered" => intval($totalFiltered),
            "data"            => $data
        );

        echo json_encode($json_data);
    }

    private function curtainProductId(array $inputs)
    {
        if (!empty($inputs['product_id'])) {
            return $inputs['product_id'];
        }

        if (!empty($inputs['fabric_product_id'])) {
            return $inputs['fabric_product_id'];
        }

        foreach (['window_detail_fabric_product_id', 'door_detail_product_id', 'mattress_detail_product_id', 'pillow_detail_product_id', 'bolster_detail_product_id'] as $key) {
            foreach (($inputs[$key] ?? []) as $productId) {
                if ($productId) {
                    return $productId;
                }
            }
        }

        if (!empty($inputs['fabric_type'])) {
            return Product::where('name', $inputs['fabric_type'])->value('id');
        }

        return null;
    }

    private function deactivateTailoringProduct(TailoringProduct $product)
    {
        $transactions = FinancialTransaction::where('reference_type', TailoringProduct::class)
            ->where('reference_id', $product->id)
            ->whereNull('reversed_at')
            ->where('direction', 'in')
            ->get();
        foreach ($transactions as $transaction) {
            app(MainCashAccount::class)->reverse($transaction, trans('file.Canceled curtain order payment reversal'));
        }

        $product->is_active = false;

        if ($product->waiscoat) {
            $product->waiscoat->delete();
        }
        if ($product->coat) {
            $product->coat->delete();
        }
        if ($product->pant) {
            $product->pant->delete();
        }
        if ($product->dress) {
            $product->dress->delete();
        }
        if ($product->curtain) {
            if ($product->stock_synced) {
                $this->syncTailoringProductStock($product, $this->curtainMaterialUsageFromCurtain($product->curtain), null);
                $product->stock_synced = false;
            }
            $product->curtain->windowDetails()->delete();
            $product->curtain->doorDetails()->delete();
            $product->curtain->beddingDetails()->delete();
            $product->curtain->delete();
        }

        if ($product->sale) {
            Product_Sale::where('sale_id', $product->sale->id)->delete();
            $product->sale->delete();
        }

        $product->save();
    }

    private function syncTailoringSale(
        TailoringProduct $order,
        array $windowDetails,
        array $doorDetails,
        array $beddingDetails
    ) {
        $lines = $this->tailoringSaleLines($windowDetails, $doorDetails, $beddingDetails);
        if (empty($lines)) {
            return;
        }

        $firstProductId = (int) $lines[0]['product_id'];
        $warehouseId = $this->tailoringStockWarehouseId($firstProductId)
            ?: Warehouse::where('is_active', true)->orderBy('id')->value('id');
        $userId = Auth::id() ?: User::orderBy('id')->value('id');
        if (!$userId) {
            throw new Exception(trans('file.Tailoring sale requires an active user'));
        }
        $billerId = Auth::check() ? Auth::user()->biller_id : null;
        if (!$billerId || !Biller::where([['id', $billerId], ['is_active', true]])->exists()) {
            $billerId = Biller::where('is_active', true)->orderBy('id')->value('id');
        }
        if (!$warehouseId || !$billerId) {
            throw new Exception(trans('file.Tailoring sale requires an active warehouse and biller'));
        }

        $generalSetting = GeneralSetting::latest()->first();
        $sale = Sale::firstOrNew(['tailoring_product_id' => $order->id]);
        $sale->fill([
            'reference_no' => 'TAIL-' . $order->code,
            'sale_type' => 'tailoring',
            'user_id' => $userId,
            'customer_id' => $order->customer_id,
            'warehouse_id' => $warehouseId,
            'biller_id' => $billerId,
            'item' => count($lines),
            'total_qty' => array_sum(array_column($lines, 'qty')),
            'total_discount' => 0,
            'total_tax' => 0,
            'total_price' => (float) $order->material_total,
            'service_charge' => (float) $order->service_charge,
            'order_tax_rate' => 0,
            'order_tax' => 0,
            'order_discount' => 0,
            'shipping_cost' => 0,
            'grand_total' => (float) $order->total_price,
            'currency_id' => $generalSetting ? $generalSetting->currency : null,
            'exchange_rate' => 1,
            'sale_status' => 1,
            'payment_status' => $this->tailoringSalePaymentStatus($order),
            'paid_amount' => (float) $order->paid_amount,
            'sale_note' => trans('file.Generated from tailoring order') . ' ' . $order->code,
        ]);

        $cashRegister = CashRegister::where([
            ['user_id', $userId],
            ['warehouse_id', $warehouseId],
            ['status', true],
        ])->first();
        $sale->cash_register_id = $cashRegister ? $cashRegister->id : null;
        if (!$sale->exists) {
            $sale->created_at = $order->created_at ?: now();
        }
        $sale->save();

        Product_Sale::where('sale_id', $sale->id)->delete();
        $meterUnitId = $this->meterUnitId();
        foreach ($lines as $line) {
            Product_Sale::create([
                'sale_id' => $sale->id,
                'product_id' => $line['product_id'],
                'product_batch_id' => null,
                'variant_id' => null,
                'imei_number' => null,
                'qty' => $line['qty'],
                'sale_unit_id' => $meterUnitId,
                'net_unit_price' => $line['unit_price'],
                'discount' => 0,
                'tax_rate' => 0,
                'tax' => 0,
                'total' => round($line['qty'] * $line['unit_price'], 4),
            ]);
        }
    }

    public function syncTailoringSaleHistory(TailoringProduct $order)
    {
        $order->load('curtain.windowDetails', 'curtain.doorDetails', 'curtain.beddingDetails');
        if (!$order->curtain) {
            return false;
        }

        $windowDetails = $order->curtain->windowDetails->map->toArray()->all();
        $doorDetails = $order->curtain->doorDetails->map->toArray()->all();
        $beddingDetails = $order->curtain->beddingDetails->map->toArray()->all();
        $this->syncTailoringSale($order, $windowDetails, $doorDetails, $beddingDetails);

        return true;
    }

    private function syncTailoringSalePayment(TailoringProduct $order)
    {
        Sale::where('tailoring_product_id', $order->id)->update([
            'grand_total' => (float) $order->total_price,
            'paid_amount' => (float) $order->paid_amount,
            'payment_status' => $this->tailoringSalePaymentStatus($order),
        ]);
    }

    private function tailoringSalePaymentStatus(TailoringProduct $order)
    {
        $total = round((float) $order->total_price, 2);
        $paid = round((float) $order->paid_amount, 2);
        if ($paid >= $total) {
            return 4;
        }
        return $paid > 0 ? 3 : 2;
    }

    private function meterUnitId()
    {
        $unitId = Unit::where('unit_name', 'متر')->value('id');
        if (!$unitId) {
            $unitId = Unit::where('operator', '*')->where('operation_value', 1)->orderBy('id')->value('id');
        }
        if (!$unitId) {
            throw new Exception(trans('file.Meter unit is not configured'));
        }
        return $unitId;
    }

    private function tailoringSaleLines(array $windowDetails, array $doorDetails, array $beddingDetails)
    {
        $lines = [];
        $append = function ($productId, $quantity, $unitPrice) use (&$lines) {
            $productId = (int) $productId;
            $quantity = round((float) $quantity, 4);
            $unitPrice = round((float) $unitPrice, 4);
            if (!$productId || $quantity <= 0) {
                return;
            }
            $key = $productId . ':' . number_format($unitPrice, 4, '.', '');
            if (!isset($lines[$key])) {
                $lines[$key] = ['product_id' => $productId, 'qty' => 0, 'unit_price' => $unitPrice];
            }
            $lines[$key]['qty'] = round($lines[$key]['qty'] + $quantity, 4);
        };

        foreach ($windowDetails as $detail) {
            $append(
                $detail['fabric_product_id'] ?? null,
                (float) $detail['window_count'] * (float) $detail['panel_count'] * (float) $detail['panel_meter'],
                $detail['fabric_unit_price'] ?? 0
            );
            $append(
                $detail['netting_product_id'] ?? null,
                (float) $detail['window_count'] * (float) $detail['middle_netting_meter'],
                $detail['netting_unit_price'] ?? 0
            );
        }
        foreach ($doorDetails as $detail) {
            $append($detail['product_id'] ?? null, $detail['meterage'] ?? 0, $detail['unit_price'] ?? 0);
        }
        foreach ($beddingDetails as $detail) {
            $append($detail['product_id'] ?? null, $detail['meterage'] ?? 0, $detail['unit_price'] ?? 0);
            if (!empty($detail['has_under_cover'])) {
                $append(
                    $detail['under_cover_product_id'] ?? null,
                    $detail['under_cover_meterage'] ?? 0,
                    $detail['under_cover_unit_price'] ?? 0
                );
            }
        }

        return array_values($lines);
    }

    private function nextTailoringOrderCode()
    {
        $usedCodes = TailoringProduct::pluck('code')
            ->filter(function ($code) {
                return is_numeric($code) && (int) $code > 0;
            })
            ->mapWithKeys(function ($code) {
                return [str_pad((int) $code, 4, '0', STR_PAD_LEFT) => true];
            });

        $nextCode = 1;
        do {
            $code = str_pad($nextCode, 4, '0', STR_PAD_LEFT);
            $nextCode++;
        } while (isset($usedCodes[$code]));

        return $code;
    }

    private function curtainNettingProductId(array $inputs)
    {
        if (!empty($inputs['netting_product_id'])) {
            return $inputs['netting_product_id'];
        }

        if (!empty($inputs['netting_type'])) {
            return Product::where('name', $inputs['netting_type'])->value('id');
        }

        return null;
    }

    private function curtainMaterialUsageFromDetails(array $windowDetails, array $doorDetails, array $beddingDetails)
    {
        $usage = ['items' => []];

        foreach ($windowDetails as $detail) {
            $this->addCurtainMaterialUsage(
                $usage,
                $detail['fabric_product_id'] ?? null,
                (float) $detail['window_count'] * (float) $detail['panel_count'] * (float) $detail['panel_meter']
            );
            $this->addCurtainMaterialUsage(
                $usage,
                $detail['netting_product_id'] ?? null,
                (float) $detail['window_count'] * (float) $detail['middle_netting_meter']
            );
        }

        foreach ($doorDetails as $detail) {
            $this->addCurtainMaterialUsage($usage, $detail['product_id'] ?? null, (float) $detail['meterage']);
        }

        foreach ($beddingDetails as $detail) {
            $this->addCurtainMaterialUsage($usage, $detail['product_id'] ?? null, (float) $detail['meterage']);
            if (!empty($detail['has_under_cover'])) {
                $this->addCurtainMaterialUsage(
                    $usage,
                    $detail['under_cover_product_id'] ?? null,
                    (float) $detail['under_cover_meterage']
                );
            }
        }

        return $usage;
    }

    private function curtainMaterialUsageFromCurtain(Curtain $curtain)
    {
        $windowDetails = $curtain->windowDetails->map(function ($detail) {
            return $detail->toArray();
        })->all();
        $doorDetails = $curtain->doorDetails->map(function ($detail) {
            return $detail->toArray();
        })->all();
        $beddingDetails = $curtain->beddingDetails->map(function ($detail) {
            return $detail->toArray();
        })->all();

        $hasLinkedProducts = collect($windowDetails)->contains(function ($detail) {
            return !empty($detail['fabric_product_id']) || !empty($detail['netting_product_id']);
        }) || collect($doorDetails)->contains(function ($detail) {
            return !empty($detail['product_id']);
        }) || collect($beddingDetails)->contains(function ($detail) {
            return !empty($detail['product_id']) || !empty($detail['under_cover_product_id']);
        });

        if ($hasLinkedProducts) {
            return $this->curtainMaterialUsageFromDetails($windowDetails, $doorDetails, $beddingDetails);
        }

        $usage = ['items' => []];
        $this->addCurtainMaterialUsage(
            $usage,
            Product::where('name', $curtain->fabric_type)->value('id'),
            (float) $curtain->panel_meter + $this->curtainBeddingFabricMeterage($beddingDetails)
        );
        $this->addCurtainMaterialUsage(
            $usage,
            Product::where('name', $curtain->netting_type)->value('id'),
            (float) $curtain->middle_netting_meter
        );

        return $usage;
    }

    private function addCurtainMaterialUsage(array &$usage, $productId, float $quantity)
    {
        if (!$productId || $quantity <= 0) {
            return;
        }

        $productId = (int) $productId;
        $usage['items'][$productId] = ($usage['items'][$productId] ?? 0) + $quantity;
    }

    private function curtainBeddingFabricMeterage(array $beddingDetails)
    {
        return array_reduce($beddingDetails, function ($total, $detail) {
            return $total + (float) ($detail['meterage'] ?? 0);
        }, 0);
    }

    private function syncTailoringProductStock(TailoringProduct $order, ?array $oldUsage, ?array $newUsage)
    {
        foreach (($oldUsage['items'] ?? []) as $productId => $quantity) {
            $this->applyMaterialStockAdjustment($productId, (float) $quantity);
        }

        foreach (($newUsage['items'] ?? []) as $productId => $quantity) {
            $this->applyMaterialStockAdjustment($productId, -1 * (float) $quantity);
        }
    }

    private function curtainMaterialStockError(?array $newUsage, ?array $oldUsage = null)
    {
        if (!$newUsage) {
            return null;
        }

        $requiredByProduct = $newUsage['items'] ?? [];

        foreach (($oldUsage['items'] ?? []) as $productId => $quantity) {
            $requiredByProduct[$productId] = ($requiredByProduct[$productId] ?? 0) - (float) $quantity;
        }

        foreach ($requiredByProduct as $productId => $requiredQty) {
            if ($requiredQty <= 0) {
                continue;
            }

            $product = Product::select('id', 'name', 'qty')->where('id', $productId)->lockForUpdate()->first();
            if ($product && $requiredQty > (float) $product->qty) {
                return trans('file.Not enough stock for product', [
                    'product' => $product->name,
                    'required' => number_format($requiredQty, 2, '.', ''),
                    'available' => number_format((float) $product->qty, 2, '.', ''),
                ]);
            }
        }

        return null;
    }

    private function applyMaterialStockAdjustment($productId, float $quantity)
    {
        if (!$productId || abs($quantity) < 0.00001) {
            return;
        }

        $product = Product::where('id', $productId)->lockForUpdate()->first();
        if (!$product) {
            return;
        }

        if ($quantity < 0 && ((float) $product->qty + $quantity) < -0.00001) {
            throw new Exception(trans('file.Not enough stock for product', [
                'product' => $product->name,
                'required' => number_format(abs($quantity), 2, '.', ''),
                'available' => number_format((float) $product->qty, 2, '.', ''),
            ]));
        }

        $product->qty += $quantity;
        $product->save();

        $warehouseId = $this->tailoringStockWarehouseId($productId, $quantity);
        if (!$warehouseId) {
            return;
        }

        $productWarehouse = Product_Warehouse::where([
            ['product_id', $productId],
            ['warehouse_id', $warehouseId],
        ])->lockForUpdate()->first();

        if (!$productWarehouse) {
            $productWarehouse = new Product_Warehouse();
            $productWarehouse->product_id = $productId;
            $productWarehouse->warehouse_id = $warehouseId;
            $productWarehouse->qty = 0;
        }

        if ($quantity < 0 && ((float) $productWarehouse->qty + $quantity) < -0.00001) {
            throw new Exception(trans('file.Not enough warehouse stock for product', ['product' => $product->name]));
        }

        $productWarehouse->qty += $quantity;
        $productWarehouse->save();
    }

    private function tailoringStockWarehouseId($productId, float $quantity = 0)
    {
        if ($quantity < 0) {
            $requiredQty = abs($quantity);
            $stockWarehouse = Product_Warehouse::where('product_id', $productId)
                ->where('qty', '>=', $requiredQty)
                ->orderBy('qty', 'desc')
                ->value('warehouse_id');

            if ($stockWarehouse) {
                return $stockWarehouse;
            }
        }

        if (Auth::check() && !empty(Auth::user()->warehouse_id)
            && Product_Warehouse::where([['product_id', $productId], ['warehouse_id', Auth::user()->warehouse_id]])->exists()) {
            return Auth::user()->warehouse_id;
        }

        return Product_Warehouse::where('product_id', $productId)->value('warehouse_id');
    }

    private function curtainModelValue($value)
    {
        if (is_array($value)) {
            return implode('، ', array_filter(array_map('trim', $value)));
        }

        return trim((string) $value);
    }

    private function curtainBeddingDetailsFromInputs(array $inputs)
    {
        return array_merge(
            $this->beddingDetailsByType($inputs, 'mattress'),
            $this->beddingDetailsByType($inputs, 'pillow'),
            $this->beddingDetailsByType($inputs, 'bolster')
        );
    }

    private function beddingDetailsByType(array $inputs, string $type)
    {
        $details = [];
        $counts = $inputs[$type . '_detail_count'] ?? [];

        foreach ($counts as $index => $count) {
            $itemCount = (int) $count;
            if ($itemCount < 1) {
                continue;
            }

            $details[] = [
                'type' => $type,
                'label' => trim($inputs[$type . '_detail_label'][$index] ?? ''),
                'product_id' => $this->validCurtainProductId($inputs[$type . '_detail_product_id'][$index] ?? null),
                'unit_price' => $this->curtainOrderUnitPrice(
                    $inputs[$type . '_detail_product_id'][$index] ?? null,
                    $inputs[$type . '_detail_unit_price'][$index] ?? null
                ),
                'count' => $itemCount,
                'height' => trim($inputs[$type . '_detail_height'][$index] ?? ''),
                'width' => trim($inputs[$type . '_detail_width'][$index] ?? ''),
                'meterage' => trim($inputs[$type . '_detail_meterage'][$index] ?? ''),
                'model' => trim($inputs[$type . '_detail_model'][$index] ?? ''),
                'has_under_cover' => !empty($inputs[$type . '_detail_has_under_cover'][$index]),
                'under_cover_product_id' => $this->validCurtainProductId($inputs[$type . '_detail_under_cover_product_id'][$index] ?? null),
                'under_cover_unit_price' => $this->curtainOrderUnitPrice(
                    $inputs[$type . '_detail_under_cover_product_id'][$index] ?? null,
                    $inputs[$type . '_detail_under_cover_unit_price'][$index] ?? null
                ),
                'under_cover_count' => (int) ($inputs[$type . '_detail_under_cover_count'][$index] ?? 0),
                'under_cover_height' => trim($inputs[$type . '_detail_under_cover_height'][$index] ?? ''),
                'under_cover_width' => trim($inputs[$type . '_detail_under_cover_width'][$index] ?? ''),
                'under_cover_meterage' => trim($inputs[$type . '_detail_under_cover_meterage'][$index] ?? ''),
            ];
        }

        if (empty($details)) {
            $fallbackCount = (int) ($inputs[$type . '_count'] ?? 0);
            if ($fallbackCount > 0) {
                $details[] = [
                    'type' => $type,
                    'label' => '',
                    'product_id' => null,
                    'unit_price' => null,
                    'count' => $fallbackCount,
                    'height' => '',
                    'width' => '',
                    'meterage' => '',
                    'model' => trim($inputs['pillow_mattress_model'] ?? ''),
                    'has_under_cover' => false,
                ];
            }
        }

        return $details;
    }

    private function curtainBeddingSummary(array $details)
    {
        $summary = [
            'mattress_count' => 0,
            'pillow_count' => 0,
            'bolster_count' => 0,
            'size' => '',
            'model' => '',
        ];
        $sizeLines = [];
        $modelLines = [];

        foreach ($details as $index => $detail) {
            $typeLabel = $this->beddingTypeLabel($detail['type']);
            $label = $detail['label'] ?: trans('file.Group') . ' ' . ($index + 1);

            if ($detail['type'] === 'mattress') {
                $summary['mattress_count'] += $detail['count'];
            } elseif ($detail['type'] === 'pillow') {
                $summary['pillow_count'] += $detail['count'];
            } elseif ($detail['type'] === 'bolster') {
                $summary['bolster_count'] += $detail['count'];
            }

            if ($detail['height'] || $detail['width']) {
                $sizeLines[] = $typeLabel . ' - ' . $label . ': ' . $detail['height'] . ' x ' . $detail['width'];
            }
            if ($detail['model']) {
                $modelLines[] = $typeLabel . ' - ' . $label . ': ' . $detail['model'];
            }
        }

        $summary['size'] = mb_substr(implode(' | ', $sizeLines), 0, 250);
        $summary['model'] = mb_substr(implode(' | ', $modelLines), 0, 250);

        return $summary;
    }

    private function curtainWindowDetailsFromInputs(array $inputs)
    {
        $details = [];
        $counts = $inputs['window_detail_count'] ?? [];

        foreach ($counts as $index => $count) {
            $windowCount = (int) $count;
            $panelCount = (int) ($inputs['window_detail_panel_count'][$index] ?? 0);
            $panelMeter = (float) ($inputs['window_detail_panel_meter'][$index] ?? 0);
            $middleNetting = (float) ($inputs['window_detail_middle_netting'][$index] ?? 0);

            if ($windowCount < 1) {
                continue;
            }

            $details[] = [
                'label' => trim($inputs['window_detail_label'][$index] ?? ''),
                'fabric_product_id' => $this->validCurtainProductId($inputs['window_detail_fabric_product_id'][$index] ?? null),
                'fabric_unit_price' => $this->curtainOrderUnitPrice(
                    $inputs['window_detail_fabric_product_id'][$index] ?? null,
                    $inputs['window_detail_fabric_unit_price'][$index] ?? null
                ),
                'netting_product_id' => $this->validCurtainProductId($inputs['window_detail_netting_product_id'][$index] ?? null),
                'netting_unit_price' => $this->curtainOrderUnitPrice(
                    $inputs['window_detail_netting_product_id'][$index] ?? null,
                    $inputs['window_detail_netting_unit_price'][$index] ?? null
                ),
                'window_count' => $windowCount,
                'panel_count' => $panelCount,
                'panel_meter' => $panelMeter,
                'middle_netting_meter' => $middleNetting,
            ];
        }

        return $details;
    }

    private function curtainWindowTotals(array $details)
    {
        $totals = [
            'window_count' => 0,
            'panel_count' => 0,
            'panel_meter' => 0,
            'middle_netting_meter' => 0,
        ];

        foreach ($details as $detail) {
            $windowCount = (int) $detail['window_count'];
            $panelCount = (int) $detail['panel_count'];
            $panelMeter = (float) $detail['panel_meter'];
            $middleNetting = (float) $detail['middle_netting_meter'];

            $totals['window_count'] += $windowCount;
            $totals['panel_count'] += $windowCount * $panelCount;
            $totals['panel_meter'] += $windowCount * $panelCount * $panelMeter;
            $totals['middle_netting_meter'] += $windowCount * $middleNetting;
        }

        $totals['panel_meter'] = number_format($totals['panel_meter'], 2, '.', '');
        $totals['middle_netting_meter'] = number_format($totals['middle_netting_meter'], 2, '.', '');

        return $totals;
    }

    private function curtainDoorDetailsFromInputs(array $inputs)
    {
        $details = [];
        $counts = $inputs['door_detail_count'] ?? [];

        foreach ($counts as $index => $count) {
            $doorCount = (int) $count;
            if ($doorCount < 1) {
                continue;
            }

            $materialType = $inputs['door_detail_material_type'][$index] ?? 'fabric';
            if (!in_array($materialType, ['fabric', 'netting'])) {
                $materialType = 'fabric';
            }

            $details[] = [
                'label' => trim($inputs['door_detail_label'][$index] ?? ''),
                'product_id' => $this->validCurtainProductId($inputs['door_detail_product_id'][$index] ?? null),
                'unit_price' => $this->curtainOrderUnitPrice(
                    $inputs['door_detail_product_id'][$index] ?? null,
                    $inputs['door_detail_unit_price'][$index] ?? null
                ),
                'door_count' => $doorCount,
                'material_type' => $materialType,
                'meterage' => (float) ($inputs['door_detail_meterage'][$index] ?? 0),
            ];
        }

        return $details;
    }

    private function curtainDoorTotals(array $details, $fallbackDoorCount = 0)
    {
        $totals = [
            'door_count' => 0,
            'fabric_meterage' => 0,
            'netting_meterage' => 0,
        ];

        foreach ($details as $detail) {
            $totals['door_count'] += (int) $detail['door_count'];

            if ($detail['material_type'] === 'netting') {
                $totals['netting_meterage'] += (float) $detail['meterage'];
            } else {
                $totals['fabric_meterage'] += (float) $detail['meterage'];
            }
        }

        if (!$totals['door_count']) {
            $totals['door_count'] = (int) $fallbackDoorCount;
        }

        $totals['fabric_meterage'] = number_format($totals['fabric_meterage'], 2, '.', '');
        $totals['netting_meterage'] = number_format($totals['netting_meterage'], 2, '.', '');

        return $totals;
    }

    private function syncCurtainWindowDetails(Curtain $curtain, array $details)
    {
        CurtainWindowDetail::where('curtain_id', $curtain->id)->delete();

        foreach ($details as $detail) {
            CurtainWindowDetail::create([
                'curtain_id' => $curtain->id,
                'label' => $detail['label'] ?: null,
                'fabric_product_id' => $detail['fabric_product_id'] ?? null,
                'fabric_unit_price' => $detail['fabric_unit_price'] ?? null,
                'netting_product_id' => $detail['netting_product_id'] ?? null,
                'netting_unit_price' => $detail['netting_unit_price'] ?? null,
                'window_count' => $detail['window_count'],
                'panel_count' => $detail['panel_count'],
                'panel_meter' => $detail['panel_meter'],
                'middle_netting_meter' => $detail['middle_netting_meter'],
            ]);
        }
    }

    private function syncCurtainDoorDetails(Curtain $curtain, array $details)
    {
        CurtainDoorDetail::where('curtain_id', $curtain->id)->delete();

        foreach ($details as $detail) {
            CurtainDoorDetail::create([
                'curtain_id' => $curtain->id,
                'label' => $detail['label'] ?: null,
                'product_id' => $detail['product_id'] ?? null,
                'unit_price' => $detail['unit_price'] ?? null,
                'door_count' => $detail['door_count'],
                'material_type' => $detail['material_type'],
                'meterage' => $detail['meterage'],
            ]);
        }
    }

    private function syncCurtainBeddingDetails(Curtain $curtain, array $details)
    {
        CurtainBeddingDetail::where('curtain_id', $curtain->id)->delete();

        foreach ($details as $detail) {
            CurtainBeddingDetail::create([
                'curtain_id' => $curtain->id,
                'type' => $detail['type'],
                'label' => $detail['label'] ?: null,
                'product_id' => $detail['product_id'] ?? null,
                'unit_price' => $detail['unit_price'] ?? null,
                'count' => $detail['count'],
                'height' => $detail['height'] ?: null,
                'width' => $detail['width'] ?: null,
                'meterage' => $detail['meterage'] ?: null,
                'model' => $detail['model'] ?: null,
                'has_under_cover' => !empty($detail['has_under_cover']),
                'under_cover_product_id' => $detail['under_cover_product_id'] ?? null,
                'under_cover_unit_price' => $detail['under_cover_unit_price'] ?? null,
                'under_cover_count' => !empty($detail['has_under_cover']) ? ($detail['under_cover_count'] ?? null) : null,
                'under_cover_height' => !empty($detail['has_under_cover']) ? ($detail['under_cover_height'] ?: null) : null,
                'under_cover_width' => !empty($detail['has_under_cover']) ? ($detail['under_cover_width'] ?: null) : null,
                'under_cover_meterage' => !empty($detail['has_under_cover']) ? ($detail['under_cover_meterage'] ?: null) : null,
            ]);
        }
    }

    private function validCurtainProductId($productId)
    {
        if (!$productId) {
            return null;
        }

        return Product::where([['id', $productId], ['is_active', true]])->value('id');
    }

    private function curtainProductPrice($productId)
    {
        if (!$productId) {
            return null;
        }

        return Product::where([['id', $productId], ['is_active', true]])->value('price');
    }

    private function curtainOrderUnitPrice($productId, $submittedPrice)
    {
        if (!$this->validCurtainProductId($productId)) {
            return null;
        }

        if ($submittedPrice !== null && $submittedPrice !== '' && is_numeric($submittedPrice)) {
            return round(max((float) $submittedPrice, 0), 4);
        }

        return $this->curtainProductPrice($productId);
    }

    private function curtainTailorFeeSnapshot(Tailor $tailor, TailoringProduct $existingOrder = null)
    {
        $sameTailor = $existingOrder
            && $existingOrder->curtain
            && (int) $existingOrder->curtain->tailor_id === (int) $tailor->id
            && $existingOrder->tailor_fabric_meter_fee !== null;

        if ($sameTailor) {
            return [
                'tailor_fabric_meter_fee' => (float) $existingOrder->tailor_fabric_meter_fee,
                'tailor_netting_meter_fee' => (float) $existingOrder->tailor_netting_meter_fee,
                'tailor_mattress_fee' => (float) $existingOrder->tailor_mattress_fee,
                'tailor_pillow_fee' => (float) $existingOrder->tailor_pillow_fee,
                'tailor_bolster_fee' => (float) $existingOrder->tailor_bolster_fee,
                'tailor_under_cover_fee_method' => $existingOrder->tailor_under_cover_fee_method ?: 'corresponding',
                'tailor_mattress_under_cover_fee' => (float) $existingOrder->tailor_mattress_under_cover_fee,
                'tailor_pillow_under_cover_fee' => (float) $existingOrder->tailor_pillow_under_cover_fee,
                'tailor_bolster_under_cover_fee' => (float) $existingOrder->tailor_bolster_under_cover_fee,
            ];
        }

        return [
            'tailor_fabric_meter_fee' => (float) $tailor->fabric_meter_fee,
            'tailor_netting_meter_fee' => (float) $tailor->netting_meter_fee,
            'tailor_mattress_fee' => (float) $tailor->mattress_fee,
            'tailor_pillow_fee' => (float) $tailor->pillow_fee,
            'tailor_bolster_fee' => (float) $tailor->bolster_fee,
            'tailor_under_cover_fee_method' => $tailor->under_cover_fee_method ?: 'corresponding',
            'tailor_mattress_under_cover_fee' => (float) $tailor->mattress_under_cover_fee,
            'tailor_pillow_under_cover_fee' => (float) $tailor->pillow_under_cover_fee,
            'tailor_bolster_under_cover_fee' => (float) $tailor->bolster_under_cover_fee,
        ];
    }

    private function curtainTailorCost(array $windowDetails, array $doorDetails, array $beddingDetails, array $rates)
    {
        $fabricMeters = 0;
        $nettingMeters = 0;
        foreach ($windowDetails as $detail) {
            $fabricMeters += (float) $detail['window_count'] * (float) $detail['panel_count'] * (float) $detail['panel_meter'];
            $nettingMeters += (float) $detail['window_count'] * (float) $detail['middle_netting_meter'];
        }
        foreach ($doorDetails as $detail) {
            if (($detail['material_type'] ?? 'fabric') === 'netting') {
                $nettingMeters += (float) $detail['meterage'];
            } else {
                $fabricMeters += (float) $detail['meterage'];
            }
        }

        $total = $fabricMeters * $rates['tailor_fabric_meter_fee'];
        $total += $nettingMeters * $rates['tailor_netting_meter_fee'];

        foreach ($beddingDetails as $detail) {
            $type = $detail['type'];
            $itemFeeKey = 'tailor_' . $type . '_fee';
            $total += (int) $detail['count'] * (float) ($rates[$itemFeeKey] ?? 0);

            if (!empty($detail['has_under_cover']) && $rates['tailor_under_cover_fee_method'] === 'separate') {
                $underCoverFee = (float) ($rates['tailor_' . $type . '_under_cover_fee'] ?? 0);
                $total += (int) ($detail['under_cover_count'] ?? 0) * $underCoverFee;
            }
        }

        return round($total, 2);
    }

    private function curtainMaterialTotal(array $windowDetails, array $doorDetails, array $beddingDetails)
    {
        $total = 0;
        foreach ($windowDetails as $detail) {
            $fabricQty = (float) $detail['window_count'] * (float) $detail['panel_count'] * (float) $detail['panel_meter'];
            $nettingQty = (float) $detail['window_count'] * (float) $detail['middle_netting_meter'];
            $total += $fabricQty * (float) ($detail['fabric_unit_price'] ?? 0);
            $total += $nettingQty * (float) ($detail['netting_unit_price'] ?? 0);
        }
        foreach ($doorDetails as $detail) {
            $total += (float) $detail['meterage'] * (float) ($detail['unit_price'] ?? 0);
        }
        foreach ($beddingDetails as $detail) {
            $total += (float) $detail['meterage'] * (float) ($detail['unit_price'] ?? 0);
            if (!empty($detail['has_under_cover'])) {
                $total += (float) $detail['under_cover_meterage'] * (float) ($detail['under_cover_unit_price'] ?? 0);
            }
        }

        return round($total, 2);
    }

    private function curtainLegacyProductName(array $windowDetails, array $doorDetails, array $beddingDetails, string $role)
    {
        $productId = null;
        if ($role === 'netting') {
            foreach ($windowDetails as $detail) {
                if (!empty($detail['netting_product_id'])) {
                    $productId = $detail['netting_product_id'];
                    break;
                }
            }
        } else {
            foreach ($windowDetails as $detail) {
                if (!empty($detail['fabric_product_id'])) {
                    $productId = $detail['fabric_product_id'];
                    break;
                }
            }
            if (!$productId) {
                foreach (array_merge($doorDetails, $beddingDetails) as $detail) {
                    if (!empty($detail['product_id'])) {
                        $productId = $detail['product_id'];
                        break;
                    }
                }
            }
        }

        return $productId ? (Product::where('id', $productId)->value('name') ?: '') : '';
    }

    private function curtainDetailsValidationError(array $windowDetails, array $doorDetails, array $beddingDetails)
    {
        if (!$windowDetails && !$doorDetails && !$beddingDetails) {
            return trans('file.Add Curtain Detail Group');
        }

        foreach ($windowDetails as $detail) {
            $fabricQty = (float) $detail['window_count'] * (float) $detail['panel_count'] * (float) $detail['panel_meter'];
            $nettingQty = (float) $detail['window_count'] * (float) $detail['middle_netting_meter'];
            if ($fabricQty > 0 && empty($detail['fabric_product_id'])) {
                return trans('file.Select Window Fabric Product');
            }
            if ($nettingQty > 0 && empty($detail['netting_product_id'])) {
                return trans('file.Select Window Netting Product');
            }
            if ($fabricQty <= 0 && $nettingQty <= 0) {
                return trans('file.Window Group Requires Material');
            }
        }

        foreach ($doorDetails as $detail) {
            if (empty($detail['product_id']) || (float) $detail['meterage'] <= 0) {
                return trans('file.Door Group Requires Product');
            }
        }

        foreach ($beddingDetails as $detail) {
            if (empty($detail['product_id']) || (float) $detail['meterage'] <= 0) {
                return trans('file.Bedding Group Requires Product');
            }
            if (!empty($detail['has_under_cover']) && (
                empty($detail['under_cover_product_id']) ||
                (int) $detail['under_cover_count'] < 1 ||
                (float) $detail['under_cover_meterage'] <= 0
            )) {
                return trans('file.Under Cover Requires Product');
            }
        }

        return null;
    }

    private function beddingTypeLabel(string $type)
    {
        if ($type === 'mattress') {
            return trans('file.Mattress Details');
        }

        if ($type === 'bolster') {
            return trans('file.Bolster Details');
        }

        return trans('file.Pillow Details');
    }

    private function doorMaterialLabel(string $materialType)
    {
        return $materialType === 'netting' ? trans('file.Netting') : trans('file.Fabric');
    }

    private function curtainWindowDetailText(Curtain $curtain)
    {
        $text = $curtain->windowDetails->map(function ($detail, $index) {
            $label = $detail->label ?: trans('file.Group') . ' ' . ($index + 1);
            $fabric = $this->curtainProductLabel($detail->fabricProduct) ?: '—';
            $netting = $this->curtainProductLabel($detail->nettingProduct) ?: '—';

            return $label . ': ' . trans('file.Fabric') . ' ' . $fabric . ', ' . trans('file.Netting') . ' ' . $netting . ', ' .
                trans('file.Window Count') . ' ' . $detail->window_count . '، ' .
                trans('file.Curtain Panels') . ' ' . $detail->panel_count . '، ' .
                trans('file.Panel Meter') . ' ' . $detail->panel_meter . '، ' .
                trans('file.Middle Netting') . ' ' . $detail->middle_netting_meter;
        })->implode('<br>');

        return str_replace(['"', "\r", "\n"], ["'", ' ', ' '], $text);
    }

    private function curtainDoorDetailText(Curtain $curtain)
    {
        $text = $curtain->doorDetails->map(function ($detail, $index) {
            $label = $detail->label ?: trans('file.Group') . ' ' . ($index + 1);

            return $label . ': ' . trans('file.Product') . ' ' . ($this->curtainProductLabel($detail->product) ?: '—') . ', ' .
                trans('file.Door Count') . ' ' . $detail->door_count . '، ' .
                trans('file.Required Material') . ' ' . $this->doorMaterialLabel($detail->material_type) . '، ' .
                trans('file.Meterage') . ' ' . $detail->meterage;
        })->implode('<br>');

        return str_replace(['"', "\r", "\n"], ["'", ' ', ' '], $text);
    }

    private function curtainBeddingDetailText(Curtain $curtain)
    {
        $text = $curtain->beddingDetails->map(function ($detail, $index) {
            $type = $this->beddingTypeLabel($detail->type);
            $label = $detail->label ?: trans('file.Group') . ' ' . ($index + 1);
            $underCover = $detail->has_under_cover
                ? ', ' . trans('file.Under Cover') . ': ' . ($this->curtainProductLabel($detail->underCoverProduct) ?: '—') .
                    ', ' . trans('file.Qty') . ' ' . $detail->under_cover_count . ', ' . trans('file.Meterage') . ' ' . $detail->under_cover_meterage
                : '';

            return $type . ' - ' . $label . ': ' . trans('file.Product') . ' ' . ($this->curtainProductLabel($detail->product) ?: '—') . ', ' .
                trans('file.Qty') . ' ' . $detail->count . '، ' .
                trans('file.Height') . ' ' . $detail->height . '، ' .
                trans('file.Width') . ' ' . $detail->width . '، ' .
                trans('file.Meterage') . ' ' . $detail->meterage . '، ' .
                trans('file.Bedding Model') . ' ' . $detail->model . $underCover;
        })->implode('<br>');

        return str_replace(['"', "\r", "\n"], ["'", ' ', ' '], $text);
    }

    private function curtainProductLabel($product)
    {
        if (!$product) {
            return '';
        }

        return collect([$product->name, optional($product->brand)->title, $product->code])
            ->filter()
            ->implode(' — ');
    }
}
