<?php

namespace Modules\SystemCore\App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\SystemCore\App\Models\PostingLog;

class SyncController extends Controller
{
    /**
     * Display the posting history page
     */
    public function index()
    {
        $statistics = PostingLog::getStatistics();

        // Get unique modules for filter dropdown
        $modules = PostingLog::select('source_module')
            ->groupBy('source_module')
            ->pluck('source_module')
            ->merge(
                PostingLog::select('target_module')
                    ->groupBy('target_module')
                    ->pluck('target_module')
            )
            ->unique()
            ->values();

        return view('systemcore::sync.index', compact('statistics', 'modules'));
    }

    /**
     * DataTable endpoint for posting logs
     */
    public function postings(Request $request)
    {
        $query = PostingLog::query()
            ->with('postedBy')
            ->select('posting_logs.*');

        // Filter by module
        if ($request->filled('module')) {
            $query->forModule($request->module);
        }

        // Filter by status
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        // Filter by date range
        if ($request->filled('start_date') && $request->filled('end_date')) {
            $query->forDateRange($request->start_date, $request->end_date.' 23:59:59');
        }

        return datatables($query)
            ->addColumn('posted_at_formatted', fn ($log) => $log->formatted_posted_at)
            ->addColumn('source', fn ($log) => $log->source_reference)
            ->addColumn('target', fn ($log) => $log->target_reference)
            ->addColumn('action_badge', fn ($log) => $log->action_badge)
            ->addColumn('status_badge', fn ($log) => $log->status_badge)
            ->addColumn('amount_formatted', fn ($log) => $log->formatted_amount ?? '-')
            ->addColumn('posted_by_name', fn ($log) => $log->postedBy?->full_name ?? __('System'))
            ->addColumn('actions', function ($log) {
                $actions = [
                    [
                        'label' => __('View Details'),
                        'icon' => 'bx bx-show',
                        'onclick' => "viewDetails({$log->id})",
                    ],
                ];

                if ($log->canRetry()) {
                    $actions[] = [
                        'label' => __('Retry'),
                        'icon' => 'bx bx-refresh',
                        'onclick' => "retryPosting({$log->id})",
                        'class' => 'text-warning',
                    ];
                }

                return view('components.datatable-actions', [
                    'id' => $log->id,
                    'actions' => $actions,
                ])->render();
            })
            ->rawColumns(['action_badge', 'status_badge', 'actions'])
            ->make(true);
    }

    /**
     * Get posting log details
     */
    public function viewDetails(PostingLog $postingLog): JsonResponse
    {
        return response()->json([
            'success' => true,
            'data' => [
                'id' => $postingLog->id,
                'source_module' => $postingLog->source_module,
                'source_entity_type' => $postingLog->source_entity_type,
                'source_entity_id' => $postingLog->source_entity_id,
                'target_module' => $postingLog->target_module,
                'target_entity_type' => $postingLog->target_entity_type,
                'target_entity_id' => $postingLog->target_entity_id,
                'action' => $postingLog->action,
                'status' => $postingLog->status,
                'description' => $postingLog->description,
                'amount' => $postingLog->amount,
                'amount_formatted' => $postingLog->formatted_amount,
                'old_values' => $postingLog->old_values,
                'new_values' => $postingLog->new_values,
                'error_message' => $postingLog->error_message,
                'retry_count' => $postingLog->retry_count,
                'can_retry' => $postingLog->canRetry(),
                'posted_by' => $postingLog->postedBy?->full_name ?? __('System'),
                'posted_at' => $postingLog->formatted_posted_at,
                'created_at' => $postingLog->created_at->format('M d, Y H:i:s'),
            ],
        ]);
    }

    /**
     * Retry a failed posting
     */
    public function retryPosting(PostingLog $postingLog): JsonResponse
    {
        if (! $postingLog->canRetry()) {
            return response()->json([
                'success' => false,
                'message' => __('This posting cannot be retried. Maximum retry attempts reached or posting was successful.'),
            ], 422);
        }

        try {
            // Increment retry count
            $postingLog->incrementRetry();

            // Attempt to re-run the sync based on source/target modules
            $result = $this->executeRetry($postingLog);

            if ($result['success']) {
                $postingLog->update([
                    'status' => 'success',
                    'target_entity_id' => $result['target_id'] ?? $postingLog->target_entity_id,
                    'error_message' => null,
                ]);

                return response()->json([
                    'success' => true,
                    'message' => __('Posting retried successfully.'),
                ]);
            } else {
                $postingLog->update([
                    'error_message' => $result['error'] ?? __('Unknown error during retry'),
                ]);

                return response()->json([
                    'success' => false,
                    'message' => $result['error'] ?? __('Retry failed.'),
                ], 422);
            }
        } catch (\Exception $e) {
            $postingLog->update([
                'error_message' => $e->getMessage(),
            ]);

            return response()->json([
                'success' => false,
                'message' => __('Retry failed: ').$e->getMessage(),
            ], 500);
        }
    }

    /**
     * Execute retry based on source/target modules
     */
    protected function executeRetry(PostingLog $postingLog): array
    {
        // Handle AccountingCore syncs
        if ($postingLog->target_module === 'AccountingCore' && $postingLog->target_entity_type === 'transaction') {
            return $this->retryAccountingSync($postingLog);
        }

        // For other modules, mark as needing manual intervention
        return [
            'success' => false,
            'error' => __('Automatic retry not supported for this posting type. Please sync manually.'),
        ];
    }

    /**
     * Retry AccountingCore sync
     */
    protected function retryAccountingSync(PostingLog $postingLog): array
    {
        $syncService = app(\Modules\AccountingCore\App\Services\AccountingSyncService::class);

        if ($postingLog->source_entity_type === 'sales_order') {
            $order = \Modules\SystemCore\App\Models\CoreSalesOrder::find($postingLog->source_entity_id);
            if (! $order) {
                return ['success' => false, 'error' => __('Source sales order not found.')];
            }

            $transaction = $syncService->syncSalesOrder($order, true);

            return $transaction
                ? ['success' => true, 'target_id' => $transaction->id]
                : ['success' => false, 'error' => __('Sync returned null. Order may not be in paid/partial status.')];
        }

        if ($postingLog->source_entity_type === 'purchase_order') {
            $order = \Modules\SystemCore\App\Models\CorePurchaseOrder::find($postingLog->source_entity_id);
            if (! $order) {
                return ['success' => false, 'error' => __('Source purchase order not found.')];
            }

            $transaction = $syncService->syncPurchaseOrder($order, true);

            return $transaction
                ? ['success' => true, 'target_id' => $transaction->id]
                : ['success' => false, 'error' => __('Sync returned null. Order may not be in paid/partial status.')];
        }

        return ['success' => false, 'error' => __('Unknown source entity type.')];
    }

    /**
     * Get posting statistics
     */
    public function statistics(): JsonResponse
    {
        $stats = PostingLog::getStatistics();

        // Add module breakdown
        $stats['by_module'] = PostingLog::select('source_module', DB::raw('count(*) as count'))
            ->groupBy('source_module')
            ->get();

        // Add action breakdown
        $stats['by_action'] = PostingLog::select('action', DB::raw('count(*) as count'))
            ->groupBy('action')
            ->get();

        // Add recent activity (last 7 days)
        $stats['recent_by_day'] = PostingLog::select(
            DB::raw('DATE(posted_at) as date'),
            DB::raw('count(*) as total'),
            DB::raw('SUM(CASE WHEN status = "success" THEN 1 ELSE 0 END) as successful'),
            DB::raw('SUM(CASE WHEN status = "failed" THEN 1 ELSE 0 END) as failed')
        )
            ->where('posted_at', '>=', now()->subDays(7))
            ->groupBy(DB::raw('DATE(posted_at)'))
            ->orderBy('date', 'desc')
            ->get();

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