<?php

declare(strict_types=1);

namespace ImovelZapAi\Financial\Presentation\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use ImovelZapAi\Financial\Application\Actions\CompleteTransferAction;
use ImovelZapAi\Financial\Application\Actions\CreateDealFinancialBootstrapAction;
use ImovelZapAi\Financial\Application\Actions\CreateTransferAction;
use ImovelZapAi\Financial\Application\Actions\EnsureDefaultCommissionRuleAction;
use ImovelZapAi\Financial\Application\Actions\RecordPaymentAction;
use ImovelZapAi\Financial\Application\Queries\GetDealFinancialStatementQuery;
use ImovelZapAi\Financial\Application\Queries\GetFinancialDashboardQuery;
use ImovelZapAi\Financial\Application\Queries\ListFinancialTransactionsQuery;
use ImovelZapAi\Financial\Domain\Enums\CommissionBasis;
use ImovelZapAi\Financial\Domain\Enums\DealFinanceType;
use ImovelZapAi\Financial\Domain\Enums\PaymentMethod;
use ImovelZapAi\Financial\Domain\Exceptions\FinancialException;
use ImovelZapAi\Financial\Infrastructure\Persistence\Eloquent\FinancialCommissionRuleModel;
use ImovelZapAi\Sales\Infrastructure\Persistence\Eloquent\DealModel;
use ImovelZapAi\Tenancy\Support\TenantContext;

final class FinancialWebController extends Controller
{
    public function index(
        GetFinancialDashboardQuery $dashboard,
        ListFinancialTransactionsQuery $list,
    ): View {
        $tenantId = (string) TenantContext::id();

        return view('financial.index', [
            'dashboard' => $dashboard->execute($tenantId),
            'transactions' => $list->execute($tenantId, ['per_page' => 20]),
        ]);
    }

    public function show(string $dealId, GetDealFinancialStatementQuery $statement): View
    {
        $tenantId = (string) TenantContext::id();
        $data = $statement->execute($tenantId, $dealId);

        return view('financial.show', [
            ...$data,
            'paymentMethods' => PaymentMethod::cases(),
        ]);
    }

    public function storeBootstrap(string $dealId, CreateDealFinancialBootstrapAction $action): RedirectResponse
    {
        $tenantId = (string) TenantContext::id();

        try {
            $action->execute($tenantId, $dealId, request()->user(), true, null, true);
        } catch (FinancialException $e) {
            return back()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('financial.show', $dealId)
            ->with('success', 'Financeiro da oportunidade iniciado.');
    }

    public function storePayment(string $dealId, Request $request, RecordPaymentAction $action): RedirectResponse
    {
        $tenantId = (string) TenantContext::id();
        $data = $request->validate([
            'amount' => ['required', 'numeric', 'min:0.01'],
            'method' => ['required', 'string'],
            'schedule_id' => ['nullable', 'uuid'],
            'transaction_id' => ['nullable', 'uuid'],
            'reference' => ['nullable', 'string', 'max:255'],
        ]);
        $data['deal_id'] = $dealId;

        try {
            $action->execute($tenantId, $request->user(), $data);
        } catch (FinancialException $e) {
            return back()->with('error', $e->getMessage());
        }

        return back()->with('success', 'Pagamento registrado.');
    }

    public function storeTransfer(string $dealId, Request $request, CreateTransferAction $action): RedirectResponse
    {
        $tenantId = (string) TenantContext::id();
        $data = $request->validate([
            'amount' => ['required', 'numeric', 'min:0.01'],
            'payee_type' => ['required', 'string'],
            'payee_label' => ['required', 'string', 'max:255'],
            'payee_user_id' => ['nullable', 'integer'],
            'commission_split_id' => ['nullable', 'uuid'],
            'expected_at' => ['nullable', 'date'],
            'notes' => ['nullable', 'string'],
        ]);
        $data['deal_id'] = $dealId;

        try {
            $action->execute($tenantId, $data);
        } catch (FinancialException $e) {
            return back()->with('error', $e->getMessage());
        }

        return back()->with('success', 'Repasse registrado.');
    }

    public function completeTransfer(string $transferId, CompleteTransferAction $action): RedirectResponse
    {
        $tenantId = (string) TenantContext::id();

        try {
            $transfer = $action->execute($tenantId, $transferId);
        } catch (FinancialException $e) {
            return back()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('financial.show', $transfer->deal_id)
            ->with('success', 'Repasse concluído.');
    }

    public function rules(EnsureDefaultCommissionRuleAction $ensure): View
    {
        $tenantId = (string) TenantContext::id();
        $ensure->execute($tenantId);

        return view('financial.rules', [
            'rules' => FinancialCommissionRuleModel::query()
                ->where('tenant_id', $tenantId)
                ->orderByDesc('is_default')
                ->orderBy('name')
                ->get(),
            'bases' => CommissionBasis::cases(),
            'dealTypes' => DealFinanceType::cases(),
        ]);
    }

    public function storeRule(Request $request): RedirectResponse
    {
        $tenantId = (string) TenantContext::id();
        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'basis' => ['required', 'in:percent,fixed'],
            'value' => ['required', 'numeric', 'min:0'],
            'deal_type' => ['required', 'in:sale,rent,listing,any'],
            'is_default' => ['nullable', 'boolean'],
        ]);

        if (! empty($data['is_default'])) {
            FinancialCommissionRuleModel::query()
                ->where('tenant_id', $tenantId)
                ->update(['is_default' => false]);
        }

        FinancialCommissionRuleModel::query()->create([
            'tenant_id' => $tenantId,
            'name' => $data['name'],
            'basis' => $data['basis'],
            'value' => $data['value'],
            'deal_type' => $data['deal_type'],
            'is_default' => (bool) ($data['is_default'] ?? false),
            'is_active' => true,
        ]);

        return back()->with('success', 'Regra de comissão salva.');
    }
}
