<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Controller;

use OCA\Mitgliederverwaltung\Service\LagerService;
use OCA\Mitgliederverwaltung\Service\ValidationException;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Db\DoesNotExistException;
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 Lager (camp) management.
 *
 * Part of Issue #55.
 */
class LagerController extends ApiController {

    use ApiControllerTrait;

    private LagerService $lagerService;
    private LoggerInterface $logger;

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

    /**
     * List camps with optional year/Stufe filter.
     *
     * GET /api/v1/lager?year=2026&stufeId=1
     */
    #[NoCSRFRequired]
    public function index(): JSONResponse {
        try {
            $year = $this->request->getParam('year');
            $stufeId = $this->request->getParam('stufeId');

            $camps = $this->lagerService->findAll(
                $year !== null ? (int)$year : null,
                $stufeId !== null ? (int)$stufeId : null
            );

            return new JSONResponse(['data' => $camps]);
        } catch (\Exception $e) {
            $this->logger->error('Failed to list camps', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Get camp detail with participants, Stufen, and files.
     *
     * GET /api/v1/lager/{id}
     */
    #[NoCSRFRequired]
    public function show(int $id): JSONResponse {
        try {
            $camp = $this->lagerService->find($id);
            return new JSONResponse($camp);
        } catch (DoesNotExistException $e) {
            return new JSONResponse(
                ['error' => 'Lager nicht gefunden'],
                Http::STATUS_NOT_FOUND
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to get camp', [
                'lagerId' => $id,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Create a new camp.
     *
     * POST /api/v1/lager
     */
    public function create(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $stufeIds = $data['stufeIds'] ?? [];
            unset($data['stufeIds']);

            $camp = $this->lagerService->create($data, $stufeIds);

            return new JSONResponse($camp, Http::STATUS_CREATED);
        } catch (ValidationException $e) {
            return new JSONResponse(
                ['error' => $e->getMessage()],
                Http::STATUS_BAD_REQUEST
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to create camp', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Update an existing camp.
     *
     * PUT /api/v1/lager/{id}
     */
    public function update(int $id): JSONResponse {
        try {
            $data = $this->getRequestData();
            $stufeIds = array_key_exists('stufeIds', $data) ? $data['stufeIds'] : null;
            unset($data['stufeIds']);

            $camp = $this->lagerService->update($id, $data, $stufeIds);

            return new JSONResponse($camp);
        } catch (DoesNotExistException $e) {
            return new JSONResponse(
                ['error' => 'Lager nicht gefunden'],
                Http::STATUS_NOT_FOUND
            );
        } catch (ValidationException $e) {
            return new JSONResponse(
                ['error' => $e->getMessage()],
                Http::STATUS_BAD_REQUEST
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to update camp', [
                'lagerId' => $id,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Delete a camp.
     *
     * DELETE /api/v1/lager/{id}
     */
    public function destroy(int $id): JSONResponse {
        try {
            $this->lagerService->delete($id);
            return new JSONResponse(['status' => 'deleted']);
        } catch (DoesNotExistException $e) {
            return new JSONResponse(
                ['error' => 'Lager nicht gefunden'],
                Http::STATUS_NOT_FOUND
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to delete camp', [
                'lagerId' => $id,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // ── Participants ─────────────────────────────────────────────────

    /**
     * Add a participant to a camp.
     *
     * POST /api/v1/lager/{id}/teilnehmer
     */
    public function addTeilnehmer(int $id): JSONResponse {
        try {
            $data = $this->getRequestData();
            $memberId = $data['memberId'] ?? null;
            $rolle = $data['rolle'] ?? 'Teilnehmer';

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

            $this->lagerService->addTeilnehmer($id, (int)$memberId, $rolle);

            return new JSONResponse(['status' => 'added'], Http::STATUS_CREATED);
        } catch (\Exception $e) {
            $this->logger->error('Failed to add participant', [
                'lagerId' => $id,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Remove a participant from a camp.
     *
     * DELETE /api/v1/lager/{id}/teilnehmer/{memberId}
     */
    public function removeTeilnehmer(int $id, int $memberId): JSONResponse {
        try {
            $this->lagerService->removeTeilnehmer($id, $memberId);
            return new JSONResponse(['status' => 'removed']);
        } catch (\Exception $e) {
            $this->logger->error('Failed to remove participant', [
                'lagerId' => $id,
                'memberId' => $memberId,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // ── Files ────────────────────────────────────────────────────────

    /**
     * Link a file to a camp.
     *
     * POST /api/v1/lager/{id}/files
     */
    public function addFile(int $id): JSONResponse {
        try {
            $data = $this->getRequestData();
            $filePath = $data['filePath'] ?? null;
            $label = $data['label'] ?? null;

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

            $fileId = $this->lagerService->addFile($id, $filePath, $label);

            return new JSONResponse(['id' => $fileId], Http::STATUS_CREATED);
        } catch (\Exception $e) {
            $this->logger->error('Failed to add file link', [
                'lagerId' => $id,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Remove a file link from a camp.
     *
     * DELETE /api/v1/lager/{id}/files/{fileId}
     */
    public function removeFile(int $id, int $fileId): JSONResponse {
        try {
            $this->lagerService->removeFile($fileId);
            return new JSONResponse(['status' => 'removed']);
        } catch (\Exception $e) {
            $this->logger->error('Failed to remove file link', [
                'lagerId' => $id,
                'fileId' => $fileId,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // ── Member camp history ──────────────────────────────────────────

    /**
     * Get camp history for a member.
     *
     * GET /api/v1/members/{memberId}/lager-history
     */
    #[NoCSRFRequired]
    public function memberHistory(int $memberId): JSONResponse {
        try {
            $history = $this->lagerService->getMemberLagerHistory($memberId);
            return new JSONResponse(['data' => $history]);
        } catch (\Exception $e) {
            $this->logger->error('Failed to get member camp history', [
                'memberId' => $memberId,
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Internal server error'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // getRequestData() provided by ApiControllerTrait
}
