<?php

namespace App\Livewire\Report;

use App\Exports\ExportReturn;
use App\Exports\ExportReturnDetail;
use App\Models\DetailInvoice;
use App\Models\Invoice;
use App\Models\Sales;
use App\Models\Settings;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Maatwebsite\Excel\Facades\Excel;
use Mike42\Escpos\CapabilityProfile;
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
use Mike42\Escpos\Printer;

class Returnsalereport extends Component
{
    public $startDate;
    public $endDate;
    public $invoices;
    public $data;

    public function mount()
    {
        $invoices = Invoice::with('detailInvoices')->whereNotNull('no_inv')
            ->where(function ($query) {
                if ($this->startDate && $this->endDate) {
                    if ($this->startDate === $this->endDate) {
                        // If start date and end date are the same, fetch data for the start date
                        $query->whereDate('created_at', '=', $this->startDate);
                    } else {
                        $endDate = date('Y-m-d 23:59:59', strtotime($this->endDate));

                        // If start date and end date are different, fetch data within the date range
                        $query->whereBetween('created_at', [$this->startDate, $endDate]);
                    }
                } elseif ($this->startDate) {
                    $query->whereDate('created_at', '=', $this->startDate);
                } elseif ($this->endDate) {
                    $query->whereDate('created_at', '<=', $this->endDate);
                }
            })
            ->get();
        $this->invoices = $invoices;
        $this->invoices = $this->invoices->map(function ($invoice) {
            $id_sales = $invoice->detailInvoices->first()->id_sales;
            $totalqty = $invoice->detailInvoices->where('qty', '>', 0)->sum('qty');
            $totalprice = $invoice->detailInvoices->sum('total_price');
            $sales = Sales::find($id_sales);
            $invoice->sales_name = $sales->name;
            $invoice->qty = $totalqty;
            $invoice->subtotal = $totalprice;

            if ($invoice->note) {
                // Decode the invoice note into an associative array
                $invoiceNote = json_decode($invoice->note, true);

                // Access the cash and transfer values
                $cash = $invoiceNote['cash'];
                $transfer = $invoiceNote['transfer'];

                // Set the cash and transfer values on the invoice object
                $invoice->cash = $cash;
                $invoice->transfer = $transfer;
            }

            if ($invoice->payment != '') {
                if ($invoice->change !== '' or $invoice->change !== null) {
                    $totalreturn = $invoice->must_paid + (-$invoice->paid);
                    $invoice->totalreturn = $totalreturn;
                } else {
                    $totalreturn = $invoice->must_paid + $invoice->paid - $invoice->change;
                    $invoice->totalreturn = $totalreturn;
                }
            }
            return $invoice;
        });
        $this->dispatch('refreshjs');

    }

    public function filterInvoices()
    {
        $invoices = Invoice::with('detailInvoices')->whereNotNull('no_inv')
            ->where(function ($query) {
                if ($this->startDate && $this->endDate) {
                    if ($this->startDate === $this->endDate) {
                        // If start date and end date are the same, fetch data for the start date
                        $query->whereDate('created_at', '=', $this->startDate);
                    } else {
                        $endDate = date('Y-m-d 23:59:59', strtotime($this->endDate));

                        // If start date and end date are different, fetch data within the date range
                        $query->whereBetween('created_at', [$this->startDate, $endDate]);
                    }
                } elseif ($this->startDate) {
                    $query->whereDate('created_at', '=', $this->startDate);
                } elseif ($this->endDate) {
                    $query->whereDate('created_at', '<=', $this->endDate);
                }
            })
            ->get();

        if ($invoices->isEmpty()) {
            $invoices = Invoice::with('detailInvoices')->whereNotNull('no_inv')->get();
            $this->invoices = $invoices;
        }

        $this->invoices = $invoices;


        $this->invoices = $this->invoices->map(function ($invoice) {
            $id_sales = $invoice->detailInvoices->first()->id_sales;
            $totalqty = $invoice->detailInvoices->where('qty', '>', 0)->sum('qty');
            $totalprice = $invoice->detailInvoices->sum('total_price');
            $sales = Sales::find($id_sales);
            $invoice->sales_name = $sales->name;
            $invoice->qty = $totalqty;
            $invoice->subtotal = $totalprice;

            if ($invoice->note) {
                // Decode the invoice note into an associative array
                $invoiceNote = json_decode($invoice->note, true);

                // Access the cash and transfer values
                $cash = $invoiceNote['cash'];
                $transfer = $invoiceNote['transfer'];

                // Set the cash and transfer values on the invoice object
                $invoice->cash = $cash;
                $invoice->transfer = $transfer;
            }
            if ($invoice->payment != '') {
                if ($invoice->change !== '' or $invoice->change !== null) {
                    $totalreturn = $invoice->must_paid + $invoice->paid;
                    $invoice->totalreturn = $totalreturn;
                } else {
                    $totalreturn = $invoice->must_paid + $invoice->paid - $invoice->change;
                    $invoice->totalreturn = $totalreturn;
                }
            }

            return $invoice;
        });
        $this->dispatch('refreshjs');

    }

    public function clearFilter()
    {
        $invoices = Invoice::with('detailInvoices')->whereNotNull('no_inv')->get();

        $this->invoices = $invoices;
        $this->invoices = $this->invoices->map(function ($invoice) {
            $id_sales = $invoice->detailInvoices->first()->id_sales;
            $totalqty = $invoice->detailInvoices->where('qty', '>', 0)->sum('qty');
            $totalprice = $invoice->detailInvoices->sum('total_price');
            $sales = Sales::find($id_sales);
            $invoice->sales_name = $sales->name;
            $invoice->qty = $totalqty;
            $invoice->subtotal = $totalprice;

            if ($invoice->note) {
                // Decode the invoice note into an associative array
                $invoiceNote = json_decode($invoice->note, true);

                // Access the cash and transfer values
                $cash = $invoiceNote['cash'];
                $transfer = $invoiceNote['transfer'];

                // Set the cash and transfer values on the invoice object
                $invoice->cash = $cash;
                $invoice->transfer = $transfer;
            }
            if ($invoice->payment != '') {
                if ($invoice->change !== '' or $invoice->change !== null) {
                    $totalreturn = $invoice->must_paid + $invoice->paid;
                    $invoice->totalreturn = $totalreturn;
                } else {
                    $totalreturn = $invoice->must_paid + $invoice->paid - $invoice->change;
                    $invoice->totalreturn = $totalreturn;
                }
            }


            return $invoice;
        });
        $this->startDate = '';
        $this->endDate = '';
    }

    public function render()
    {
        $this->invoices = $this->invoices->map(function ($invoice) {
            $id_sales = $invoice->detailInvoices->first()->id_sales;
            $totalqty = $invoice->detailInvoices->where('qty', '>', 0)->sum('qty');
            $totalprice = $invoice->detailInvoices->sum('total_price');
            $sales = Sales::find($id_sales);
            $invoice->sales_name = $sales->name;
            $invoice->qty = $totalqty;
            $invoice->subtotal = $totalprice;

            if ($invoice->note) {
                // Decode the invoice note into an associative array
                $invoiceNote = json_decode($invoice->note, true);

                // Access the cash and transfer values
                $cash = $invoiceNote['cash'];
                $transfer = $invoiceNote['transfer'];

                // Set the cash and transfer values on the invoice object
                $invoice->cash = $cash;
                $invoice->transfer = $transfer;
            }
            if ($invoice->payment != '') {
                if ($invoice->change !== '' or $invoice->change !== null) {
                    $totalreturn = $invoice->must_paid + $invoice->paid;
                    $invoice->totalreturn = $totalreturn;
                } else {
                    $totalreturn = $invoice->must_paid + $invoice->paid - $invoice->change;
                    $invoice->totalreturn = $totalreturn;
                }
            }
            return $invoice;
        });

        return view('livewire.report.returnsalereport', [
            'invoices' => $this->invoices,
        ]);
    }
    public function exportExcelDetail($code)
    {
        $datareturn = DetailInvoice::where('invoice', $code)
            ->whereNotNull('status')->get();
        $databuy = DetailInvoice::where('invoice', $code)
            ->whereNull('status')->get();
        $currentDate = Carbon::now();
        $now = $currentDate->format('d-m-Y');
        if ($this->startDate === null) {
            $filename = "Return Sale Detail Report - {$now}.xlsx";
        } else {
            $filename = "Return Sale Detail Report - {$this->startDate} - {$this->endDate}.xlsx";
        }
        return Excel::download(new ExportReturnDetail($datareturn, $databuy), $filename);
    }

    public function exportExcel()
    {
        $invoices = $this->invoices;
        $currentDate = Carbon::now();
        $now = $currentDate->format('d-m-Y');
        if ($this->startDate === null) {
            $filename = "Return Sale Report - {$now}.xlsx";
        } else {
            $filename = "Return Sale Report - {$this->startDate} - {$this->endDate}.xlsx";
        }
        return Excel::download(new ExportReturn($invoices), $filename);
    }

    public function print($code)
    {
        $invoice = Invoice::where('no', $code)->with('detailInvoices')->first();
        $user = Auth::user();
        $setting = Settings::where('wh_code', $user->whs_code)->first();
        $printer = $setting->printer_name;
        try {
            $profile = CapabilityProfile::load("default");
            $connector = new WindowsPrintConnector($printer);
            $printer = new Printer($connector, $profile);
            $datafirst = DetailInvoice::where('invoice', $code)->first();

            // Set the font size
            $printer->setTextSize(1, 1);

            // Set the justification
            $toko = $setting->wh_name;
            $address = $setting->address;
            $phone = "Telp : " . $setting->phone;
            $manager = "Cashier   : " . Auth::user()->name;
            $billNo = "Bill No   : " . $invoice->no_inv;
            $returNo = "Return No : " . $invoice->no;
            $date = "Date      : " . $invoice->created_at;
            $handledBy = "Handled by : " . $datafirst->sales->name;
            // Define your item list (replace this with your actual item data)
            $itemsreturn = [];

            foreach ($invoice->detailInvoices as $cartItem) {
                // Check if qty is not negative (-)
                if ($cartItem['qty'] <= 0) {
                    $name = str_pad(substr($cartItem['name'], 0, 15), 15); // Truncate or pad to 15 characters
                    $itemsreturn[] = [
                        'name' => $name,
                        'qty' => abs($cartItem['qty']),
                        'price' => $cartItem['price'],
                    ];
                }
            }

            $items = [];

            foreach ($invoice->detailInvoices as $cartItem) {
                if ($cartItem['qty'] >= 0) {
                    $name = str_pad(substr($cartItem['name'], 0, 15), 15); // Truncate or pad to 15 characters
                    $items[] = [
                        'name' => $name,
                        'qty' => abs($cartItem['qty']),
                        'price' => $cartItem['price'],
                    ];
                }
            }

            $subTotalreturn = array_reduce($itemsreturn, function ($carry, $item) {
                return $carry + $item['price'] * $item['qty'];
            }, 0);

            $subTotalitems = array_reduce($items, function ($carry, $item) {
                return $carry + $item['price'] * $item['qty'];
            }, 0);

            // Start the receipt
            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text("$toko\n$phone\n$address\n");
            $printer->text("---------------------------------------\n");
            $printer->setJustification(0);
            $printer->text("$manager\n$billNo\n$returNo\n$date\n");
            $printer->text("---------------------------------------\n");

            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text(" *ITEM RETURN* \n");
            $printer->setJustification(0);

            // Print the table
            $printer->setJustification(Printer::JUSTIFY_LEFT);
            $printer->text("Item               Qty        Price\n");
            $printer->text("---------------------------------------\n");

            foreach ($itemsreturn as $item) {
                $printer->text(sprintf(
                    "%-15s %5d   %12s\n",
                    $item['name'],
                    $item['qty'],
                    number_format($item['price'] * $item['qty'], 2)
                ));
            }

            // Print totals

            $printer->setJustification(0);
            $padding = 14; // Number of spaces before the text
            $printer->text("---------------------------------------\n");
            $subTotal = "SubTotal  : " . number_format($subTotalreturn, 2);


            // Add padding before the text to ensure it starts at character 12
            $rightAlignedSubtotal = str_repeat(' ', $padding) . $subTotal;
            $printer->text("$rightAlignedSubtotal\n");
            $printer->text("---------------------------------------\n");

            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text(" *ITEMS* \n");
            $printer->setJustification(0);

            // Print the table
            $printer->setJustification(Printer::JUSTIFY_LEFT);
            $printer->text("Item               Qty        Price\n");
            $printer->text("---------------------------------------\n");

            foreach ($items as $item) {
                $printer->text(sprintf(
                    "%-15s %5d   %12s\n",
                    $item['name'],
                    $item['qty'],
                    number_format($item['price'] * $item['qty'], 2)
                ));
            }

            // Print totals

            $printer->setJustification(0);
            $padding = 14; // Number of spaces before the text
            $printer->text("---------------------------------------\n");
            $subTotals = "SubTotal  : " . number_format($subTotalitems, 2);

            // Add padding before the text to ensure it starts at character 12
            $rightAlignedSubtotal = str_repeat(' ', $padding) . $subTotals;
            $printer->text("$rightAlignedSubtotal\n");
            $printer->text("---------------------------------------\n");

            // Handled by
            $printer->text("---------------------------------------\n");
            $printer->text("$handledBy\n");

            // Thank you message
            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text("---------------------------------------\n");
            $footer = $setting->receipt_footer;
            $lines = explode('\n', $footer);

            foreach ($lines as $line) {
                $printer->text($line . "\n");
            }

            $printer->text("THANK YOU\n\n\n\n"); // Send a form feed character

            $printer->text("( _ _ _ _ _ _ _ _ _ _ _ )");

            $printer->feed(2); // Adjust the number of lines as needed

            // Cut the receipt
            $printer->cut();

            // Close the printer
            $printer->close();
        } catch (Exception $e) {
            // Handle the printing error here, you can log the error or display a message
            $this->dispatch('printernotfound');
        }
        // dd('No money ' , $invoice);
    }
    public function printwithmoney($code)
    {
        $invoice = Invoice::where('no', $code)->with('detailInvoices')->first();
        $user = Auth::user();
        $setting = Settings::where('wh_code', $user->whs_code)->first();
        $changeFormatted = number_format($invoice->change ?? 0, 2);
        $datafirst = DetailInvoice::where('invoice', $code)->first();

        $printer = $setting->printer_name;
        try {
            $profile = CapabilityProfile::load("default");
            $connector = new WindowsPrintConnector($printer);
            $printer = new Printer($connector, $profile);

            // Set the font size
            $printer->setTextSize(1, 1);

            // Set the justification
            $toko = $setting->wh_name;
            $address = $setting->address;
            $phone = "Telp : " . $setting->phone;
            $manager = "Cashier   : " . Auth::user()->name;
            $billNo = "Bill No   : " . $invoice->no_inv;
            $returNo = "Return No : " . $invoice->no;
            $date = "Date      : " . $invoice->created_at;
            $handledBy = "Handled by : " . $datafirst->sales->name;
            // Define your item list (replace this with your actual item data)
            if ($invoice->payment === "Multi") {
                $note = json_decode($invoice['note'], true);
                $cash = $note['cash'];
                $card = $note['transfer'];
                $change = 0;
            } elseif ($invoice->payment === "Card") {
                $note = json_decode($invoice['note'], true);
                $cash = 0;
                $card = $note['transfer'];
                $change = $invoice->change;
            } elseif ($invoice->payment === "Cash") {
                $cash = $invoice->paid;
                $card = 0;
                $change = $invoice->change;
            } elseif ($invoice->payment === "Qris") {
                $cash = 0;
                $card = $invoice->paid;
                $change = $invoice->change;
            }

            $itemsreturn = [];

            foreach ($invoice->detailInvoices as $cartItem) {
                if ($cartItem['qty'] <= 0) {
                    $name = str_pad(substr($cartItem['name'], 0, 15), 15); // Truncate or pad to 15 characters
                    $itemsreturn[] = [
                        'name' => $name,
                        'qty' => abs($cartItem['qty']),
                        'price' => $cartItem['price'],
                    ];
                }
            }

            $items = [];

            foreach ($invoice->detailInvoices as $cartItem) {
                if ($cartItem['qty'] >= 0) {
                    $name = str_pad(substr($cartItem['name'], 0, 15), 15); // Truncate or pad to 15 characters
                    $items[] = [
                        'name' => $name,
                        'qty' => abs($cartItem['qty']),
                        'price' => $cartItem['price'],
                    ];
                }
            }

            $subTotalreturn = array_reduce($itemsreturn, function ($carry, $item) {
                return $carry + $item['price'] * $item['qty'];
            }, 0);

            $subTotalitems = array_reduce($items, function ($carry, $item) {
                return $carry + $item['price'] * $item['qty'];
            }, 0);

            $grandTotal = $subTotalitems - $subTotalreturn;
            // Start the receipt
            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text("$toko\n$phone\n$address\n");
            $printer->text("---------------------------------------\n");
            $printer->setJustification(0);
            $printer->text("$manager\n$billNo\n$returNo\n$date\n");
            $printer->text("---------------------------------------\n");

            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text(" *ITEM RETURN* \n");
            $printer->setJustification(0);

            // Print the table
            $printer->setJustification(Printer::JUSTIFY_LEFT);
            $printer->text("Item               Qty        Price\n");
            $printer->text("---------------------------------------\n");

            foreach ($itemsreturn as $item) {
                $printer->text(sprintf(
                    "%-15s %5d   %12s\n",
                    $item['name'],
                    $item['qty'],
                    number_format($item['price'] * $item['qty'], 2)
                ));
            }

            // Print totals

            $printer->setJustification(0);
            $padding = 14; // Number of spaces before the text
            $printer->text("---------------------------------------\n");
            $subTotal = "SubTotal  : " . number_format($subTotalreturn, 2);


            // Add padding before the text to ensure it starts at character 12
            $rightAlignedSubtotal = str_repeat(' ', $padding) . $subTotal;
            $printer->text("$rightAlignedSubtotal\n");
            $printer->text("---------------------------------------\n");

            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text(" *ITEMS* \n");
            $printer->setJustification(0);

            // Print the table
            $printer->setJustification(Printer::JUSTIFY_LEFT);
            $printer->text("Item               Qty        Price\n");
            $printer->text("---------------------------------------\n");

            foreach ($items as $item) {
                $printer->text(sprintf(
                    "%-15s %5d   %12s\n",
                    $item['name'],
                    $item['qty'],
                    number_format($item['price'] * $item['qty'], 2)
                ));
            }

            // Print Information card
            if ($invoice->payment === "Card" || $invoice->payment === "Multi") {
                $note = json_decode($invoice->note, true);
                $printer->text("---------------------------------------\n");
                $name = "Name        : " . $note['nama_pemegang_kartu'];
                $nocard = "Card Number : " . $note['nomor_kartu'];
                $printer->text("$nocard\n");
                $printer->text("$name\n");
            }

            $printer->setJustification(0);
            $padding = 14; // Number of spaces before the text
            $printer->text("---------------------------------------\n");
            $subTotals = "SubTotal  : " . number_format($subTotalitems, 2);
            $grandTotal = "GrandTotal: " . number_format($grandTotal, 2);

            // Add padding before the text to ensure it starts at character 12
            $rightAlignedSubtotal = str_repeat(' ', $padding) . $subTotals;
            $rightAlignedGrandTotal = str_repeat(' ', $padding) . $grandTotal;
            $printer->text("$rightAlignedSubtotal\n");
            $printer->text("$rightAlignedGrandTotal\n");
            $cash = "Cash      : " . number_format($cash, 2);
            $card = "Card      : " . number_format($card, 2);
            $change = "Change    : " . $changeFormatted;
            // Add padding before the text to ensure it starts at character 12
            $rightAlignedCash = str_repeat(' ', $padding) . $cash;
            $rightAlignedCard = str_repeat(' ', $padding) . $card;
            $rightAlignedChange = str_repeat(' ', $padding) . $change;


            $printer->text("$rightAlignedCard\n");
            $printer->text("$rightAlignedCash\n");
            $printer->text("$rightAlignedChange\n");
            $printer->text("---------------------------------------\n");


            // Handled by
            $printer->text("---------------------------------------\n");
            $printer->text("$handledBy\n");

            // Thank you message
            $printer->setJustification(Printer::JUSTIFY_CENTER);
            $printer->text("---------------------------------------\n");
            $footer = $setting->receipt_footer;
            $lines = explode('\n', $footer);

            foreach ($lines as $line) {
                $printer->text($line . "\n");
            }

            $printer->text("THANK YOU\n\n\n\n"); // Send a form feed character

            $printer->text("( _ _ _ _ _ _ _ _ _ _ _ )");

            $printer->feed(2); // Adjust the number of lines as needed

            // Cut the receipt
            $printer->cut();

            // Close the printer
            $printer->close();
        } catch (Exception $e) {
            // Handle the printing error here, you can log the error or display a message
            // dd($e);
            $this->dispatch('printernotfound');
        }
    }
}
