<?php

namespace App\Repositories\Shop;

use App\Models\Shop\Offer;
use App\Models\Shop\PriceList;
use App\Models\Shop\PriceListValue;
use App\Models\Shop\SaleChannel;
use App\Traits\Model\Basic;

class Offers
{
    use Basic;

    public static function init()
    {
        return [
            'articles' => Articles::getOptionsWithNature(),
            'article_visibilities' => Articles::getVisibilityMap(),
            'tariffs' => Tariffs::getOptions(),
            'tariff_statuses' => Tariffs::getStatusMap(),
            'tariff_status_labels' => Tariffs::getStatuses(),
            'tariff_pricelist_counts' => Tariffs::getPriceListCountMap(),
            'variations' => Variations::getOptions(),
        ];
    }

    public static function decreaseStock($item)
    {
        $offer = self::get($item['offer_id']);
        $offer->stock_current = $offer->stock_current - $item['quantity'];
        if ($offer->stock_current <= 0) {
            $offer->stock_current = 0;
        }

        return $offer->save();
    }

    public static function getStockCurrent($id)
    {
        return self::getField($id, 'stock_current');
    }

    public static function getWeight($id, $quantity = 1)
    {
        $offer = self::get($id);

        return $offer ? $offer->weight * $quantity : 0;
    }

    public static function getWithVariationByIds($ids)
    {
        return Offer::with('variation')->byIds($ids)->get();
    }

    public static function getWithPricesByIds($ids, $saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();

        return Offer::with([
            'variation',
            'article.article_nature',
            'article.product',
            'article.image',
            'price_lists.price_list_values',
        ])->withPriceListsBySaleChannel($saleChannelId)->byIds($ids)->get();
    }

    public static function getFull($id, $saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();
        $offer = Offer::with([
            'article.article_nature',
            'article.product',
            'tariff' => function ($query) use ($saleChannelId) {
                $query->bySaleChannel($saleChannelId);
            },
            'tariff.price_lists' => function ($query) use ($saleChannelId) {
                $query->BySaleChannel($saleChannelId);
            },
            'tariff.price_lists.price_list_values',
            'variation',
        ])->find($id);
        $images = ArticleImages::getFullImagesByArticle($offer->article);
        $offer->article->image = Articles::getPreviewSrc($images[0] ?? false);

        return $offer;
    }

    public static function getPrice($id, $quantity = 1, $saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();
        $offer = Offer::withPriceBySaleChannelByQuantity($saleChannelId, $quantity)->find($id);
        $priceList = $offer->price_lists->first();

        return $priceList ? $priceList->price_list_values->first() : false;
    }

    public static function getOffersByArticles($article_ids, $saleChannelId = false)
    {
        return self::getOffersBySaleChannelRaw($saleChannelId)->byArticles($article_ids)->get();
    }

    public static function getOffersByArticle($article_id, $saleChannelId = false)
    {
        return self::getOffersBySaleChannelRaw($saleChannelId)->byArticle($article_id)->get();
    }

    public static function getOffersBySaleChannel($saleChannelId = false)
    {
        return self::getOffersBySaleChannelRaw($saleChannelId)->get();
    }

    public static function getOffersBySaleChannelRaw($saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();

        return Offer::active()->byStockAvailable()
            ->with([
                'article_nature',
                'variation',
                'tariff.price_lists' => function ($query) use ($saleChannelId) {
                    $query->bySaleChannel($saleChannelId);
                },
                'tariff.price_lists.price_list_values',
            ])
            ->bySaleChannel($saleChannelId);
    }

    public static function getThumbSrcById($id)
    {
        return self::getThumbSrc(self::get($id));
    }

    public static function getThumbSrc(Offer $offer)
    {
        $image = $offer->article ? ArticleImages::getFullImageByArticle($offer->article) : false;

        return $image ? Articles::getThumbSrc($image) : false;
    }

    public static function getLast()
    {
        return Offer::with(['article.image'])->active()->orderByDesc('updated_at')->get();
    }

    public static function getByCategoryWithTags($category_id)
    {
        $category = Categories::get($category_id);
        $tags = Categories::getTagsByCategory($category);
        $offers1 = self::getByCategory($category_id)->toArray();
        $offers2 = self::getByTags($tags)->toArray();

        return array_merge($offers1, $offers2);
    }

    public static function getByCategory($category_id)
    {
        return Offer::with(['article.image'])->byCategory($category_id)->get();
    }

    public static function getByTags($tags)
    {
        return Offer::with(['article.tags'])->byTags($tags)->get();
    }

    public static function toggleActive($id, $status_id)
    {
        return self::update(['status_id' => $status_id], $id);
    }

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

    public static function getSaleChannelsForArticle($articleId)
    {
        $channels = SaleChannel::query()
            ->whereHas('price_lists', function ($query) use ($articleId) {
                $query->whereHas('tariff.offers', function ($subQuery) use ($articleId) {
                    $subQuery->byArticle($articleId);
                })->whereHas('price_list_values');
            })
            ->orderBy('name')
            ->get();

        $offers = Offer::query()
            ->byArticle($articleId)
            ->with([
                'article',
                'tariff:id,status_id',
                'variation',
            ])
            ->get();

        return $channels->map(function ($channel) use ($offers) {
            $priceValue = null;
            $candidateOffer = null;
            $allOffersForChannel = [];

            foreach ($offers as $offer) {
                $priceCandidate = self::getPrice($offer->id, 1, $channel->id);

                if ($priceCandidate && (float) $priceCandidate->price_taxed > 0) {
                    // Get price list name
                    $priceListName = null;
                    if ($priceCandidate) {
                        $priceListModel = PriceList::find($priceCandidate->price_list_id);
                        $priceListName = $priceListModel ? $priceListModel->name : null;
                    }

                    // Collect all offers with their details
                    $allOffersForChannel[] = [
                        'id' => $offer->id,
                        'variation_name' => $offer->variation ? $offer->variation->name : null,
                        'stock_current' => (int) $offer->stock_current,
                        'status_id' => (int) $offer->status_id,
                        'is_active' => (int) $offer->status_id === 1,
                        'tariff_id' => $offer->tariff_id ? (int) $offer->tariff_id : null,
                        'price_taxed' => (float) $priceCandidate->price_taxed,
                        'quantity' => (int) $priceCandidate->quantity,
                        'price_list_name' => $priceListName,
                    ];

                    // Keep first valid offer as the main candidate
                    if (!$candidateOffer) {
                        $priceValue = $priceCandidate;
                        $candidateOffer = $offer;
                    }
                }
            }

            $offerId = $candidateOffer ? $candidateOffer->id : null;
            $offerStock = $candidateOffer ? (int) $candidateOffer->stock_current : null;
            $offerIsActive = $candidateOffer ? (int) $candidateOffer->status_id === 1 : false;
            $offerTariffStatus = $candidateOffer && $candidateOffer->tariff ? (int) $candidateOffer->tariff->status_id : null;
            $offerHasStock = $candidateOffer && $candidateOffer->stock_current !== null
                ? (float) $candidateOffer->stock_current > 0
                : null;
            $offerTariffId = $candidateOffer && $candidateOffer->tariff_id ? (int) $candidateOffer->tariff_id : null;

            return [
                'id' => $channel->id,
                'name' => $channel->name,
                'code' => $channel->code,
                'price_taxed' => $priceValue ? (float) $priceValue->price_taxed : null,
                'quantity' => $priceValue ? (int) $priceValue->quantity : null,
                'offer_id' => $offerId,
                'offer_is_active' => $offerIsActive,
                'offer_stock_current' => $offerStock,
                'offer_has_stock' => $offerHasStock,
                'tariff_status_id' => $offerTariffStatus,
                'tariff_id' => $offerTariffId,
                'all_offers' => $allOffersForChannel,
            ];
        })->toArray();
    }
}
