<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\RecurringTemplate;
use App\Models\RecurringInstance;
use App\Models\Transaction;
use App\Services\RecurringService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;

class RecurringTemplateController extends Controller
{
    private RecurringService $recurringService;

    public function __construct(RecurringService $recurringService)
    {
        $this->recurringService = $recurringService;
    }

    /**
     * Lista todos os templates de recorrência do usuário
     */
    public function index(Request $request): JsonResponse
    {
        $query = RecurringTemplate::where('user_id', Auth::id())
            ->with(['account', 'category', 'costCenter'])
            ->withCount(['instances', 'pendingInstances', 'paidInstances']);

        // Filtros
        if ($request->has('is_active')) {
            $query->where('is_active', $request->boolean('is_active'));
        }

        if ($request->has('frequency')) {
            $query->where('frequency', $request->frequency);
        }

        if ($request->has('type')) {
            $query->where('type', $request->type);
        }

        if ($request->has('account_id')) {
            $query->where('account_id', $request->account_id);
        }

        if ($request->has('category_id')) {
            $query->where('category_id', $request->category_id);
        }

        // Ordenação
        $sortBy = $request->get('sort_by', 'name');
        $sortDir = $request->get('sort_dir', 'asc');
        $query->orderBy($sortBy, $sortDir);

        $templates = $query->paginate($request->get('per_page', 20));

        return response()->json($templates);
    }

    /**
     * Exibe um template específico
     */
    public function show(RecurringTemplate $recurringTemplate): JsonResponse
    {
        $this->authorize('view', $recurringTemplate);

        $recurringTemplate->load([
            'account', 
            'category', 
            'costCenter',
            'sourceTransaction',
            'instances' => fn($q) => $q->orderBy('due_date', 'asc'),
        ]);

        return response()->json($recurringTemplate);
    }

    /**
     * Cria um novo template de recorrência manualmente
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string|max:1000',
            'frequency' => 'required|in:' . implode(',', array_keys(RecurringTemplate::FREQUENCIES)),
            'frequency_interval' => 'nullable|integer|min:1|max:12',
            'day_of_month' => 'nullable|integer|min:1|max:31',
            'day_of_week' => 'nullable|integer|min:0|max:6',
            'start_date' => 'required|date',
            'end_date' => 'nullable|date|after:start_date',
            'max_occurrences' => 'nullable|integer|min:1|max:999',
            'account_id' => 'required|exists:accounts,id',
            'category_id' => 'nullable|exists:categories,id',
            'cost_center_id' => 'nullable|exists:cost_centers,id',
            'type' => 'required|in:income,expense',
            'planned_amount' => 'required|numeric|min:0.01',
            'transaction_description' => 'required|string|max:255',
            'notes' => 'nullable|string|max:1000',
        ]);

        $template = $this->recurringService->createTemplate(Auth::id(), $validated);

        return response()->json([
            'message' => __('Recurring template created successfully'),
            'template' => $template,
        ], 201);
    }

    /**
     * Cria um template a partir de uma transação existente
     */
    public function createFromTransaction(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'transaction_id' => 'required|exists:transactions,id',
            'frequency' => 'required|in:' . implode(',', array_keys(RecurringTemplate::FREQUENCIES)),
            'name' => 'nullable|string|max:255',
            'description' => 'nullable|string|max:1000',
            'frequency_interval' => 'nullable|integer|min:1|max:12',
            'day_of_month' => 'nullable|integer|min:1|max:31',
            'day_of_week' => 'nullable|integer|min:0|max:6',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
            'max_occurrences' => 'nullable|integer|min:1|max:999',
        ]);

        $transaction = Transaction::where('user_id', Auth::id())
            ->findOrFail($validated['transaction_id']);

        $options = collect($validated)->except(['transaction_id', 'frequency'])->filter()->toArray();

        $template = $this->recurringService->createFromTransaction(
            $transaction,
            $validated['frequency'],
            $options
        );

        return response()->json([
            'message' => __('Recurring template created from transaction'),
            'template' => $template,
        ], 201);
    }

    /**
     * Atualiza um template
     */
    public function update(Request $request, RecurringTemplate $recurringTemplate): JsonResponse
    {
        $this->authorize('update', $recurringTemplate);

        $validated = $request->validate([
            'name' => 'sometimes|string|max:255',
            'description' => 'nullable|string|max:1000',
            'frequency' => 'sometimes|in:' . implode(',', array_keys(RecurringTemplate::FREQUENCIES)),
            'frequency_interval' => 'nullable|integer|min:1|max:12',
            'day_of_month' => 'nullable|integer|min:1|max:31',
            'day_of_week' => 'nullable|integer|min:0|max:6',
            'end_date' => 'nullable|date',
            'max_occurrences' => 'nullable|integer|min:1|max:999',
            'account_id' => 'sometimes|exists:accounts,id',
            'category_id' => 'nullable|exists:categories,id',
            'cost_center_id' => 'nullable|exists:cost_centers,id',
            'planned_amount' => 'sometimes|numeric|min:0.01',
            'transaction_description' => 'sometimes|string|max:255',
            'notes' => 'nullable|string|max:1000',
            'is_active' => 'sometimes|boolean',
        ]);

        $recurringTemplate->update($validated);

        return response()->json([
            'message' => __('Recurring template updated successfully'),
            'template' => $recurringTemplate->fresh(['account', 'category', 'costCenter']),
        ]);
    }

    /**
     * Remove um template e suas instâncias pendentes
     */
    public function destroy(RecurringTemplate $recurringTemplate): JsonResponse
    {
        $this->authorize('delete', $recurringTemplate);

        // Remover instâncias pendentes (manter as pagas para histórico)
        $recurringTemplate->instances()
            ->where('status', RecurringInstance::STATUS_PENDING)
            ->delete();

        // Desativar o template em vez de deletar (soft delete)
        $recurringTemplate->update(['is_active' => false]);

        return response()->json([
            'message' => __('Recurring template deleted successfully'),
        ]);
    }

    /**
     * Pausa um template
     */
    public function pause(RecurringTemplate $recurringTemplate): JsonResponse
    {
        $this->authorize('update', $recurringTemplate);

        $template = $this->recurringService->pauseTemplate($recurringTemplate);

        return response()->json([
            'message' => __('Recurring template paused'),
            'template' => $template,
        ]);
    }

    /**
     * Reativa um template
     */
    public function resume(RecurringTemplate $recurringTemplate): JsonResponse
    {
        $this->authorize('update', $recurringTemplate);

        $template = $this->recurringService->resumeTemplate($recurringTemplate);

        return response()->json([
            'message' => __('Recurring template resumed'),
            'template' => $template,
        ]);
    }

    /**
     * Lista instâncias de um template
     */
    public function instances(Request $request, RecurringTemplate $recurringTemplate): JsonResponse
    {
        $this->authorize('view', $recurringTemplate);

        $query = $recurringTemplate->instances()
            ->with('transaction');

        // Filtro por status
        if ($request->has('status')) {
            $query->where('status', $request->status);
        }

        // Filtro por período
        if ($request->has('from_date')) {
            $query->where('due_date', '>=', $request->from_date);
        }

        if ($request->has('to_date')) {
            $query->where('due_date', '<=', $request->to_date);
        }

        $instances = $query->orderBy('due_date', 'asc')->get();

        return response()->json($instances);
    }

    /**
     * Lista todas as instâncias pendentes do usuário (dashboard)
     */
    public function allPendingInstances(Request $request): JsonResponse
    {
        $query = RecurringInstance::where('user_id', Auth::id())
            ->where('status', RecurringInstance::STATUS_PENDING)
            ->with(['template', 'template.account', 'template.category']);

        // Filtros
        if ($request->has('type')) {
            $query->whereHas('template', fn($q) => $q->where('type', $request->type));
        }

        if ($request->has('from_date')) {
            $query->where('due_date', '>=', $request->from_date);
        }

        if ($request->has('to_date')) {
            $query->where('due_date', '<=', $request->to_date);
        }

        // Ordenar por data de vencimento
        $instances = $query->orderBy('due_date', 'asc')
            ->limit($request->get('limit', 50))
            ->get();

        return response()->json($instances);
    }

    /**
     * Lista instâncias vencidas
     */
    public function overdueInstances(): JsonResponse
    {
        $instances = RecurringInstance::where('user_id', Auth::id())
            ->overdue()
            ->with(['template', 'template.account', 'template.category'])
            ->orderBy('due_date', 'asc')
            ->get();

        return response()->json($instances);
    }

    /**
     * Lista instâncias próximas do vencimento (próximos 7 dias)
     */
    public function dueSoonInstances(Request $request): JsonResponse
    {
        $days = $request->get('days', 7);

        $instances = RecurringInstance::where('user_id', Auth::id())
            ->dueSoon($days)
            ->with(['template', 'template.account', 'template.category'])
            ->orderBy('due_date', 'asc')
            ->get();

        return response()->json($instances);
    }

    /**
     * Marca uma instância como paga (cria transação)
     */
    public function markAsPaid(Request $request, RecurringInstance $recurringInstance): JsonResponse
    {
        $this->authorize('update', $recurringInstance->template);

        if ($recurringInstance->isPaid()) {
            return response()->json([
                'message' => __('This instance is already paid'),
            ], 422);
        }

        $validated = $request->validate([
            'amount' => 'nullable|numeric|min:0.01',
            'effective_date' => 'nullable|date',
            'description' => 'nullable|string|max:255',
            'notes' => 'nullable|string|max:1000',
        ]);

        $instance = $this->recurringService->markAsPaid($recurringInstance, $validated);

        return response()->json([
            'message' => __('Instance marked as paid'),
            'instance' => $instance,
        ]);
    }

    /**
     * Concilia uma instância com uma transação existente
     */
    public function reconcile(Request $request, RecurringInstance $recurringInstance): JsonResponse
    {
        $this->authorize('update', $recurringInstance->template);

        if ($recurringInstance->isPaid()) {
            return response()->json([
                'message' => __('This instance is already reconciled'),
            ], 422);
        }

        $validated = $request->validate([
            'transaction_id' => 'required|exists:transactions,id',
            'notes' => 'nullable|string|max:1000',
        ]);

        $transaction = Transaction::where('user_id', Auth::id())
            ->findOrFail($validated['transaction_id']);

        $instance = $this->recurringService->reconcileWithTransaction(
            $recurringInstance,
            $transaction,
            $validated['notes'] ?? null
        );

        return response()->json([
            'message' => __('Instance reconciled with transaction'),
            'instance' => $instance,
        ]);
    }

    /**
     * Busca transações candidatas para conciliação
     */
    public function findCandidates(Request $request, RecurringInstance $recurringInstance): JsonResponse
    {
        $this->authorize('view', $recurringInstance->template);

        $daysTolerance = $request->get('days_tolerance', 7);
        
        $candidates = $this->recurringService->findCandidateTransactions(
            $recurringInstance,
            $daysTolerance
        );

        return response()->json($candidates);
    }

    /**
     * Pula uma instância
     */
    public function skip(Request $request, RecurringInstance $recurringInstance): JsonResponse
    {
        $this->authorize('update', $recurringInstance->template);

        $validated = $request->validate([
            'reason' => 'nullable|string|max:255',
        ]);

        $instance = $this->recurringService->skipInstance(
            $recurringInstance,
            $validated['reason'] ?? null
        );

        return response()->json([
            'message' => __('Instance skipped'),
            'instance' => $instance,
        ]);
    }

    /**
     * Atualiza uma instância individual
     */
    public function updateInstance(Request $request, RecurringInstance $recurringInstance): JsonResponse
    {
        $this->authorize('update', $recurringInstance->template);

        if ($recurringInstance->isPaid()) {
            return response()->json([
                'message' => __('Cannot edit a paid instance'),
            ], 422);
        }

        $validated = $request->validate([
            'planned_amount' => 'sometimes|numeric|min:0.01',
            'due_date' => 'sometimes|date',
            'notes' => 'nullable|string|max:1000',
        ]);

        $recurringInstance->update($validated);

        return response()->json([
            'message' => __('Instance updated successfully'),
            'instance' => $recurringInstance->fresh(['template', 'transaction']),
        ]);
    }

    /**
     * Cancela uma instância
     */
    public function cancel(Request $request, RecurringInstance $recurringInstance): JsonResponse
    {
        $this->authorize('update', $recurringInstance->template);

        $validated = $request->validate([
            'reason' => 'nullable|string|max:255',
        ]);

        $instance = $this->recurringService->cancelInstance(
            $recurringInstance,
            $validated['reason'] ?? null
        );

        return response()->json([
            'message' => __('Instance cancelled'),
            'instance' => $instance,
        ]);
    }

    /**
     * Retorna as frequências disponíveis
     */
    public function frequencies(): JsonResponse
    {
        return response()->json(RecurringTemplate::FREQUENCIES);
    }

    /**
     * Regenera instâncias para todos os templates ativos do usuário
     */
    public function regenerateAll(): JsonResponse
    {
        $generated = $this->recurringService->regenerateAllForUser(Auth::id());

        return response()->json([
            'message' => __(':count instances generated', ['count' => $generated]),
            'generated' => $generated,
        ]);
    }
}
