<?php

namespace App\Http\Controllers\Api\Finance;

use App\Http\Controllers\Api\BaseApiController;
use App\Http\Requests\Refunds\RefundDecisionRequest;
use App\Http\Requests\Refunds\RefundIndexRequest;
use App\Http\Requests\Refunds\RefundPaymentRequest;
use App\Http\Requests\Refunds\RefundRecalculateRequest;
use App\Http\Requests\Refunds\RefundRejectRequest;
use App\Http\Requests\Refunds\RefundStoreRequest;
use App\Http\Resources\Refunds\RefundResource;
use App\Models\Configuration;
use App\Services\Refunds\RefundDecisionService;
use App\Services\Refunds\RefundOverpaymentService;
use App\Services\Refunds\RefundPayoutService;
use App\Services\Refunds\RefundQueryService;
use App\Services\Refunds\RefundRequestService;
use App\Services\Refunds\RefundSummaryService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

class RefundController extends BaseApiController
{
    public function __construct(
        private RefundQueryService $queryService,
        private RefundRequestService $requestService,
        private RefundDecisionService $decisionService,
        private RefundPayoutService $payoutService,
        private RefundOverpaymentService $overpaymentService,
        private RefundSummaryService $summaryService
    ) {
        parent::__construct();
    }

    public function index(RefundIndexRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $result = $this->queryService->list($payload);

        return response()->json([
            'ok' => true,
            'refunds' => RefundResource::collection($result['refunds']),
            'pagination' => $result['pagination'],
        ]);
    }

    public function show(int $refundId): JsonResponse
    {
        $refund = $this->queryService->find($refundId);
        if (!$refund) {
            return response()->json(['ok' => false, 'message' => 'Refund not found.'], 404);
        }

        return response()->json([
            'ok' => true,
            'refund' => new RefundResource($refund),
        ]);
    }

    public function store(RefundStoreRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $actorId = (int) (auth()->id() ?? 0);

        try {
            $result = $this->requestService->requestRefund($payload, $actorId);
        } catch (\Throwable $e) {
            Log::error('Refund request failed.', ['error' => $e->getMessage()]);
            return response()->json(['ok' => false, 'message' => 'Failed to submit refund request.'], 500);
        }

        if (empty($result['ok'])) {
            return response()->json([
                'ok' => false,
                'message' => $result['message'] ?? 'Failed to submit refund request.',
                'available' => $result['available'] ?? null,
            ], 422);
        }

        return response()->json([
            'ok' => true,
            'refund_id' => $result['refund_id'] ?? null,
            'refund_amount' => $result['refund_amount'] ?? null,
            'status' => $result['status'] ?? null,
        ], 201);
    }

    public function update(RefundDecisionRequest $request, int $refundId): JsonResponse
    {
        $payload = $request->validated();
        $actorId = (int) (auth()->id() ?? 0);

        $result = $this->decisionService->updateDecision(
            $refundId,
            (string) $payload['status'],
            (string) $payload['reason'],
            $actorId
        );

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Failed to update refund.'], 422);
        }

        return response()->json(['ok' => true]);
    }

    public function destroy(int $refundId): JsonResponse
    {
        $actorId = (int) (auth()->id() ?? 0);
        $result = $this->decisionService->cancel($refundId, $actorId);

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Failed to cancel refund.'], 404);
        }

        return response()->json(['ok' => true]);
    }

    public function approve(int $refundId): JsonResponse
    {
        $actorId = (int) (auth()->id() ?? 0);
        $result = $this->decisionService->approve($refundId, $actorId);

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Approve failed.'], 422);
        }

        return response()->json(['ok' => true]);
    }

    public function reject(RefundRejectRequest $request, int $refundId): JsonResponse
    {
        $payload = $request->validated();
        $actorId = (int) (auth()->id() ?? 0);
        $result = $this->decisionService->reject($refundId, (string) $payload['reason'], $actorId);

        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Reject failed.'], 422);
        }

        return response()->json(['ok' => true]);
    }

    public function recordPayment(RefundPaymentRequest $request, int $refundId): JsonResponse
    {
        $payload = $request->validated();
        $payload['check_file'] = $request->file('check_file');
        $actorId = (int) (auth()->id() ?? 0);

        $result = $this->payoutService->recordPayment($refundId, $payload, $actorId);
        if (empty($result['ok'])) {
            return response()->json(['ok' => false, 'message' => $result['message'] ?? 'Failed to update payment.'], 422);
        }

        return response()->json(['ok' => true]);
    }

    public function recalculateOverpayments(RefundRecalculateRequest $request): JsonResponse
    {
        $payload = $request->validated();
        $actorId = (int) (auth()->id() ?? 0);

        $result = $this->overpaymentService->recalculate(true, $payload['invoice_number'] ?? null, $actorId);

        return response()->json([
            'ok' => true,
            'created_ids' => $result['created_ids'] ?? null,
            'updated_ids' => $result['updated_ids'] ?? null,
            'message' => $result['message'] ?? null,
        ]);
    }

    public function parentBalances(int $parentId): JsonResponse
    {
        $termSchoolYear = (string) (Configuration::getConfig('school_year') ?? '');
        $termSemester = (string) (Configuration::getConfig('semester') ?? '');

        $summary = $this->summaryService->getParentFinancialSummary($parentId, $termSchoolYear, $termSemester);

        return response()->json([
            'ok' => true,
            'summary' => $summary,
        ]);
    }
}
