<?php

namespace App\Http\Controllers\Api\V1\Admin\Ticket;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\TicketItemListRequest;
use App\Models\TicketItem;
use App\Support\ApiResponse;
use App\Support\CurrencyFormatter;
use App\Support\PaginationTrait;
use App\Support\AdminScopePolicy;
use App\Support\AgentNodeApiPresenter;
use App\Support\TicketItemListFilters;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * 后台：全量注单列表。
 *
 * Query：
 * - `page`、`per_page` / `size`
 * - `player_id`（可选）
 * - `player_account`（可选，模糊匹配 `players.site_player_id` / `username` / `nickname`）
 * - `draw_no`（可选）
 * - `status[]`（可选）
 * - `number`（可选，模糊匹配注项号/号码/订单号）
 * - `start_date` / `end_date`（可选，`Y-m-d`，按订单创建时间）
 */
final class AdminTicketItemIndexController extends Controller
{
    use PaginationTrait;
    use TicketItemListFilters;

    public function __invoke(TicketItemListRequest $request): JsonResponse
    {
        $admin = $request->lotteryAdmin();
        abort_if($admin === null, 401);

        $validated = $request->validated();
        $scope = AdminScopePolicy::resolveContext($request, $admin);

        $perPage = $this->perPage($request, 'per_page', 10, 100);
        $page = $this->page($request);

        $query = TicketItem::query()
            ->with([
                'draw:id,draw_no,business_date',
                'order:id,order_no,currency_code,created_at',
                'player:id,site_code,site_player_id,username,nickname,agent_node_id,funding_mode',
                'player.agentNode:id,code,name',
            ])
            ->orderByDesc('ticket_items.id');

        if (! empty($validated['player_id'])) {
            $query->where('ticket_items.player_id', (int) $validated['player_id']);
        } elseif (! empty($validated['player_account'])) {
            $term = '%'.addcslashes(trim((string) $validated['player_account']), '%_\\').'%';
            $query->whereHas('player', function ($q) use ($term): void {
                $q->where('site_player_id', 'like', $term)
                    ->orWhere('username', 'like', $term)
                    ->orWhere('nickname', 'like', $term);
            });
        }

        $drawNo = $validated['draw_no'] ?? null;
        if (is_string($drawNo) && trim($drawNo) !== '') {
            $query->whereHas('draw', fn ($q) => $q->where('draw_no', trim($drawNo)));
        }

        $statusInput = $validated['status'] ?? [];
        if (is_string($statusInput)) {
            $statusInput = [$statusInput];
        }
        $statusValues = is_array($statusInput)
            ? array_values(array_filter(array_map(
                fn ($status) => is_string($status) ? trim($status) : '',
                $statusInput,
            )))
            : [];
        if ($statusValues !== []) {
            $query->whereIn('ticket_items.status', $statusValues);
        }

        $number = trim((string) ($validated['number'] ?? ''));
        $this->applyTicketItemNumberSearch($query, $number);
        $this->applyOrderPlacedDateRange(
            $query,
            is_string($validated['start_date'] ?? null) ? $validated['start_date'] : null,
            is_string($validated['end_date'] ?? null) ? $validated['end_date'] : null,
        );

        AdminScopePolicy::applyViaPlayerRelationWithContext($query, $scope, 'player');

        $paginator = $query->paginate(perPage: $perPage, page: $page, columns: ['*']);

        $items = collect($paginator->items())->map(function (TicketItem $row): array {
            $totalBet = (int) $row->total_bet_amount;
            $actualDeduct = (int) $row->actual_deduct_amount;
            $winAmount = (int) $row->win_amount;
            $jackpotWin = (int) $row->jackpot_win_amount;

            return [
                'id' => $row->id,
                'ticket_no' => $row->ticket_no,
                ...AgentNodeApiPresenter::embed($row->player?->agentNode),
                'player_id' => $row->player_id,
                'site_code' => $row->player?->site_code,
                'site_player_id' => $row->player?->site_player_id,
                'username' => $row->player?->username,
                'nickname' => $row->player?->nickname,
                'funding_mode' => $row->player?->funding_mode,
                'uses_credit' => $row->player?->funding_mode === 'credit',
                'order_no' => $row->order?->order_no,
                'draw_no' => $row->draw?->draw_no,
                'currency_code' => $row->order?->currency_code,
                'play_code' => $row->play_code,
                'original_number' => $row->original_number,
                // 历史字段：保留兼容，实际单位为 minor。
                'total_bet_amount' => $totalBet,
                'total_bet_amount_minor' => $totalBet,
                'total_bet_amount_formatted' => CurrencyFormatter::fromMinor($totalBet),
                // 历史字段：保留兼容，实际单位为 minor。
                'actual_deduct_amount' => $actualDeduct,
                'actual_deduct_amount_minor' => $actualDeduct,
                'actual_deduct_amount_formatted' => CurrencyFormatter::fromMinor($actualDeduct),
                'status' => $row->status,
                'fail_reason_code' => $row->fail_reason_code,
                'fail_reason_text' => $row->fail_reason_text,
                // 历史字段：保留兼容，实际单位为 minor。
                'win_amount' => $winAmount,
                'win_amount_minor' => $winAmount,
                'win_amount_formatted' => CurrencyFormatter::fromMinor($winAmount),
                // 历史字段：保留兼容，实际单位为 minor。
                'jackpot_win_amount' => $jackpotWin,
                'jackpot_win_amount_minor' => $jackpotWin,
                'jackpot_win_amount_formatted' => CurrencyFormatter::fromMinor($jackpotWin),
                'placed_at' => $row->order?->created_at?->toIso8601String(),
                'updated_at' => $row->updated_at?->toIso8601String(),
            ];
        })->values()->all();

        return ApiResponse::success([
            'items' => $items,
            'total' => $paginator->total(),
            'page' => $paginator->currentPage(),
            'per_page' => $paginator->perPage(),
            'last_page' => $paginator->lastPage(),
        ]);
    }
}
