<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Controller;

use OCA\Mitgliederverwaltung\Service\FeeCalculationService;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

/**
 * REST API controller for fee management.
 *
 * Part of Issue #42.
 */
class FeeController extends ApiController {

    use ApiControllerTrait;

    private FeeCalculationService $feeService;
    private LoggerInterface $logger;

    public function __construct(
        string $appName,
        IRequest $request,
        FeeCalculationService $feeService,
        LoggerInterface $logger
    ) {
        parent::__construct($appName, $request);
        $this->feeService = $feeService;
        $this->logger = $logger;
    }

    #[NoCSRFRequired]
    public function listRules(): JSONResponse {
        return $this->handleAction(function () {
            $rules = $this->feeService->getAllRules();
            return new JSONResponse(array_map(fn($r) => $r->jsonSerialize(), $rules));
        }, 'Beitragsregeln auflisten');
    }

    public function createRule(): JSONResponse {
        return $this->handleAction(function () {
            $rule = $this->feeService->createRule($this->getRequestData());
            return new JSONResponse($rule, Http::STATUS_CREATED);
        }, 'Beitragsregel erstellen');
    }

    public function updateRule(int $ruleId): JSONResponse {
        return $this->handleAction(function () use ($ruleId) {
            $rule = $this->feeService->updateRule($ruleId, $this->getRequestData());
            return new JSONResponse($rule);
        }, 'Beitragsregel');
    }

    #[NoCSRFRequired]
    public function listRecords(): JSONResponse {
        return $this->handleAction(function () {
            $year = $this->request->getParam('year');
            if ($year === null) {
                return new JSONResponse(
                    ['error' => 'Parameter year ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $records = $this->feeService->getFeeRecordsForYear((int)$year);
            return new JSONResponse(array_map(fn($r) => $r->jsonSerialize(), $records));
        }, 'Beitragseintraege');
    }

    #[NoCSRFRequired]
    public function memberRecords(int $memberId): JSONResponse {
        return $this->handleAction(function () use ($memberId) {
            $records = $this->feeService->getMemberFeeHistory($memberId);
            return new JSONResponse(array_map(fn($r) => $r->jsonSerialize(), $records));
        }, 'Mitglied-Beitragshistorie');
    }

    public function batchCalculate(): JSONResponse {
        return $this->handleAction(function () {
            $data = $this->getRequestData();
            $year = $data['year'] ?? null;

            if ($year === null) {
                return new JSONResponse(
                    ['error' => 'Parameter year ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            return new JSONResponse($this->feeService->batchCalculate((int)$year));
        }, 'Beitragsberechnung');
    }

    public function markPaid(int $recordId): JSONResponse {
        return $this->handleAction(function () use ($recordId) {
            $data = $this->getRequestData();
            $paymentDate = $data['paymentDate'] ?? (new \DateTime())->format('Y-m-d');

            return new JSONResponse($this->feeService->markAsPaid($recordId, $paymentDate));
        }, 'Beitragsposition');
    }

    public function manualOverride(int $recordId): JSONResponse {
        return $this->handleAction(function () use ($recordId) {
            $data = $this->getRequestData();

            if (!isset($data['amount'])) {
                return new JSONResponse(
                    ['error' => 'Parameter amount ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            return new JSONResponse($this->feeService->manualOverride(
                $recordId,
                (string)$data['amount'],
                $data['notes'] ?? null
            ));
        }, 'Beitragsposition');
    }
}
