<?php

namespace App\Repositories\Shop;

use App\Datatables\Shop\CustomerInvoicesDataTable;
use App\Datatables\Shop\CustomerOrdersDataTable;
use App\Models\Shop\Customer;
use App\Traits\Model\Basic;
use App\Repositories\Shop\CustomerAddresses;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class Customers
{
    use Basic;

    public static function init()
    {
        return [
            'sale_channels' => SaleChannels::getOptions(),
        ];
    }

    public static function getSaleChannelIds($customerId = false)
    {
        $channels = self::getSaleChannels($customerId);

        return $channels ? $channels->pluck('id')->toArray() : false;
    }

    public static function getSaleChannels($customerId = false)
    {
        $customer = $customerId ? self::get($customerId) : self::getAuth();
        $saleChannels = collect();

        if ($customer) {
            $customer->loadMissing('sale_channels');
            $saleChannels = $customer->sale_channels ?? collect();

            if ($saleChannels instanceof \Illuminate\Support\Collection && $saleChannels->isNotEmpty()) {
                return $saleChannels;
            }
        }

        $default = SaleChannels::getDefault($customerId);

        return $default ? collect([$default]) : collect();
    }

    public static function getSaleChannel($customerId = false)
    {
        $saleChannels = self::getSaleChannels($customerId);

        if ($saleChannels instanceof \Illuminate\Support\Collection) {
            return $saleChannels->first();
        }

        return $saleChannels;
    }

    public static function getDeliveries()
    {
        $customer = self::getAuth();
        $deliveries = $customer ? $customer->deliveries : false;

        return $deliveries ? $deliveries : [Deliveries::getDefault()];
    }

    public static function getOptions()
    {
        return Customer::pluck('last_name', 'id');
    }

    public static function editProfile($id = false)
    {
        if (! $id) {
            abort('403');
        }

        $customer = self::get($id, ['addresses', 'deliveries', 'sale_channels']);

        $saleChannels = self::getSaleChannels($id);

        return [
            'customer' => $customer->toArray(),
            'sale_channels' => $saleChannels->toArray(),
            'deliveries' => Deliveries::getByCustomer($id)->toArray(),
            'sale_channel_checks' => Shop::getSaleChannelAvailabilitySummary($saleChannels->pluck('id')->toArray()),
            'orders' => (new CustomerOrdersDataTable())->html(),
            'invoices' => (new CustomerInvoicesDataTable())->html(),
        ];
    }

    public static function getAddresses($id = false)
    {
        $customer = self::getWithAddresses($id);

        return $customer ? $customer->addresses : false;
    }

    public static function getWithAddresses($id = false)
    {
        $id = $id ? $id : self::getId();

        return self::get($id, ['invoice_addresses', 'delivery_addresses']);
    }

    public static function getName($id = false)
    {
        $user = $id ? self::get($id) : self::getAuth();

        return $user ? $user->name : '';
    }

    public static function edit($id)
    {
        if (!$id) {
            abort('403');
        }
        $customer = self::get($id, ['delivery_addresses', 'invoice_addresses', 'sale_channels']);
        $data = $customer->toArray();
        $data['sale_channels'] = $customer->sale_channels->pluck('id')->toArray();
        $data['deliveries'] = Deliveries::getBySaleChannels($data['sale_channels'])->toArray();
        $data['delivery_address_id'] = optional(CustomerAddresses::getDeliveryAddress($id))->id;
        $data['invoice_address_id'] = optional(CustomerAddresses::getInvoiceAddress($id))->id;

        if (! $data['delivery_address_id'] && ! empty($data['delivery_addresses'])) {
            $data['delivery_address_id'] = $data['delivery_addresses'][0]['id'] ?? null;
        }

        if (! $data['invoice_address_id'] && ! empty($data['invoice_addresses'])) {
            $data['invoice_address_id'] = $data['invoice_addresses'][0]['id'] ?? null;
        }

        return $data;
    }

    public static function storeFull($data)
    {
        $data2 = $data;
        $saleChannels = array_key_exists('sale_channels', $data) ? $data['sale_channels'] : null;
        if ($saleChannels !== null) {
            unset($data['sale_channels']);
        }
        if ($data['deliveries'] ?? false) {
            unset($data['deliveries']);
        }
        if ($data['invoices'] ?? false) {
            unset($data['invoices']);
        }
        $customer = self::store($data);
        if ($saleChannels !== null) {
            $customer->sale_channels()->sync($saleChannels);
        }
        CustomerAddresses::storeByCustomer($customer, $data2);

        return $customer->id;
    }

    public static function storeDeliveries($customerId, $deliveries)
    {
        $customer = self::get($customerId);

        return $customer->deliveries()->sync($deliveries);
    }

    public static function storeAddresses($customerId, $addresses)
    {
        foreach ($addresses as $address) {
            $address['customer_id'] = $customerId;
            CustomerAddresses::store($address);
        }
    }

    public static function storeSaleChannels($customerId, $saleChannels)
    {
        $customer = self::get($customerId);

        return $customer->sale_channels()->sync($saleChannels);
    }

    public static function setDefaultSaleChannel($customerId, $saleChannelId)
    {
        if (! $customerId) {
            return false;
        }

        $customer = self::get($customerId);

        if (! $customer) {
            return false;
        }

        $customer->default_sale_channel_id = $saleChannelId ?: null;
        $customer->save();

        return $customer->fresh(['sale_channels']);
    }

    public static function create($data)
    {
        $data['uuid'] = Str::uuid();
        $data['active'] = true;
        $data['password'] = bcrypt($data['password']);

        return Customer::create($data);
    }

    public static function getAuth()
    {
        return self::guard()->user();
    }

    public static function getId()
    {
        return self::guard()->id();
    }

    public static function isNotConnected()
    {
        return !self::isConnected();
    }

    public static function isConnected()
    {
        return self::guard()->check();
    }

    public static function guard()
    {
        return Auth::guard('customer');
    }

    public static function getModel()
    {
        return Customer::query();
    }
}
