<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Controller;

use OCA\Mitgliederverwaltung\Service\BundleImportService;
use OCA\Mitgliederverwaltung\Service\EntityImportService;
use OCA\Mitgliederverwaltung\Service\ImportService;
use OCA\Mitgliederverwaltung\Service\ValidationException;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

/**
 * REST API controller for CSV/Excel import.
 *
 * Provides three import flows:
 * - Legacy member import (3-step: upload/preview/execute) — Issue #58
 * - Per-entity import with auto-detection — Issue #150
 * - ZIP bundle import with dependency-aware ordering — Issue #151
 *
 * Admin-only access.
 */
class ImportController extends ApiController {

    use ApiControllerTrait;

    private ImportService $importService;
    private EntityImportService $entityImportService;
    private BundleImportService $bundleImportService;
    private LoggerInterface $logger;

    public function __construct(
        string $appName,
        IRequest $request,
        ImportService $importService,
        EntityImportService $entityImportService,
        BundleImportService $bundleImportService,
        LoggerInterface $logger
    ) {
        parent::__construct($appName, $request);
        $this->importService = $importService;
        $this->entityImportService = $entityImportService;
        $this->bundleImportService = $bundleImportService;
        $this->logger = $logger;
    }

    /**
     * Upload a CSV file and return parsed columns + preview rows.
     *
     * POST /api/v1/import/upload
     *
     * Expects JSON body:
     * - content: string (Base64-encoded file content)
     * - delimiter: string (optional, default ",")
     * - encoding: string (optional, default "UTF-8")
     */
    public function upload(): JSONResponse {
        try {
            $data = $this->getRequestData();

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

            // Decode Base64 content
            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $delimiter = $data['delimiter'] ?? ',';
            $encoding = $data['encoding'] ?? 'UTF-8';

            $result = $this->importService->parseFile($decoded, $delimiter, $encoding);

            // Also return target fields for the mapping step
            $result['targetFields'] = $this->importService->getTargetFields();

            return new JSONResponse($result);
        } catch (ValidationException $e) {
            return new JSONResponse(
                ['error' => $e->getMessage()],
                Http::STATUS_BAD_REQUEST
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to parse import file', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Fehler beim Lesen der Datei'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Preview import with column mapping (dry-run).
     *
     * POST /api/v1/import/preview
     *
     * Expects JSON body:
     * - content: string (Base64-encoded file content)
     * - mapping: object { sourceIndex: targetFieldKey }
     * - delimiter: string (optional)
     * - encoding: string (optional)
     * - groupFamilies: boolean (optional)
     */
    public function preview(): JSONResponse {
        try {
            $data = $this->getRequestData();

            $content = $data['content'] ?? null;
            $mapping = $data['mapping'] ?? null;

            if ($content === null || $mapping === null) {
                return new JSONResponse(
                    ['error' => 'content und mapping sind erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $delimiter = $data['delimiter'] ?? ',';
            $encoding = $data['encoding'] ?? 'UTF-8';
            $groupFamilies = $data['groupFamilies'] ?? false;

            $result = $this->importService->preview(
                $decoded,
                $mapping,
                $delimiter,
                $encoding,
                $groupFamilies
            );

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

    /**
     * Execute the import.
     *
     * POST /api/v1/import/execute
     *
     * Same body as preview.
     */
    public function execute(): JSONResponse {
        try {
            $data = $this->getRequestData();

            $content = $data['content'] ?? null;
            $mapping = $data['mapping'] ?? null;

            if ($content === null || $mapping === null) {
                return new JSONResponse(
                    ['error' => 'content und mapping sind erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $delimiter = $data['delimiter'] ?? ',';
            $encoding = $data['encoding'] ?? 'UTF-8';
            $groupFamilies = $data['groupFamilies'] ?? false;

            $result = $this->importService->execute(
                $decoded,
                $mapping,
                $delimiter,
                $encoding,
                $groupFamilies
            );

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

    // ── Per-entity import (Issue #150) ────────────────────────────

    /**
     * Upload a CSV file for entity import: parse, auto-detect type, return schema.
     *
     * POST /api/v1/import/entity/upload
     * Body: { content, delimiter?, encoding?, entityType? }
     */
    public function entityUpload(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $content = $data['content'] ?? null;
            if ($content === null || $content === '') {
                return new JSONResponse(
                    ['error' => 'Dateiinhalt ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $delimiter = $data['delimiter'] ?? ';';
            $encoding = $data['encoding'] ?? 'UTF-8';

            $parsed = $this->entityImportService->parseFile($decoded, $delimiter, $encoding);

            // Auto-detect entity type
            $detection = $this->entityImportService->detectEntityType($parsed['columns']);

            // Use explicit type if provided, otherwise use detected
            $entityType = $data['entityType'] ?? $detection['type'];

            $result = [
                'columns' => $parsed['columns'],
                'rows' => $parsed['rows'],
                'totalRows' => $parsed['totalRows'],
                'detection' => $detection,
                'entityType' => $entityType,
            ];

            // If we have a type, include schema and auto-mapping
            if ($entityType) {
                $schema = $this->entityImportService->getImportSchema($entityType);
                $result['targetFields'] = $schema['targetFields'];
                $result['mapping'] = $this->entityImportService->autoMapHeaders($entityType, $parsed['columns']);
            }

            return new JSONResponse($result);
        } catch (ValidationException $e) {
            return new JSONResponse(
                ['error' => $e->getMessage()],
                Http::STATUS_BAD_REQUEST
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to parse entity import file', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Fehler beim Lesen der Datei'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Get import schema for an entity type (target fields, headers).
     *
     * GET /api/v1/import/entity/schema/{type}
     */
    public function entitySchema(string $type): JSONResponse {
        try {
            $schema = $this->entityImportService->getImportSchema($type);
            return new JSONResponse($schema);
        } catch (\InvalidArgumentException $e) {
            return new JSONResponse(
                ['error' => $e->getMessage()],
                Http::STATUS_BAD_REQUEST
            );
        }
    }

    /**
     * Preview entity import (dry-run).
     *
     * POST /api/v1/import/entity/preview
     * Body: { content, entityType, mapping, delimiter?, encoding? }
     */
    public function entityPreview(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $content = $data['content'] ?? null;
            $entityType = $data['entityType'] ?? null;
            $mapping = $data['mapping'] ?? null;

            if ($content === null || $entityType === null || $mapping === null) {
                return new JSONResponse(
                    ['error' => 'content, entityType und mapping sind erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $delimiter = $data['delimiter'] ?? ';';
            $encoding = $data['encoding'] ?? 'UTF-8';
            $migrationMode = $data['migrationMode'] ?? false;
            $corrections = $data['corrections'] ?? [];

            $result = $this->entityImportService->preview(
                $entityType,
                $decoded,
                $mapping,
                $delimiter,
                $encoding,
                (bool)$migrationMode,
                $corrections
            );

            return new JSONResponse($result);
        } catch (\Exception $e) {
            $this->logger->error('Failed to preview entity import', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Fehler bei der Vorschau'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Execute entity import.
     *
     * POST /api/v1/import/entity/execute
     * Body: { content, entityType, mapping, delimiter?, encoding? }
     */
    public function entityExecute(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $content = $data['content'] ?? null;
            $entityType = $data['entityType'] ?? null;
            $mapping = $data['mapping'] ?? null;

            if ($content === null || $entityType === null || $mapping === null) {
                return new JSONResponse(
                    ['error' => 'content, entityType und mapping sind erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $delimiter = $data['delimiter'] ?? ';';
            $encoding = $data['encoding'] ?? 'UTF-8';
            $migrationMode = $data['migrationMode'] ?? false;
            $corrections = $data['corrections'] ?? [];

            $result = $this->entityImportService->execute(
                $entityType,
                $decoded,
                $mapping,
                $delimiter,
                $encoding,
                (bool)$migrationMode,
                $corrections
            );

            return new JSONResponse($result);
        } catch (\Exception $e) {
            $this->logger->error('Failed to execute entity import', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Import fehlgeschlagen'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // ── Conflict resolution (Issue #152) ─────────────────────────

    /**
     * Apply per-field merge resolutions for duplicate records.
     *
     * POST /api/v1/import/entity/merge
     * Body: { entityType, resolutions: [{existingId, mergedFields: {field: value}}] }
     */
    public function entityMerge(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $entityType = $data['entityType'] ?? null;
            $resolutions = $data['resolutions'] ?? null;

            if ($entityType === null || $resolutions === null) {
                return new JSONResponse(
                    ['error' => 'entityType und resolutions sind erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $result = $this->entityImportService->mergeConflicts($entityType, $resolutions);
            return new JSONResponse($result);
        } catch (\Exception $e) {
            $this->logger->error('Failed to merge conflicts', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Konfliktzusammenfuehrung fehlgeschlagen'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // ── ZIP bundle import (Issue #151) ────────────────────────────

    /**
     * Upload and analyze a ZIP bundle.
     *
     * POST /api/v1/import/bundle/upload
     * Body: { content (base64) }
     */
    public function bundleUpload(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $content = $data['content'] ?? null;
            if ($content === null || $content === '') {
                return new JSONResponse(
                    ['error' => 'Dateiinhalt ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $analysis = $this->bundleImportService->analyzeBundle($decoded);
            return new JSONResponse($analysis);
        } catch (ValidationException $e) {
            return new JSONResponse(
                ['error' => $e->getMessage()],
                Http::STATUS_BAD_REQUEST
            );
        } catch (\Exception $e) {
            $this->logger->error('Failed to analyze bundle', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Bundle-Analyse fehlgeschlagen'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Preview bundle import (dry-run for all entities).
     *
     * POST /api/v1/import/bundle/preview
     * Body: { content (base64) }
     */
    public function bundlePreview(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $content = $data['content'] ?? null;
            if ($content === null) {
                return new JSONResponse(
                    ['error' => 'content ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $corrections = $data['corrections'] ?? [];

            $result = $this->bundleImportService->previewBundle($decoded, $corrections);
            return new JSONResponse($result);
        } catch (\Exception $e) {
            $this->logger->error('Failed to preview bundle', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Bundle-Vorschau fehlgeschlagen'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    /**
     * Execute bundle import.
     *
     * POST /api/v1/import/bundle/execute
     * Body: { content (base64), overrides?: {filename: type} }
     */
    public function bundleExecute(): JSONResponse {
        try {
            $data = $this->getRequestData();
            $content = $data['content'] ?? null;
            if ($content === null) {
                return new JSONResponse(
                    ['error' => 'content ist erforderlich'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $decoded = base64_decode($content, true);
            if ($decoded === false) {
                return new JSONResponse(
                    ['error' => 'Ungueltige Base64-Kodierung'],
                    Http::STATUS_BAD_REQUEST
                );
            }

            $overrides = $data['overrides'] ?? [];
            $corrections = $data['corrections'] ?? [];

            $result = $this->bundleImportService->executeBundle($decoded, $overrides, $corrections);
            return new JSONResponse($result);
        } catch (\Exception $e) {
            $this->logger->error('Failed to execute bundle import', [
                'exception' => $e,
                'app' => 'mitgliederverwaltung',
            ]);
            return new JSONResponse(
                ['error' => 'Bundle-Import fehlgeschlagen'],
                Http::STATUS_INTERNAL_SERVER_ERROR
            );
        }
    }

    // getRequestData() provided by ApiControllerTrait
}
