<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Service;

use OCA\Mitgliederverwaltung\Db\GeneralMaterialMapper;
use OCA\Mitgliederverwaltung\Db\InventoryCategoryMapper;
use OCA\Mitgliederverwaltung\Db\InventoryItemCategoryMapper;
use OCA\Mitgliederverwaltung\Db\StockItemMapper;
use OCA\Mitgliederverwaltung\Db\StockVariantMapper;
use OCA\Mitgliederverwaltung\Db\SaleRecordMapper;
use Psr\Log\LoggerInterface;

/**
 * Service for generating inventory reports.
 *
 * Part of Issue #165 (Inventory Tracking).
 */
class InventoryReportService {

    private GeneralMaterialMapper $generalMaterialMapper;
    private InventoryCategoryMapper $categoryMapper;
    private InventoryItemCategoryMapper $itemCategoryMapper;
    private StockItemMapper $stockItemMapper;
    private StockVariantMapper $stockVariantMapper;
    private SaleRecordMapper $saleRecordMapper;
    private LoggerInterface $logger;

    public function __construct(
        GeneralMaterialMapper $generalMaterialMapper,
        InventoryCategoryMapper $categoryMapper,
        InventoryItemCategoryMapper $itemCategoryMapper,
        StockItemMapper $stockItemMapper,
        StockVariantMapper $stockVariantMapper,
        SaleRecordMapper $saleRecordMapper,
        LoggerInterface $logger
    ) {
        $this->generalMaterialMapper = $generalMaterialMapper;
        $this->categoryMapper = $categoryMapper;
        $this->itemCategoryMapper = $itemCategoryMapper;
        $this->stockItemMapper = $stockItemMapper;
        $this->stockVariantMapper = $stockVariantMapper;
        $this->saleRecordMapper = $saleRecordMapper;
        $this->logger = $logger;
    }

    /**
     * Generate condition report data.
     *
     * @return array{summary: array, rows: array, headers: string[]}
     */
    public function generateConditionReport(): array {
        $items = $this->generalMaterialMapper->findAll();

        // Build summary by category
        $summary = [];
        foreach ($items as $item) {
            $catIds = $this->itemCategoryMapper->findByItemId($item->getId());
            if (count($catIds) === 0) {
                $catName = '(keine Kategorie)';
            } else {
                $catNames = [];
                foreach ($catIds as $cat) {
                    try {
                        $c = $this->categoryMapper->findById((int)$cat->getCategoryId());
                        $catNames[] = $c->getName();
                    } catch (\Exception $e) {
                        // ignore
                    }
                }
                $catName = implode(', ', $catNames);
            }
            if (!isset($summary[$catName])) {
                $summary[$catName] = 0;
            }
            $summary[$catName] += 1;
        }

        // Build detail rows for items needing repair (condition ≤ 2 or NULL)
        $rows = [];
        $needingRepair = $this->generalMaterialMapper->findNeedingRepair();
        foreach ($needingRepair as $item) {
            $catIds = $this->itemCategoryMapper->findByItemId($item->getId());
            $catNames = [];
            foreach ($catIds as $cat) {
                try {
                    $c = $this->categoryMapper->findById((int)$cat->getCategoryId());
                    $catNames[] = $c->getName();
                } catch (\Exception $e) {
                    // ignore
                }
            }

            $conditionLabel = $item->getCondition() === null
                ? 'Nicht bewertet'
                : $item->getCondition() . '/5';

            $rows[] = [
                'name' => $item->getName(),
                'condition' => $conditionLabel,
                'categories' => implode(', ', $catNames) ?: '–',
                'notes' => $item->getNotes() ?? '–',
            ];
        }

        return [
            'summary' => $summary,
            'rows' => $rows,
            'headers' => ['Artikel', 'Zustand', 'Kategorie', 'Notizen'],
        ];
    }

    /**
     * Generate sales report data.
     *
     * @param string|null $dateFrom Start date (YYYY-MM-DD)
     * @param string|null $dateTo   End date (YYYY-MM-DD)
     * @return array{title: string, summary: array, rows: array, headers: string[]}
     */
    public function generateSalesReport(?string $dateFrom = null, ?string $dateTo = null): array {
        $sales = $this->saleRecordMapper->findByDateRange($dateFrom, $dateTo);
        $rows = [];
        $totalRevenue = 0.0;

        foreach ($sales as $sale) {
            $itemName = 'Unbekannt';
            try {
                $stockItem = $this->stockItemMapper->findById((int)$sale->getStockItemId());
                $itemName = $stockItem->getName();
            } catch (\Exception $e) {
                // ignore, keep default name
            }

            $variantName = '';
            if ($sale->getVariantId() !== null) {
                try {
                    $variant = $this->stockVariantMapper->findById((int)$sale->getVariantId());
                    $variantName = ' – ' . $variant->getLabel();
                } catch (\Exception $e) {
                    // ignore
                }
            }

            $totalRevenue += (float)$sale->getTotalPrice();

            $rows[] = [
                'date' => $sale->getDate(),
                'item' => $itemName . $variantName,
                'quantity' => (string)$sale->getQuantity(),
                'unit_price' => number_format((float)$sale->getUnitPrice(), 2, ',', '.') . ' €',
                'total_price' => number_format((float)$sale->getTotalPrice(), 2, ',', '.') . ' €',
            ];
        }

        $title = 'Inventur-Verkäufe';
        if ($dateFrom !== null || $dateTo !== null) {
            $title .= ' (' . ($dateFrom ?? 'Anfang') . ' – ' . ($dateTo ?? 'Ende') . ')';
        }

        return [
            'title' => $title,
            'summary' => [
                'total_sales' => count($sales),
                'total_revenue' => number_format($totalRevenue, 2, ',', '.') . ' €',
            ],
            'rows' => $rows,
            'headers' => ['Datum', 'Artikel', 'Menge', 'Stückpreis', 'Gesamtsumme'],
        ];
    }
}
