<?php

namespace App\Livewire\Studio\Dashboard;

use App\Models\Bottle;
use App\Models\Brand;
use App\Models\Category;
use App\Models\Customer;
use App\Models\Expense;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Outlet;
use App\Models\Payroll;
use App\Models\Perfume;
use App\Models\Product;
use App\Models\Purchase;
use App\Models\Tier;
use App\Models\User;
use App\Models\Voucher;
use Carbon\Carbon;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Title('Analisa')]
class Analysis extends Component
{
    public string $period = 'all';

    public array $outlets = [];

    public array $range = [
        'start' => null,
        'end' => null,
    ];

    public array $selectedOutletIds = [];

    public array $countingData = [];

    public array $orders = [];

    public array $expenses = [];

    public array $topPerfumes = [];

    public array $topProducts = [];

    public array $topBottles = [];

    public function mount()
    {
        $this->outlets = auth()->user()->outlets()->get()->pluck('name', 'id')->toArray();

        $this->loadData();
    }

    public function updatedPeriod(string $period)
    {
        $this->loadData();
    }

    public function updatedSelectedOutletIds()
    {
        $this->loadData();
    }

    public function updatedRange($range)
    {
        $this->loadData();
    }

    protected function loadData()
    {
        $outletIds = $this->selectedOutletIds;
        $period = $this->period;
        $range = $this->range;

        $dateQuery = match ($period) {
            '7' => now()->subDays(1),
            '30' => now()->subDays(30),
            '90' => now()->subDays(90),
            '365' => now()->subDays(365),
            default => null,
        };

        $startDate = ! empty($range['start']) ? Carbon::parse($range['start'])->startOfDay() : null;
        $endDate = ! empty($range['end']) ? Carbon::parse($range['end'])->endOfDay() : null;

        if ($startDate && $endDate) {
            $dateQuery = null;
        }

        $filterDate = function ($q) use ($dateQuery, $startDate, $endDate) {
            if ($startDate && $endDate) {
                $q->whereBetween('created_at', [$startDate, $endDate]);
            } elseif ($dateQuery) {
                $q->where('created_at', '>=', $dateQuery);
            }
        };

        $this->countingData = [
            [
                'title' => 'Outlet',
                'value' => Outlet::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
            ],
            [
                'title' => 'Pegawai',
                'value' => User::whereHas('employee')
                    ->when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->count(),
            ],
            [
                'title' => 'Tier',
                'value' => Tier::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
            ],
            [
                'title' => 'Voucher Aktif',
                'value' => Voucher::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->active()
                    ->count(),
            ],
            [
                'title' => 'Member',
                'value' => User::whereHas('customer')
                    ->when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->count(),
            ],
            [
                'title' => 'Customer',
                'value' => Customer::whereDoesntHave('user')
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->count(),
            ],
            [
                'title' => 'Kategori',
                'value' => Category::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
            ],
            [
                'title' => 'Merek',
                'value' => Brand::when($dateQuery || ($startDate && $endDate), $filterDate)->count(),
            ],
            [
                'title' => 'Parfum',
                'value' => Perfume::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->count(),
            ],
            [
                'title' => 'Produk',
                'value' => Product::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->count(),
            ],
            [
                'title' => 'Botol',
                'value' => Bottle::when(! empty($outletIds), fn ($q) => $q->whereHas('outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                    ->when($dateQuery || ($startDate && $endDate), $filterDate)
                    ->count(),
            ],
        ];

        $this->orders = [
            [
                'title' => 'Total Order',
                'value' => currency(
                    Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->count()
                ),
            ],
            [
                'title' => 'Pendapatan',
                'value' => currency(
                    Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->sum('total'),
                    'Rp'
                ),
            ],
            [
                'title' => 'HPP',
                'value' => currency(
                    Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->sum('cogs'),
                    'Rp'
                ),
            ],
            [
                'title' => 'Diskon',
                'value' => currency(
                    Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->sum('discount'),
                    'Rp'
                ),
            ],
            [
                'title' => 'Voucher Terpakai',
                'value' => currency(
                    Order::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->whereNotNull('voucher_id')->count()
                ),
            ],
            [
                'title' => 'Parfum Terjual',
                'value' => currency(
                    OrderItem::where('orderable_type', Perfume::class)
                        ->whereHas('order', fn ($q) => $q->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))->when($dateQuery || ($startDate && $endDate), $filterDate))
                        ->sum('quantity')
                ).' ml',
            ],
            [
                'title' => 'Produk Terjual',
                'value' => currency(
                    OrderItem::where('orderable_type', Product::class)
                        ->whereHas('order', fn ($q) => $q->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))->when($dateQuery || ($startDate && $endDate), $filterDate))
                        ->sum('quantity')
                ).' pcs',
            ],
            [
                'title' => 'Botol Terjual',
                'value' => currency(
                    OrderItem::where('orderable_type', Bottle::class)
                        ->whereHas('order', fn ($q) => $q->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds))->when($dateQuery || ($startDate && $endDate), $filterDate))
                        ->sum('quantity')
                ).' pcs',
            ],
        ];

        $this->expenses = [
            [
                'title' => 'Beban Toko',
                'value' => currency(
                    Expense::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->sum('amount'),
                    'Rp'
                ),
            ],
            [
                'title' => 'Belanja Barang',
                'value' => currency(
                    Purchase::when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->sum('total'),
                    'Rp'
                ),
            ],
            [
                'title' => 'Penggajian',
                'value' => currency(
                    Payroll::when(! empty($outletIds), fn ($q) => $q->whereHas('user.outlets', fn ($q2) => $q2->whereIn('outlets.id', $outletIds)))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate)
                        ->sum('total_salary'),
                    'Rp'
                ),
            ],
        ];

        $this->topPerfumes = Perfume::with(['items' => function ($query) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
            $query->whereNotNull('order_id')
                ->whereHas('order', function ($q) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
                    $q->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate);
                });
        }])
            ->select('id', 'name', 'sale_price')
            ->get()
            ->map(fn ($perfume) => [
                'name' => $perfume->name,
                'sale_price' => currency($perfume->sale_price, 'Rp'),
                'total_sold' => currency($perfume->items->sum('quantity')),
                'total_sales' => currency($perfume->items->sum(fn ($item) => $item->order?->total ?? 0), 'Rp'),
            ])
            ->sortByDesc('total_sales')
            ->filter(fn ($product) => $product['total_sold'] > 0)
            ->take(5)
            ->toArray();

        $this->topProducts = Product::with(['items' => function ($query) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
            $query->whereNotNull('order_id')
                ->whereHas('order', function ($q) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
                    $q->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate);
                });
        }])
            ->select('id', 'name', 'sale_price')
            ->get()
            ->map(fn ($product) => [
                'name' => $product->name,
                'sale_price' => currency($product->sale_price, 'Rp'),
                'total_sold' => currency($product->items->sum('quantity')),
                'total_sales' => currency($product->items->sum(fn ($item) => $item->order?->total ?? 0), 'Rp'),
            ])
            ->sortByDesc('total_sales')
            ->filter(fn ($product) => $product['total_sold'] > 0)
            ->take(5)
            ->toArray();

        $this->topBottles = Bottle::with(['items' => function ($query) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
            $query->whereNotNull('order_id')
                ->whereHas('order', function ($q) use ($outletIds, $dateQuery, $startDate, $endDate, $filterDate) {
                    $q->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds))
                        ->when($dateQuery || ($startDate && $endDate), $filterDate);
                });
        }])
            ->select('id', 'name', 'sale_price')
            ->get()
            ->map(fn ($bottle) => [
                'name' => $bottle->name,
                'sale_price' => currency($bottle->sale_price, 'Rp'),
                'total_sold' => currency($bottle->items->sum('quantity')),
                'total_sales' => currency($bottle->items->sum(fn ($item) => $item->order?->total ?? 0), 'Rp'),
            ])
            ->sortByDesc('total_sales')
            ->filter(fn ($product) => $product['total_sold'] > 0)
            ->take(5)
            ->toArray();
    }

    public function render()
    {
        return view('livewire.studio.dashboard.analysis', [
            'pageTitle' => 'Analisa',
        ]);
    }
}
