<?php

namespace App\Http\Controllers\Api\Seller;

use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\SellerProductSale;
use App\Models\Store;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ProductSaleController extends Controller
{
    public function quickSell(Request $request, Product $product): JsonResponse
    {
        $store = $request->user()->store;

        if (!$store || $product->store_id !== $store->id) {
            return response()->json(['message' => 'Bu ürünü satma yetkiniz yok.'], 403);
        }

        $validated = $request->validate([
            'quantity' => 'required|integer|min:1|max:100000',
            'customer_name' => 'nullable|string|max:255',
        ]);

        try {
            $sale = DB::transaction(function () use ($product, $store, $request, $validated) {
                $locked = Product::query()
                    ->whereKey($product->id)
                    ->where('store_id', $store->id)
                    ->lockForUpdate()
                    ->first();

                if (!$locked || $locked->stock_quantity < $validated['quantity']) {
                    throw new \RuntimeException('INSUFFICIENT_STOCK');
                }

                $locked->decrement('stock_quantity', $validated['quantity']);

                return SellerProductSale::create([
                    'store_id' => $store->id,
                    'product_id' => $locked->id,
                    'created_by' => $request->user()->id,
                    'quantity' => $validated['quantity'],
                    'customer_name' => $validated['customer_name'] ?: null,
                ]);
            });

            $sale->load('product:id,name');

            return response()->json([
                'message' => 'Satış kaydedildi.',
                'data' => $sale,
            ], 201);
        } catch (\RuntimeException $e) {
            if ($e->getMessage() === 'INSUFFICIENT_STOCK') {
                return response()->json([
                    'message' => 'Yeterli stok yok.',
                ], 422);
            }
            throw $e;
        }
    }

    public function index(Request $request): JsonResponse
    {
        $store = $request->user()->store;

        if (!$store) {
            return response()->json(['message' => 'Mağazanız bulunamadı.'], 404);
        }

        $request->validate([
            'customer_search' => ['sometimes', 'nullable', 'string', 'max:255'],
            'product_search' => ['sometimes', 'nullable', 'string', 'max:255'],
            'from' => ['sometimes', 'nullable', 'date'],
            'to' => ['sometimes', 'nullable', 'date'],
            'product_id' => ['sometimes', 'nullable', 'integer'],
        ]);

        $query = SellerProductSale::query()
            ->where('store_id', $store->id)
            ->with(['product:id,name'])
            ->orderByDesc('created_at');

        $this->applySaleListFilters($query, $request);

        return response()->json($query->paginate(min($request->integer('per_page', 25), 50)));
    }

    /**
     * Özet rapor: toplamlar, günlük seri (eksik günler 0), ürün kırılımı.
     * Ciro: quantity × güncel products.price (satış anı fiyatı saklanmıyor).
     */
    public function report(Request $request): JsonResponse
    {
        $store = $request->user()->store;

        if (!$store) {
            return response()->json(['message' => 'Mağazanız bulunamadı.'], 404);
        }

        $request->validate([
            'customer_search' => ['sometimes', 'nullable', 'string', 'max:255'],
            'product_search' => ['sometimes', 'nullable', 'string', 'max:255'],
            'from' => ['sometimes', 'nullable', 'date'],
            'to' => ['sometimes', 'nullable', 'date'],
            'product_id' => ['sometimes', 'nullable', 'integer'],
        ]);

        [$from, $to] = $this->resolveReportPeriod($request);

        $base = $this->filteredSalesJoinQuery($store, $request, $from, $to);

        $totalsRow = (clone $base)
            ->selectRaw('COUNT(*) as transaction_count')
            ->selectRaw('COALESCE(SUM(seller_product_sales.quantity), 0) as quantity_sum')
            ->selectRaw('COALESCE(SUM(seller_product_sales.quantity * products.price), 0) as revenue_sum')
            ->first();

        $dailyRows = (clone $base)
            ->selectRaw('DATE(seller_product_sales.created_at) as sale_date')
            ->selectRaw('SUM(seller_product_sales.quantity) as quantity_sum')
            ->selectRaw('SUM(seller_product_sales.quantity * products.price) as revenue_sum')
            ->groupBy('sale_date')
            ->orderBy('sale_date')
            ->get()
            ->keyBy(fn ($r) => Carbon::parse($r->sale_date)->format('Y-m-d'));

        $daily = [];
        foreach (CarbonPeriod::create($from->toDateString(), $to->toDateString()) as $day) {
            $key = $day->format('Y-m-d');
            $row = $dailyRows->get($key);
            $daily[] = [
                'date' => $key,
                'quantity' => (int) ($row?->quantity_sum ?? 0),
                'revenue' => round((float) ($row?->revenue_sum ?? 0), 2),
            ];
        }

        $byProduct = (clone $base)
            ->select([
                'seller_product_sales.product_id',
                'products.name',
            ])
            ->selectRaw('SUM(seller_product_sales.quantity) as quantity_sum')
            ->selectRaw('SUM(seller_product_sales.quantity * products.price) as revenue_sum')
            ->groupBy('seller_product_sales.product_id', 'products.name')
            ->orderByDesc('quantity_sum')
            ->limit(50)
            ->get()
            ->map(fn ($row) => [
                'product_id' => (int) $row->product_id,
                'name' => $row->name,
                'quantity' => (int) $row->quantity_sum,
                'revenue' => round((float) $row->revenue_sum, 2),
            ])
            ->values()
            ->all();

        return response()->json([
            'period' => [
                'from' => $from->format('Y-m-d'),
                'to' => $to->format('Y-m-d'),
            ],
            'totals' => [
                'transaction_count' => (int) ($totalsRow->transaction_count ?? 0),
                'quantity_sum' => (int) ($totalsRow->quantity_sum ?? 0),
                'revenue' => round((float) ($totalsRow->revenue_sum ?? 0), 2),
            ],
            'daily' => $daily,
            'by_product' => $byProduct,
        ]);
    }

    /**
     * @return array{0: \Carbon\Carbon, 1: \Carbon\Carbon}
     */
    private function resolveReportPeriod(Request $request): array
    {
        $hasFrom = $request->filled('from');
        $hasTo = $request->filled('to');

        if (!$hasFrom && !$hasTo) {
            $to = Carbon::now()->startOfDay();
            $from = $to->copy()->subDays(29);

            return [$from, $to];
        }

        $to = $hasTo
            ? Carbon::parse($request->input('to'))->startOfDay()
            : Carbon::now()->startOfDay();

        $from = $hasFrom
            ? Carbon::parse($request->input('from'))->startOfDay()
            : $to->copy()->subDays(29);

        if ($from->greaterThan($to)) {
            [$from, $to] = [$to->copy(), $from->copy()];
        }

        return [$from, $to];
    }

    /**
     * JOIN products — rapor aggregasyonları için (arama + ciro).
     */
    private function filteredSalesJoinQuery(Store $store, Request $request, Carbon $from, Carbon $to): Builder
    {
        $q = SellerProductSale::query()
            ->where('seller_product_sales.store_id', $store->id)
            ->join('products', 'products.id', '=', 'seller_product_sales.product_id')
            ->whereDate('seller_product_sales.created_at', '>=', $from)
            ->whereDate('seller_product_sales.created_at', '<=', $to);

        if ($request->filled('product_id')) {
            $q->where('seller_product_sales.product_id', $request->integer('product_id'));
        }

        $customerSearch = trim((string) $request->input('customer_search', ''));
        if ($customerSearch !== '') {
            $like = '%'.$this->escapeLike($customerSearch).'%';
            $q->where('seller_product_sales.customer_name', 'like', $like);
        }

        $productSearch = trim((string) $request->input('product_search', ''));
        if ($productSearch !== '') {
            $like = '%'.$this->escapeLike($productSearch).'%';
            $q->where('products.name', 'like', $like);
        }

        return $q;
    }

    private function applySaleListFilters(Builder $query, Request $request): void
    {
        if ($request->filled('product_id')) {
            $query->where('product_id', $request->integer('product_id'));
        }

        if ($request->filled('from')) {
            $query->whereDate('created_at', '>=', $request->date('from'));
        }

        if ($request->filled('to')) {
            $query->whereDate('created_at', '<=', $request->date('to'));
        }

        $customerSearch = trim((string) $request->input('customer_search', ''));
        if ($customerSearch !== '') {
            $like = '%'.$this->escapeLike($customerSearch).'%';
            $query->where('customer_name', 'like', $like);
        }

        $productSearch = trim((string) $request->input('product_search', ''));
        if ($productSearch !== '') {
            $like = '%'.$this->escapeLike($productSearch).'%';
            $query->whereHas('product', function ($q) use ($like) {
                $q->where('name', 'like', $like);
            });
        }
    }

    private function escapeLike(string $value): string
    {
        return str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], $value);
    }
}
