<?php

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

use App\Support\ApiResponse;
use Illuminate\Http\Request;
use App\Support\PaginationTrait;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Database\Query\Builder;
use App\Support\AdminAgentSettlementScope;

final class AgentSettlementAdjustmentIndexController extends Controller
{
    use PaginationTrait;

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

        $periodId = (int) $request->query('settlement_period_id', 0);
        $adminSiteId = (int) $request->query('admin_site_id', 0);
        $adjustmentType = trim((string) $request->query('adjustment_type', ''));

        $query = DB::table('settlement_adjustments as sa')
            ->leftJoin('settlement_periods as sp', 'sp.id', '=', 'sa.settlement_period_id')
            ->leftJoin('settlement_bills as sb', 'sb.id', '=', 'sa.original_bill_id')
            ->select([
                'sa.*',
                'sp.period_start',
                'sp.period_end',
                'sp.admin_site_id',
                'sb.bill_type as original_bill_type',
                'sb.owner_type as original_owner_type',
                'sb.owner_id as original_owner_id',
            ])
            ->orderByDesc('sa.id');

        if ($periodId > 0) {
            $query->where('sa.settlement_period_id', $periodId);
        }

        if ($adminSiteId > 0) {
            $query->where('sp.admin_site_id', $adminSiteId);
        }

        if ($adjustmentType !== '') {
            $query->where('sa.adjustment_type', $adjustmentType);
        }

        $siteIds = $admin->accessibleAdminSiteIds();
        if ($siteIds !== null) {
            if ($siteIds === []) {
                $query->whereRaw('0 = 1');
            } else {
                $query->whereIn('sp.admin_site_id', $siteIds);
            }
        }

        $actorId = AdminAgentSettlementScope::boundAgentNodeId($admin);
        if ($actorId !== null) {
            $query->where(function (Builder $outer) use ($admin): void {
                $outer->whereNull('sa.original_bill_id')
                    ->orWhereExists(function (Builder $exists) use ($admin): void {
                        $exists->selectRaw('1')
                            ->from('settlement_bills as sb')
                            ->whereColumn('sb.id', 'sa.original_bill_id');
                        AdminAgentSettlementScope::applyDirectEdgeScopeToBillsQuery($exists, $admin, 'sb');
                    });
            });
        }

        $meta = $this->paginationMeta($request, defaultPerPage: 20, maxPerPage: 200);
        $paginator = $query->paginate(
            $meta['per_page'],
            ['sa.*', 'sp.period_start', 'sp.period_end', 'sp.admin_site_id', 'sb.bill_type as original_bill_type', 'sb.owner_type as original_owner_type', 'sb.owner_id as original_owner_id'],
            'page',
            $meta['page'],
        );

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