<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\App;
use App\Core\Response;
use App\Modules\Accounting\Models\InstrumentPortfolio;
use App\Modules\Accounting\Models\NegotiableInstrument;

class InstrumentPortfolioController extends Controller
{
    public function index(Request $request): Response
    {
        $this->authorize('accounting.instruments.view');

        $type = $request->get('type', '');
        $qb = InstrumentPortfolio::query();

        if ($type) {
            $qb->where('portfolio_type', '=', $type);
        }

        $portfolios = $qb->orderBy('portfolio_date', 'DESC')->get();

        return $this->view('Accounting/Views/portfolios/index', [
            'portfolios' => $portfolios,
            'type'       => $type,
        ]);
    }

    public function create(Request $request): Response
    {
        $this->authorize('accounting.instruments.manage');

        $db = App::getInstance()->db();
        $bankAccounts = $db->select("SELECT id, account_name_ar FROM bank_accounts WHERE is_active = 1 ORDER BY account_name_ar");
        $availableInstruments = NegotiableInstrument::query()
            ->where('status', '=', 'in_hand')
            ->where('direction', '=', 'receivable')
            ->orderBy('due_date', 'ASC')
            ->get();

        return $this->view('Accounting/Views/portfolios/create', [
            'bankAccounts'         => $bankAccounts,
            'availableInstruments' => $availableInstruments,
        ]);
    }

    public function store(Request $request): Response
    {
        $this->authorize('accounting.instruments.manage');

        $data = $this->validate($request->all(), [
            'portfolio_type' => 'required',
            'portfolio_date' => 'required',
        ]);

        $session = App::getInstance()->session();
        $portfolioNumber = InstrumentPortfolio::generateNumber($data['portfolio_type']);

        $portfolio = InstrumentPortfolio::create([
            'portfolio_number' => $portfolioNumber,
            'portfolio_type'   => $data['portfolio_type'],
            'portfolio_date'   => $data['portfolio_date'],
            'bank_account_id'  => $request->post('bank_account_id') ? (int)$request->post('bank_account_id') : null,
            'description'      => $request->post('description'),
            'status'           => 'draft',
            'total_amount'     => 0,
            'instrument_count' => 0,
            'created_by'       => (int)($session->get('employee_id') ?? 0) ?: null,
        ]);

        $instrumentIds = $request->post('instrument_ids', []);
        if (is_array($instrumentIds)) {
            foreach ($instrumentIds as $instId) {
                $portfolio->addItem((int)$instId);
            }
        }

        return $this->redirect('/accounting/portfolios')
            ->withSuccess('تم إنشاء الحافظة: ' . $portfolioNumber);
    }

    public function show(Request $request, string $id): Response
    {
        $this->authorize('accounting.instruments.view');

        $portfolio = InstrumentPortfolio::findOrFail((int)$id);
        $items = $portfolio->getItems();

        return $this->view('Accounting/Views/portfolios/show', [
            'portfolio' => $portfolio->toArray(),
            'items'     => $items,
        ]);
    }

    public function confirm(Request $request, string $id): Response
    {
        $this->authorize('accounting.instruments.manage');

        $portfolio = InstrumentPortfolio::findOrFail((int)$id);

        if ($portfolio->status !== 'draft') {
            return $this->redirect('/accounting/portfolios/' . $id)
                ->withError('الحافظة مؤكدة بالفعل');
        }

        $items = $portfolio->getItems();
        $newStatus = $this->mapPortfolioTypeToInstrumentStatus($portfolio->portfolio_type);

        foreach ($items as $item) {
            $instrument = NegotiableInstrument::find((int)$item['id']);
            if ($instrument && $newStatus) {
                $extra = [];
                if ($portfolio->bank_account_id) {
                    $extra['bank_account_id'] = (int)$portfolio->bank_account_id;
                }
                $instrument->transitionTo($newStatus, $extra ?: null);
            }
        }

        $portfolio->update(['status' => 'confirmed']);

        return $this->redirect('/accounting/portfolios/' . $id)
            ->withSuccess('تم تأكيد الحافظة وتحديث حالة الأوراق');
    }

    private function mapPortfolioTypeToInstrumentStatus(string $portfolioType): ?string
    {
        $map = [
            'deposit'     => 'under_collection',
            'collection'  => 'under_collection',
            'payment'     => 'paid',
            'endorsement' => 'endorsed',
            'return'      => 'returned',
            'bounce'      => 'bounced',
        ];
        return $map[$portfolioType] ?? null;
    }
}
