<?php

namespace App\Services;

use App\Models\Cattle;
use App\Models\CattleSaleIncome;
use App\Models\MaterialExpense;
use Carbon\Carbon;

class RanchPeriodReportService
{
    /**
     * @return array{
     *   from: string,
     *   to: string,
     *   total_expenses: float,
     *   total_income: float,
     *   net_profit: float,
     *   expenses_by_category: array<string, float>,
     *   sales_count: int,
     *   mortality_count: int
     * }
     */
    public function generate(Carbon $from, Carbon $to): array
    {
        $expenses = MaterialExpense::query()
            ->whereBetween('expense_date', [$from->toDateString(), $to->toDateString()])
            ->with('materialType')
            ->get();

        $totalExpenses = (float) $expenses->sum('total_cost');

        $expensesByCategory = [];
        foreach ($expenses as $expense) {
            $cat = $expense->materialType?->category ?? 'other';
            $expensesByCategory[$cat] = ($expensesByCategory[$cat] ?? 0) + (float) $expense->total_cost;
        }

        $incomes = CattleSaleIncome::query()
            ->whereBetween('sale_date', [$from->toDateString(), $to->toDateString()])
            ->get();

        $totalIncome = (float) $incomes->sum('total_price');

        $mortalityCount = Cattle::query()
            ->where('status', Cattle::STATUS_DEAD)
            ->whereBetween('deactivated_at', [$from->toDateString(), $to->toDateString()])
            ->count();

        $deactivationsInPeriod = Cattle::query()
            ->whereIn('status', [Cattle::STATUS_SOLD, Cattle::STATUS_DEAD, Cattle::STATUS_CONSUMED])
            ->whereBetween('deactivated_at', [$from->toDateString(), $to->toDateString()])
            ->count();

        $mortalityRatePct = $deactivationsInPeriod > 0
            ? round(($mortalityCount / $deactivationsInPeriod) * 100, 1)
            : null;

        $categoryLabels = config('ranch.material_categories', []);

        $expensesByCategoryLabeled = [];
        foreach ($expensesByCategory as $key => $amount) {
            $expensesByCategoryLabeled[$key] = [
                'key' => $key,
                'label' => $categoryLabels[$key] ?? $key,
                'amount' => round($amount, 2),
            ];
        }

        return [
            'from' => $from->toDateString(),
            'to' => $to->toDateString(),
            'total_expenses' => round($totalExpenses, 2),
            'total_income' => round($totalIncome, 2),
            'net_profit' => round($totalIncome - $totalExpenses, 2),
            'expenses_by_category' => array_map(fn ($v) => round($v, 2), $expensesByCategory),
            'expenses_by_category_detail' => array_values($expensesByCategoryLabeled),
            'sales_count' => $incomes->count(),
            'mortality_count' => $mortalityCount,
            'deactivations_count' => $deactivationsInPeriod,
            'mortality_rate_pct' => $mortalityRatePct,
            'sales' => $incomes->map(fn ($row) => [
                'sale_date' => $row->sale_date?->toDateString(),
                'cattle_id' => $row->cattle_id,
                'exit_weight_kg' => (float) $row->exit_weight_kg,
                'total_price' => (float) $row->total_price,
            ])->values()->all(),
            'expenses' => $expenses->map(fn ($row) => [
                'expense_date' => $row->expense_date?->toDateString(),
                'material' => $row->materialType?->name,
                'category' => $categoryLabels[$row->materialType?->category ?? ''] ?? $row->materialType?->category,
                'total_cost' => (float) $row->total_cost,
            ])->values()->all(),
        ];
    }

    public function toCsv(array $report): string
    {
        $lines = [
            'Balance por periodo',
            'Desde,'.$report['from'],
            'Hasta,'.$report['to'],
            '',
            'Concepto,Monto',
            'Total gastos,'.$report['total_expenses'],
            'Total ingresos,'.$report['total_income'],
            'Utilidad neta,'.$report['net_profit'],
            'Ventas registradas,'.$report['sales_count'],
            'Bajas en periodo,'.($report['deactivations_count'] ?? 0),
            'Mortalidad,'.$report['mortality_count'],
            'Tasa mortalidad %,'.($report['mortality_rate_pct'] ?? ''),
            '',
            'Gastos por categoria',
            'Categoria,Monto',
        ];

        foreach ($report['expenses_by_category_detail'] ?? [] as $row) {
            $lines[] = ($row['label'] ?? $row['key']).','.$row['amount'];
        }

        $lines[] = '';
        $lines[] = 'Detalle de ventas';
        $lines[] = 'Fecha,ID animal,Peso salida kg,Total';
        foreach ($report['sales'] ?? [] as $sale) {
            $lines[] = implode(',', [
                $sale['sale_date'],
                $sale['cattle_id'],
                $sale['exit_weight_kg'],
                $sale['total_price'],
            ]);
        }

        $lines[] = '';
        $lines[] = 'Detalle de gastos';
        $lines[] = 'Fecha,Material,Categoria,Total';
        foreach ($report['expenses'] ?? [] as $expense) {
            $lines[] = implode(',', [
                $expense['expense_date'],
                '"'.str_replace('"', '""', (string) $expense['material']).'"',
                '"'.str_replace('"', '""', (string) $expense['category']).'"',
                $expense['total_cost'],
            ]);
        }

        return implode("\n", $lines);
    }
}
