<?php

namespace App\Controllers\Api;

use App\Libraries\AuditLogger;
use App\Libraries\ResponseHelper;
use App\Libraries\UuidHelper;
use App\Models\DonationContributionModel;
use App\Models\DonationRequestModel;

class DonationController extends BaseApiController
{
    private DonationRequestModel $model;

    public function initController(
        \CodeIgniter\HTTP\RequestInterface $request,
        \CodeIgniter\HTTP\ResponseInterface $response,
        \Psr\Log\LoggerInterface $logger
    ): void {
        parent::initController($request, $response, $logger);
        $this->model = $this->scopedModel(new DonationRequestModel());
    }

    public function index()
    {
        if ($err = $this->requirePermission('view_donations')) return $err;

        $result         = $this->model->scopedPaginate($this->getPerPage());
        $result['data'] = array_map([$this, 'formatWithProgress'], $result['data']);

        return ResponseHelper::paginated($result);
    }

    public function create()
    {
        if ($err = $this->requirePermission('manage_donations')) return $err;

        $data = $this->getJson();
        $v    = service('validation');
        $v->setRules([
            'title'  => 'required|min_length[3]',
            'scope'  => 'required|in_list[per_member,per_family,per_age_group,voluntary]',
        ]);

        if (!$v->run($data)) {
            return ResponseHelper::validationError($v->getErrors());
        }

        $user = $this->currentUser();
        $uuid = UuidHelper::generate();
        $this->model->insert([
            'uuid'          => $uuid,
            'church_id'     => $this->churchId(),
            'title'         => $data['title'],
            'description'   => $data['description'] ?? null,
            'scope'         => $data['scope'],
            'target_amount' => $data['target_amount'] ?? null,
            'event_id'      => $data['event_id'] ?? null,
            'due_date'      => $data['due_date'] ?? null,
            'is_active'     => 1,
            'created_by'    => $user['id'] ?? null,
        ]);

        $donation = $this->model->findByUuid($uuid);
        AuditLogger::log('donation.created', 'donation_requests', $uuid, null, $donation);

        return ResponseHelper::created($this->formatWithProgress($donation));
    }

    public function show(string $uuid)
    {
        if ($err = $this->requirePermission('view_donations')) return $err;

        $donation = $this->model->findByUuid($uuid);
        if (!$donation) return ResponseHelper::notFound();

        $contribModel         = new DonationContributionModel();
        $donation['contributions'] = $contribModel->where('donation_request_id', $donation['id'])->findAll();

        return ResponseHelper::success($this->formatWithProgress($donation));
    }

    public function update(string $uuid)
    {
        if ($err = $this->requirePermission('manage_donations')) return $err;

        $donation = $this->model->findByUuid($uuid);
        if (!$donation) return ResponseHelper::notFound();

        $data    = $this->getJson();
        $allowed = ['title', 'description', 'scope', 'target_amount', 'due_date', 'is_active'];
        $update  = array_intersect_key($data, array_flip($allowed));

        $old = $donation;
        $this->model->update($donation['id'], $update);
        $new = $this->model->findByUuid($uuid);

        AuditLogger::log('donation.updated', 'donation_requests', $uuid, $old, $new);

        return ResponseHelper::success($this->formatWithProgress($new));
    }

    public function delete(string $uuid)
    {
        if ($err = $this->requirePermission('manage_donations')) return $err;

        $donation = $this->model->findByUuid($uuid);
        if (!$donation) return ResponseHelper::notFound();

        $this->model->delete($donation['id']);
        AuditLogger::log('donation.deleted', 'donation_requests', $uuid, $donation, null);

        return ResponseHelper::success(null);
    }

    public function contribute(string $uuid)
    {
        if ($err = $this->requirePermission('view_donations')) return $err;

        $donation = $this->model->findByUuid($uuid);
        if (!$donation) return ResponseHelper::notFound();

        $data = $this->getJson();
        $v    = service('validation');
        $v->setRules(['amount' => 'required|decimal']);

        if (!$v->run($data)) {
            return ResponseHelper::validationError($v->getErrors());
        }

        $user = $this->currentUser();
        $contribModel = new DonationContributionModel();
        $contribModel->insert([
            'donation_request_id' => $donation['id'],
            'user_id'             => $user['id'] ?? null,
            'member_id'           => $data['member_id'] ?? null,
            'family_unit_id'      => $data['family_unit_id'] ?? null,
            'amount'              => $data['amount'],
            'note'                => $data['note'] ?? null,
            'church_id'           => $this->churchId(),
        ]);

        AuditLogger::log('donation.contributed', 'donation_contributions', $uuid, null, $data);

        return ResponseHelper::created(['message' => 'Contribution recorded']);
    }

    public function contributions(string $uuid)
    {
        if ($err = $this->requirePermission('manage_donations')) return $err;

        $donation = $this->model->findByUuid($uuid);
        if (!$donation) return ResponseHelper::notFound();

        $contribModel = new DonationContributionModel();
        $rows         = $contribModel->where('donation_request_id', $donation['id'])->findAll();

        return ResponseHelper::success(array_map(fn($r) => [
            'id'             => null,
            'user_id'        => $r['user_id'],
            'member_id'      => $r['member_id'],
            'family_unit_id' => $r['family_unit_id'],
            'amount'         => (float) $r['amount'],
            'note'           => $r['note'],
            'created_at'     => $r['created_at'],
        ], $rows));
    }

    private function formatWithProgress(array $d): array
    {
        $contribModel = new DonationContributionModel();
        $total = (float) ($contribModel->where('donation_request_id', $d['id'])
                                        ->selectSum('amount', 'total')
                                        ->get()->getRowArray()['total'] ?? 0);

        return [
            'uuid'          => $d['uuid'],
            'title'         => $d['title'],
            'description'   => $d['description'],
            'scope'         => $d['scope'],
            'target_amount' => $d['target_amount'] ? (float) $d['target_amount'] : null,
            'total_raised'  => $total,
            'due_date'      => $d['due_date'],
            'is_active'     => (bool) $d['is_active'],
            'created_at'    => $d['created_at'],
            'contributions' => $d['contributions'] ?? [],
        ];
    }
}
